1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
extern crate winapi;
extern crate ws2_32;

use libc;
use std::io;

pub mod public {
    use libc;
    use super::winapi;
    use super::ws2_32;

    pub type CSocket = winapi::SOCKET;
    pub type Buf = *const libc::c_char;
    pub type MutBuf = *mut libc::c_char;
    pub type BufLen = libc::c_int;
    pub type CouldFail = libc::c_int;
    pub type SockLen = winapi::socklen_t;
    pub type SockAddr = winapi::SOCKADDR;
    pub type SockAddrIn = winapi::SOCKADDR_IN;
    pub type SockAddrIn6 = winapi::sockaddr_in6;
    pub type SockAddrStorage = winapi::SOCKADDR_STORAGE;
    pub type SockAddrFamily = winapi::ADDRESS_FAMILY;
    pub type SockAddrFamily6 = libc::c_short;
    pub type InAddr = winapi::in_addr;
    pub type In6Addr = winapi::in6_addr;

    pub const AF_INET: libc::c_int = winapi::AF_INET;
    pub const AF_INET6: libc::c_int = winapi::AF_INET6;
    pub const SOCK_RAW: libc::c_int = winapi::SOCK_RAW;

    pub const IPPROTO_IP: libc::c_int = winapi::IPPROTO_IP;
    pub const IP_HDRINCL: libc::c_int = winapi::IP_HDRINCL;

    pub const IFF_UP: libc::c_int = 0x00000001;
    pub const IFF_BROADCAST: libc::c_int = 0x00000002;
    pub const IFF_LOOPBACK: libc::c_int = 0x00000004;
    pub const IFF_POINTTOPOINT: libc::c_int = 0x00000008;
    pub const IFF_POINTOPOINT: libc::c_int = IFF_POINTTOPOINT;
    pub const IFF_MULTICAST: libc::c_int = 0x00000010;
    
    pub const INVALID_SOCKET: CSocket = winapi::INVALID_SOCKET;


    pub unsafe fn close(sock: CSocket) {
        let _ = ws2_32::closesocket(sock);
    }

    pub unsafe fn socket(af: libc::c_int, sock: libc::c_int, proto: libc::c_int) -> CSocket {
        ws2_32::socket(af, sock, proto)
    }

    pub unsafe fn setsockopt(socket: CSocket,
                            level: libc::c_int,
                            name: libc::c_int,
                            value: Buf,
                            option_len: SockLen)
        -> libc::c_int {
        ws2_32::setsockopt(socket, level, name, value, option_len)
    }
}

use self::public::*;

#[inline(always)]
pub fn ipv4_addr(addr: InAddr) -> u32 {
    (addr.S_un as u32).to_be()
}

#[inline(always)]
pub fn mk_inaddr(addr: u32) -> InAddr {
    InAddr { S_un: addr as winapi::ULONG }
}


pub unsafe fn sendto(socket: CSocket,
                     buf: Buf,
                     len: BufLen,
                     flags: libc::c_int,
                     to: *const SockAddr,
                     tolen: SockLen)
    -> CouldFail {
    ws2_32::sendto(socket, buf, len, flags, to, tolen)
}

pub unsafe fn recvfrom(socket: CSocket,
                       buf: MutBuf,
                       len: BufLen,
                       flags: libc::c_int,
                       addr: *mut SockAddr,
                       addrlen: *mut SockLen)
    -> CouldFail {
    ws2_32::recvfrom(socket, buf, len, flags, addr, addrlen)
}


#[inline]
pub fn retry<F>(f: &mut F) -> libc::c_int
    where F: FnMut() -> libc::c_int
{
    loop {
        let ret = f();
        if ret != -1 || errno() as isize != winapi::WSAEINTR as isize {
            return ret;
        }
    }
}


fn errno() -> i32 {
    io::Error::last_os_error().raw_os_error().unwrap()
}