blob: 55a45be85bf211d9538481ed4d8933c99be906ed [file] [log] [blame]
/*
Written by Christopher E. Miller
$(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
*/
module core.sys.windows.winsock2;
version (Windows):
@system:
pragma(lib, "ws2_32");
extern(Windows):
nothrow:
alias SOCKET = size_t;
alias socklen_t = int;
enum SOCKET INVALID_SOCKET = cast(SOCKET)~0;
enum int SOCKET_ERROR = -1;
enum WSADESCRIPTION_LEN = 256;
enum WSASYS_STATUS_LEN = 128;
struct WSADATA
{
ushort wVersion;
ushort wHighVersion;
char[WSADESCRIPTION_LEN + 1] szDescription = 0;
char[WSASYS_STATUS_LEN + 1] szSystemStatus = 0;
ushort iMaxSockets;
ushort iMaxUdpDg;
char* lpVendorInfo;
}
alias LPWSADATA = WSADATA*;
enum int IOCPARM_MASK = 0x7F;
enum int IOC_IN = cast(int)0x80000000;
enum int FIONBIO = cast(int)(IOC_IN | ((uint.sizeof & IOCPARM_MASK) << 16) | (102 << 8) | 126);
enum NI_MAXHOST = 1025;
enum NI_MAXSERV = 32;
@nogc
{
int WSAStartup(ushort 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, const(sockaddr)* name, socklen_t namelen);
int connect(SOCKET s, const(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, const(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, const(void)* optval, socklen_t optlen);
uint inet_addr(const char* cp);
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, const(timeval)* timeout);
char* inet_ntoa(in_addr ina);
hostent* gethostbyname(const char* name);
hostent* gethostbyaddr(const(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);
}
enum: int
{
NI_NOFQDN = 0x01,
NI_NUMERICHOST = 0x02,
NI_NAMEREQD = 0x04,
NI_NUMERICSERV = 0x08,
NI_DGRAM = 0x10,
}
@nogc
{
int gethostname(const char* name, int namelen);
int getaddrinfo(const(char)* nodename, const(char)* servname, const(addrinfo)* hints, addrinfo** res);
void freeaddrinfo(addrinfo* ai);
int getnameinfo(const(sockaddr)* sa, socklen_t salen, char* host, uint hostlen, char* serv, uint servlen, int flags);
}
enum WSABASEERR = 10000;
enum: int
{
/*
* Windows Sockets definitions of regular Microsoft C error constants
*/
WSAEINTR = (WSABASEERR+4),
WSAEBADF = (WSABASEERR+9),
WSAEACCES = (WSABASEERR+13),
WSAEFAULT = (WSABASEERR+14),
WSAEINVAL = (WSABASEERR+22),
WSAEMFILE = (WSABASEERR+24),
/*
* Windows Sockets definitions of regular Berkeley error constants
*/
WSAEWOULDBLOCK = (WSABASEERR+35),
WSAEINPROGRESS = (WSABASEERR+36),
WSAEALREADY = (WSABASEERR+37),
WSAENOTSOCK = (WSABASEERR+38),
WSAEDESTADDRREQ = (WSABASEERR+39),
WSAEMSGSIZE = (WSABASEERR+40),
WSAEPROTOTYPE = (WSABASEERR+41),
WSAENOPROTOOPT = (WSABASEERR+42),
WSAEPROTONOSUPPORT = (WSABASEERR+43),
WSAESOCKTNOSUPPORT = (WSABASEERR+44),
WSAEOPNOTSUPP = (WSABASEERR+45),
WSAEPFNOSUPPORT = (WSABASEERR+46),
WSAEAFNOSUPPORT = (WSABASEERR+47),
WSAEADDRINUSE = (WSABASEERR+48),
WSAEADDRNOTAVAIL = (WSABASEERR+49),
WSAENETDOWN = (WSABASEERR+50),
WSAENETUNREACH = (WSABASEERR+51),
WSAENETRESET = (WSABASEERR+52),
WSAECONNABORTED = (WSABASEERR+53),
WSAECONNRESET = (WSABASEERR+54),
WSAENOBUFS = (WSABASEERR+55),
WSAEISCONN = (WSABASEERR+56),
WSAENOTCONN = (WSABASEERR+57),
WSAESHUTDOWN = (WSABASEERR+58),
WSAETOOMANYREFS = (WSABASEERR+59),
WSAETIMEDOUT = (WSABASEERR+60),
WSAECONNREFUSED = (WSABASEERR+61),
WSAELOOP = (WSABASEERR+62),
WSAENAMETOOLONG = (WSABASEERR+63),
WSAEHOSTDOWN = (WSABASEERR+64),
WSAEHOSTUNREACH = (WSABASEERR+65),
WSAENOTEMPTY = (WSABASEERR+66),
WSAEPROCLIM = (WSABASEERR+67),
WSAEUSERS = (WSABASEERR+68),
WSAEDQUOT = (WSABASEERR+69),
WSAESTALE = (WSABASEERR+70),
WSAEREMOTE = (WSABASEERR+71),
/*
* Extended Windows Sockets error constant definitions
*/
WSASYSNOTREADY = (WSABASEERR+91),
WSAVERNOTSUPPORTED = (WSABASEERR+92),
WSANOTINITIALISED = (WSABASEERR+93),
/* Authoritative Answer: Host not found */
WSAHOST_NOT_FOUND = (WSABASEERR+1001),
HOST_NOT_FOUND = WSAHOST_NOT_FOUND,
/* Non-Authoritative: Host not found, or SERVERFAIL */
WSATRY_AGAIN = (WSABASEERR+1002),
TRY_AGAIN = WSATRY_AGAIN,
/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
WSANO_RECOVERY = (WSABASEERR+1003),
NO_RECOVERY = WSANO_RECOVERY,
/* Valid name, no data record of requested type */
WSANO_DATA = (WSABASEERR+1004),
NO_DATA = WSANO_DATA,
/* no address, look for MX record */
WSANO_ADDRESS = WSANO_DATA,
NO_ADDRESS = WSANO_ADDRESS
}
/*
* Windows Sockets errors redefined as regular Berkeley error constants
*/
enum: int
{
EWOULDBLOCK = WSAEWOULDBLOCK,
EINPROGRESS = WSAEINPROGRESS,
EALREADY = WSAEALREADY,
ENOTSOCK = WSAENOTSOCK,
EDESTADDRREQ = WSAEDESTADDRREQ,
EMSGSIZE = WSAEMSGSIZE,
EPROTOTYPE = WSAEPROTOTYPE,
ENOPROTOOPT = WSAENOPROTOOPT,
EPROTONOSUPPORT = WSAEPROTONOSUPPORT,
ESOCKTNOSUPPORT = WSAESOCKTNOSUPPORT,
EOPNOTSUPP = WSAEOPNOTSUPP,
EPFNOSUPPORT = WSAEPFNOSUPPORT,
EAFNOSUPPORT = WSAEAFNOSUPPORT,
EADDRINUSE = WSAEADDRINUSE,
EADDRNOTAVAIL = WSAEADDRNOTAVAIL,
ENETDOWN = WSAENETDOWN,
ENETUNREACH = WSAENETUNREACH,
ENETRESET = WSAENETRESET,
ECONNABORTED = WSAECONNABORTED,
ECONNRESET = WSAECONNRESET,
ENOBUFS = WSAENOBUFS,
EISCONN = WSAEISCONN,
ENOTCONN = WSAENOTCONN,
ESHUTDOWN = WSAESHUTDOWN,
ETOOMANYREFS = WSAETOOMANYREFS,
ETIMEDOUT = WSAETIMEDOUT,
ECONNREFUSED = WSAECONNREFUSED,
ELOOP = WSAELOOP,
ENAMETOOLONG = WSAENAMETOOLONG,
EHOSTDOWN = WSAEHOSTDOWN,
EHOSTUNREACH = WSAEHOSTUNREACH,
ENOTEMPTY = WSAENOTEMPTY,
EPROCLIM = WSAEPROCLIM,
EUSERS = WSAEUSERS,
EDQUOT = WSAEDQUOT,
ESTALE = WSAESTALE,
EREMOTE = WSAEREMOTE
}
enum: int
{
EAI_NONAME = WSAHOST_NOT_FOUND,
}
int WSAGetLastError() @trusted @nogc;
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_OPTIONS = 1,
IP_HDRINCL = 2,
IP_TOS = 3,
IP_TTL = 4,
IP_MULTICAST_IF = 9,
IP_MULTICAST_TTL = 10,
IP_MULTICAST_LOOP = 11,
IP_ADD_MEMBERSHIP = 12,
IP_DROP_MEMBERSHIP = 13,
IP_DONTFRAGMENT = 14,
IP_ADD_SOURCE_MEMBERSHIP = 15,
IP_DROP_SOURCE_MEMBERSHIP = 16,
IP_BLOCK_SOURCE = 17,
IP_UNBLOCK_SOURCE = 18,
IP_PKTINFO = 19,
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,
IPV6_V6ONLY = 27,
}
/// Default FD_SETSIZE value.
/// In C/C++, it is redefinable by #define-ing the macro before #include-ing
/// winsock.h. In D, use the $(D FD_CREATE) function to allocate a $(D fd_set)
/// of an arbitrary size.
enum int FD_SETSIZE = 64;
struct fd_set_custom(uint SETSIZE)
{
uint fd_count;
SOCKET[SETSIZE] fd_array;
}
alias fd_set = fd_set_custom!FD_SETSIZE;
// Removes.
void FD_CLR(SOCKET fd, fd_set* set) pure @nogc
{
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, const(fd_set)* set) pure @nogc
{
const(SOCKET)* start = set.fd_array.ptr;
const(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) pure @nogc
{
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) pure @nogc
{
set.fd_count = 0;
}
/// Creates a new $(D fd_set) with the specified capacity.
fd_set* FD_CREATE(uint capacity) pure
{
// Take into account alignment (SOCKET may be 64-bit and require 64-bit alignment on 64-bit systems)
size_t size = (fd_set_custom!1).sizeof - SOCKET.sizeof + (SOCKET.sizeof * capacity);
auto data = new ubyte[size];
auto set = cast(fd_set*)data.ptr;
FD_ZERO(set);
return set;
}
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;
version (Win64)
{
char* s_proto;
short s_port;
}
else version (Win32)
{
short s_port;
char* s_proto;
}
}
/+
union in6_addr
{
private union _u_t
{
ubyte[16] Byte;
ushort[8] Word;
}
_u_t u;
}
struct in_addr6
{
ubyte[16] s6_addr;
}
+/
@safe pure @nogc
{
ushort htons(ushort x);
uint htonl(uint x);
ushort ntohs(ushort x);
uint ntohl(uint 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
}
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,
AI_ADDRCONFIG = 0x0400,
AI_NON_AUTHORITATIVE = 0x04000,
AI_SECURE = 0x08000,
AI_RETURN_PREFERRED_NAMES = 0x010000,
}
struct timeval
{
int tv_sec;
int tv_usec;
}
union in_addr
{
private union _S_un_t
{
private struct _S_un_b_t
{
ubyte s_b1, s_b2, s_b3, s_b4;
}
_S_un_b_t S_un_b;
private struct _S_un_w_t
{
ushort s_w1, s_w2;
}
_S_un_w_t S_un_w;
uint S_addr;
}
_S_un_t S_un;
uint s_addr;
struct
{
ubyte s_net, s_host;
union
{
ushort s_imp;
struct
{
ubyte s_lh, s_impno;
}
}
}
}
union in6_addr
{
private union _in6_u_t
{
ubyte[16] u6_addr8;
ushort[8] u6_addr16;
uint[4] u6_addr32;
}
_in6_u_t in6_u;
ubyte[16] s6_addr8;
ushort[8] s6_addr16;
uint[4] s6_addr32;
alias s6_addr = s6_addr8;
}
enum in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
enum 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_INIT = IN6ADDR_ANY;
//alias IN6ADDR_LOOPBACK_INIT = IN6ADDR_LOOPBACK;
enum int INET_ADDRSTRLEN = 16;
enum int INET6_ADDRSTRLEN = 46;
struct sockaddr
{
short sa_family;
ubyte[14] sa_data;
}
alias sockaddr SOCKADDR;
alias SOCKADDR* PSOCKADDR, LPSOCKADDR;
struct sockaddr_storage
{
short ss_family;
char[6] __ss_pad1 = void;
long __ss_align;
char[112] __ss_pad2 = void;
}
alias sockaddr_storage SOCKADDR_STORAGE;
alias SOCKADDR_STORAGE* PSOCKADDR_STORAGE;
struct sockaddr_in
{
short sin_family = AF_INET;
ushort sin_port;
in_addr sin_addr;
ubyte[8] sin_zero;
}
alias sockaddr_in SOCKADDR_IN;
alias SOCKADDR_IN* PSOCKADDR_IN, LPSOCKADDR_IN;
struct sockaddr_in6
{
short sin6_family = AF_INET6;
ushort sin6_port;
uint sin6_flowinfo;
in6_addr sin6_addr;
uint sin6_scope_id;
}
struct addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
char* ai_canonname;
sockaddr* ai_addr;
addrinfo* ai_next;
}
struct hostent
{
char* h_name;
char** h_aliases;
short h_addrtype;
short h_length;
char** h_addr_list;
char* h_addr() @safe pure nothrow @nogc
{
return h_addr_list[0];
}
}
// Note: These are Winsock2!!
struct WSAOVERLAPPED;
alias LPWSAOVERLAPPED = WSAOVERLAPPED*;
alias LPWSAOVERLAPPED_COMPLETION_ROUTINE = void function(uint, uint, LPWSAOVERLAPPED, uint);
int WSAIoctl(SOCKET s, uint dwIoControlCode,
void* lpvInBuffer, uint cbInBuffer,
void* lpvOutBuffer, uint cbOutBuffer,
uint* lpcbBytesReturned,
LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
enum IOC_VENDOR = 0x18000000;
enum SIO_KEEPALIVE_VALS = IOC_IN | IOC_VENDOR | 4;
/* Argument structure for SIO_KEEPALIVE_VALS */
struct tcp_keepalive
{
uint onoff;
uint keepalivetime;
uint keepaliveinterval;
}