/* Written by Christopher E. Miller Placed into public domain. */ module std.c.windows.winsock; private import std.stdint; private import std.c.windows.windows; extern(Windows): alias int SOCKET; alias uint socklen_t; const SOCKET INVALID_SOCKET = cast(SOCKET)~0; const int SOCKET_ERROR = -1; const int WSADESCRIPTION_LEN = 256; const int WSASYS_STATUS_LEN = 128; struct WSADATA { WORD wVersion; WORD wHighVersion; char szDescription[WSADESCRIPTION_LEN + 1]; char szSystemStatus[WSASYS_STATUS_LEN + 1]; USHORT iMaxSockets; USHORT iMaxUdpDg; char* lpVendorInfo; } alias WSADATA* LPWSADATA; const int IOCPARM_MASK = 0x7F; const int IOC_IN = cast(int)0x80000000; const int FIONBIO = cast(int)(IOC_IN | ((UINT.sizeof & IOCPARM_MASK) << 16) | (102 << 8) | 126); int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData); int WSACleanup(); SOCKET socket(int af, int type, int protocol); int ioctlsocket(SOCKET s, int cmd, uint* argp); int bind(SOCKET s, sockaddr* name, socklen_t namelen); int connect(SOCKET s, sockaddr* name, socklen_t namelen); int listen(SOCKET s, int backlog); SOCKET accept(SOCKET s, sockaddr* addr, socklen_t* addrlen); int closesocket(SOCKET s); int shutdown(SOCKET s, int how); int getpeername(SOCKET s, sockaddr* name, socklen_t* namelen); int getsockname(SOCKET s, sockaddr* name, socklen_t* namelen); int send(SOCKET s, const(void)* buf, int len, int flags); int sendto(SOCKET s, const(void)* buf, int len, int flags, sockaddr* to, socklen_t tolen); int recv(SOCKET s, void* buf, int len, int flags); int recvfrom(SOCKET s, void* buf, int len, int flags, sockaddr* from, socklen_t* fromlen); int getsockopt(SOCKET s, int level, int optname, void* optval, socklen_t* optlen); int setsockopt(SOCKET s, int level, int optname, void* optval, socklen_t optlen); uint inet_addr(const char* cp); int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout); char* inet_ntoa(in_addr ina); hostent* gethostbyname(const char* name); hostent* gethostbyaddr(void* addr, int len, int type); protoent* getprotobyname(const char* name); protoent* getprotobynumber(int number); servent* getservbyname(const char* name, const char* proto); servent* getservbyport(int port, const char* proto); int gethostname(const char* name, int namelen); int getaddrinfo(char* nodename, char* servname, addrinfo* hints, addrinfo** res); void freeaddrinfo(addrinfo* ai); int getnameinfo(sockaddr* sa, socklen_t salen, char* host, DWORD hostlen, char* serv, DWORD servlen, int flags); enum: int { WSAEWOULDBLOCK = 10035, WSAEINTR = 10004, WSAHOST_NOT_FOUND = 11001, } int WSAGetLastError(); enum: int { AF_UNSPEC = 0, AF_UNIX = 1, AF_INET = 2, AF_IMPLINK = 3, AF_PUP = 4, AF_CHAOS = 5, AF_NS = 6, AF_IPX = AF_NS, AF_ISO = 7, AF_OSI = AF_ISO, AF_ECMA = 8, AF_DATAKIT = 9, AF_CCITT = 10, AF_SNA = 11, AF_DECnet = 12, AF_DLI = 13, AF_LAT = 14, AF_HYLINK = 15, AF_APPLETALK = 16, AF_NETBIOS = 17, AF_VOICEVIEW = 18, AF_FIREFOX = 19, AF_UNKNOWN1 = 20, AF_BAN = 21, AF_ATM = 22, AF_INET6 = 23, AF_CLUSTER = 24, AF_12844 = 25, AF_IRDA = 26, AF_NETDES = 28, AF_MAX = 29, PF_UNSPEC = AF_UNSPEC, PF_UNIX = AF_UNIX, PF_INET = AF_INET, PF_IMPLINK = AF_IMPLINK, PF_PUP = AF_PUP, PF_CHAOS = AF_CHAOS, PF_NS = AF_NS, PF_IPX = AF_IPX, PF_ISO = AF_ISO, PF_OSI = AF_OSI, PF_ECMA = AF_ECMA, PF_DATAKIT = AF_DATAKIT, PF_CCITT = AF_CCITT, PF_SNA = AF_SNA, PF_DECnet = AF_DECnet, PF_DLI = AF_DLI, PF_LAT = AF_LAT, PF_HYLINK = AF_HYLINK, PF_APPLETALK = AF_APPLETALK, PF_VOICEVIEW = AF_VOICEVIEW, PF_FIREFOX = AF_FIREFOX, PF_UNKNOWN1 = AF_UNKNOWN1, PF_BAN = AF_BAN, PF_INET6 = AF_INET6, PF_MAX = AF_MAX, } enum: int { SOL_SOCKET = 0xFFFF, } enum: int { SO_DEBUG = 0x0001, SO_ACCEPTCONN = 0x0002, SO_REUSEADDR = 0x0004, SO_KEEPALIVE = 0x0008, SO_DONTROUTE = 0x0010, SO_BROADCAST = 0x0020, SO_USELOOPBACK = 0x0040, SO_LINGER = 0x0080, SO_DONTLINGER = ~SO_LINGER, SO_OOBINLINE = 0x0100, SO_SNDBUF = 0x1001, SO_RCVBUF = 0x1002, SO_SNDLOWAT = 0x1003, SO_RCVLOWAT = 0x1004, SO_SNDTIMEO = 0x1005, SO_RCVTIMEO = 0x1006, SO_ERROR = 0x1007, SO_TYPE = 0x1008, SO_EXCLUSIVEADDRUSE = ~SO_REUSEADDR, TCP_NODELAY = 1, IP_MULTICAST_LOOP = 0x4, IP_ADD_MEMBERSHIP = 0x5, IP_DROP_MEMBERSHIP = 0x6, IPV6_UNICAST_HOPS = 4, IPV6_MULTICAST_IF = 9, IPV6_MULTICAST_HOPS = 10, IPV6_MULTICAST_LOOP = 11, IPV6_ADD_MEMBERSHIP = 12, IPV6_DROP_MEMBERSHIP = 13, IPV6_JOIN_GROUP = IPV6_ADD_MEMBERSHIP, IPV6_LEAVE_GROUP = IPV6_DROP_MEMBERSHIP, } const uint FD_SETSIZE = 64; struct fd_set { UINT fd_count; SOCKET[FD_SETSIZE] fd_array; } // Removes. void FD_CLR(SOCKET fd, fd_set* set) { uint c = set.fd_count; SOCKET* start = set.fd_array.ptr; SOCKET* stop = start + c; for(; start != stop; start++) { if(*start == fd) goto found; } return; //not found found: for(++start; start != stop; start++) { *(start - 1) = *start; } set.fd_count = c - 1; } // Tests. int FD_ISSET(SOCKET fd, fd_set* set) { SOCKET* start = set.fd_array.ptr; SOCKET* stop = start + set.fd_count; for(; start != stop; start++) { if(*start == fd) return true; } return false; } // Adds. void FD_SET(SOCKET fd, fd_set* set) { uint c = set.fd_count; set.fd_array.ptr[c] = fd; set.fd_count = c + 1; } // Resets to zero. void FD_ZERO(fd_set* set) { set.fd_count = 0; } struct linger { USHORT l_onoff; USHORT l_linger; } struct protoent { char* p_name; char** p_aliases; SHORT p_proto; } struct servent { char* s_name; char** s_aliases; SHORT s_port; char* s_proto; } /+ union in6_addr { private union _u_t { BYTE[16] Byte; WORD[8] Word; } _u_t u; } struct in_addr6 { BYTE[16] s6_addr; } +/ version(BigEndian) { uint16_t htons(uint16_t x) { return x; } uint32_t htonl(uint32_t x) { return x; } } else version(LittleEndian) { private import core.bitop; uint16_t htons(uint16_t x) { return cast(uint16_t)((x >> 8) | (x << 8)); } uint32_t htonl(uint32_t x) { return bswap(x); } } else { static assert(0); } uint16_t ntohs(uint16_t x) { return htons(x); } uint32_t ntohl(uint32_t x) { return htonl(x); } enum: int { SOCK_STREAM = 1, SOCK_DGRAM = 2, SOCK_RAW = 3, SOCK_RDM = 4, SOCK_SEQPACKET = 5, } enum: int { IPPROTO_IP = 0, IPPROTO_ICMP = 1, IPPROTO_IGMP = 2, IPPROTO_GGP = 3, IPPROTO_TCP = 6, IPPROTO_PUP = 12, IPPROTO_UDP = 17, IPPROTO_IDP = 22, IPPROTO_IPV6 = 41, IPPROTO_ND = 77, IPPROTO_RAW = 255, IPPROTO_MAX = 256, } enum: int { MSG_OOB = 0x1, MSG_PEEK = 0x2, MSG_DONTROUTE = 0x4, MSG_NOSIGNAL = 0x0, /// not supported on win32, would be 0x4000 if it was } enum: int { SD_RECEIVE = 0, SD_SEND = 1, SD_BOTH = 2, } enum: uint { INADDR_ANY = 0, INADDR_LOOPBACK = 0x7F000001, INADDR_BROADCAST = 0xFFFFFFFF, INADDR_NONE = 0xFFFFFFFF, ADDR_ANY = INADDR_ANY, } enum: int { AI_PASSIVE = 0x1, AI_CANONNAME = 0x2, AI_NUMERICHOST = 0x4, } struct timeval { int32_t tv_sec; int32_t tv_usec; } union in_addr { private union _S_un_t { private struct _S_un_b_t { uint8_t s_b1, s_b2, s_b3, s_b4; } _S_un_b_t S_un_b; private struct _S_un_w_t { uint16_t s_w1, s_w2; } _S_un_w_t S_un_w; uint32_t S_addr; } _S_un_t S_un; uint32_t s_addr; struct { uint8_t s_net, s_host; union { uint16_t s_imp; struct { uint8_t s_lh, s_impno; } } } } union in6_addr { private union _in6_u_t { uint8_t[16] u6_addr8; uint16_t[8] u6_addr16; uint32_t[4] u6_addr32; } _in6_u_t in6_u; uint8_t[16] s6_addr8; uint16_t[8] s6_addr16; uint32_t[4] s6_addr32; alias s6_addr8 s6_addr; } const in6_addr IN6ADDR_ANY = { s6_addr8: [0] }; const in6_addr IN6ADDR_LOOPBACK = { s6_addr8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] }; //alias IN6ADDR_ANY IN6ADDR_ANY_INIT; //alias IN6ADDR_LOOPBACK IN6ADDR_LOOPBACK_INIT; const uint INET_ADDRSTRLEN = 16; const uint INET6_ADDRSTRLEN = 46; struct sockaddr { int16_t sa_family; ubyte[14] sa_data; } struct sockaddr_in { int16_t sin_family = AF_INET; uint16_t sin_port; in_addr sin_addr; ubyte[8] sin_zero; } struct sockaddr_in6 { int16_t sin6_family = AF_INET6; uint16_t sin6_port; uint32_t sin6_flowinfo; in6_addr sin6_addr; uint32_t sin6_scope_id; } struct addrinfo { int32_t ai_flags; int32_t ai_family; int32_t ai_socktype; int32_t ai_protocol; size_t ai_addrlen; char* ai_canonname; sockaddr* ai_addr; addrinfo* ai_next; } struct hostent { char* h_name; char** h_aliases; int16_t h_addrtype; int16_t h_length; char** h_addr_list; char* h_addr() { return h_addr_list[0]; } }