10 // helper: convert WSAGetLastError() to an errno constant
11 static int wsa_errno(void)
13 switch(WSAGetLastError()) {
14 case WSAEACCES: return EACCES;
15 case WSAECONNRESET: return ECONNRESET;
16 case WSAEFAULT: return EFAULT;
17 case WSAEINPROGRESS: return EINPROGRESS;
18 case WSAEINTR: return EINTR;
19 case WSAEINVAL: return EINVAL;
20 case WSAEMSGSIZE: return EMSGSIZE;
21 case WSAENETDOWN: return ENETDOWN;
22 case WSAENETRESET: return ENETRESET;
23 case WSAENOBUFS: return ENOBUFS;
24 case WSAENOTCONN: return ENOTCONN;
25 case WSAENOTSOCK: return ENOTSOCK;
26 case WSAEOPNOTSUPP: return EOPNOTSUPP;
27 case WSAESHUTDOWN: return ESHUTDOWN;
28 case WSAETIMEDOUT: return ETIMEDOUT;
29 case WSAEWOULDBLOCK: return EWOULDBLOCK;
35 void winsock_init(void)
40 if((error = WSAStartup(MAKEWORD(2,2), &wsa)) != 0)
41 catta_log_error("WSAStartup() failed: %d", error);
44 void winsock_exit(void)
46 if(WSACleanup() == SOCKET_ERROR)
47 catta_log_warn("WSACleanup() failed: %d", WSAGetLastError());
50 char *errnostrsocket(void)
54 int err = WSAGetLastError();
55 int len = snprintf(buf, sizeof(buf), "[%i] ", err);
56 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
57 NULL, err, 0, buf + len, sizeof(buf) - len, NULL);
62 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
64 LPFN_WSARECVMSG WSARecvMsg = NULL;
65 GUID wsaid = WSAID_WSARECVMSG;
73 // size_t is larger than DWORD on 64bit
74 if(msg->msg_iovlen > UINT32_MAX) {
79 // obtain the function pointer to WSARecvMsg
80 r = WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
81 &wsaid, sizeof(wsaid), &WSARecvMsg, sizeof(WSARecvMsg),
83 if(r == SOCKET_ERROR) {
87 assert(b == sizeof(WSARecvMsg));
88 assert(WSARecvMsg != NULL);
90 // convert msghdr to WSAMSG structure
91 wsamsg.name = msg->msg_name;
92 wsamsg.namelen = msg->msg_namelen;
93 wsamsg.lpBuffers = malloc(msg->msg_iovlen * sizeof(WSABUF));
94 wsamsg.dwBufferCount = msg->msg_iovlen;
95 wsamsg.Control.len = msg->msg_controllen;
96 wsamsg.Control.buf = msg->msg_control;
97 wsamsg.dwFlags = (DWORD)flags;
99 // all flags that fit into dwFlags also fit through the flags argument
100 assert(sizeof(DWORD) <= sizeof(flags));
102 if(wsamsg.lpBuffers == NULL) {
103 // malloc will have set errno
107 // re-wrap iovecs as WSABUFs
108 for(i=0; i<msg->msg_iovlen; i++) {
110 if(msg->msg_iov[i].iov_len > ULONG_MAX) {
111 free(wsamsg.lpBuffers);
116 wsamsg.lpBuffers[i].len = msg->msg_iov[i].iov_len;
117 wsamsg.lpBuffers[i].buf = msg->msg_iov[i].iov_base;
120 r = WSARecvMsg(sockfd, &wsamsg, &bytesrcvd, NULL, NULL);
122 // the allocated WSABUF wrappers are no longer needed
123 free(wsamsg.lpBuffers);
125 if(r == SOCKET_ERROR) {
126 // XXX do we need special handling for ENETRESET, EMSGSIZE, ETIMEDOUT?
131 // DWORD has one bit more than ssize_t on 32bit
132 // XXX check for this condition before the WSARecvMsg call
133 if(bytesrcvd > SSIZE_MAX) {
138 // transfer results from wsamsg to msg
139 // NB: the data and control buffers are shared
140 msg->msg_controllen = wsamsg.Control.len;
141 msg->msg_flags = (int)wsamsg.dwFlags;
142 // all flags that fit into dwFlags also fit into msg_flags (see above)
147 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
149 LPFN_WSASENDMSG WSASendMsg = NULL;
150 GUID wsaid = WSAID_WSASENDMSG;
158 // size_t is larger than DWORD on 64bit
159 if(msg->msg_iovlen > UINT32_MAX) {
164 // obtain the function pointer to WSASendMsg
165 r = WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
166 &wsaid, sizeof(wsaid), &WSASendMsg, sizeof(WSASendMsg),
168 if(r == SOCKET_ERROR) {
172 assert(b == sizeof(WSASendMsg));
173 assert(WSASendMsg != NULL);
175 // convert msghdr to WSAMSG structure
176 wsamsg.name = msg->msg_name;
177 wsamsg.namelen = msg->msg_namelen;
178 wsamsg.lpBuffers = malloc(msg->msg_iovlen * sizeof(WSABUF));
179 wsamsg.dwBufferCount = msg->msg_iovlen;
180 wsamsg.Control.len = msg->msg_controllen;
181 wsamsg.Control.buf = msg->msg_control;
182 wsamsg.dwFlags = 0; // ignored
184 if(wsamsg.lpBuffers == NULL) {
185 // malloc will have set errno
189 // re-wrap iovecs as WSABUFs
190 for(i=0; i<msg->msg_iovlen; i++) {
192 if(msg->msg_iov[i].iov_len > ULONG_MAX) {
193 free(wsamsg.lpBuffers);
198 wsamsg.lpBuffers[i].len = msg->msg_iov[i].iov_len;
199 wsamsg.lpBuffers[i].buf = msg->msg_iov[i].iov_base;
202 r = WSASendMsg(sockfd, &wsamsg, flags, &bytessent, NULL, NULL);
204 // the allocated WSABUF wrappers are no longer needed
205 free(wsamsg.lpBuffers);
207 if(r == SOCKET_ERROR) {
208 // XXX do we need special handling for ENETRESET, ETIMEDOUT?
213 // DWORD has one bit more than ssize_t on 32bit
214 // XXX check for this condition before sending anything
215 if(bytessent > SSIZE_MAX) {
223 int ioctl(int d, unsigned long request, int *p)
227 if(ioctlsocket(d, request, &arg) == SOCKET_ERROR) {
241 int pipe(int pipefd[2])
243 int lsock = (int)INVALID_SOCKET;
244 struct sockaddr_in laddr;
245 socklen_t laddrlen = sizeof(laddr);
247 pipefd[0] = pipefd[1] = (int)INVALID_SOCKET;
249 // bind a listening socket to a TCP port on localhost
250 laddr.sin_family = AF_INET;
252 laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
253 if((lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
255 if(bind(lsock, (struct sockaddr *)&laddr, sizeof(laddr)) == SOCKET_ERROR)
257 if(listen(lsock, 1) == SOCKET_ERROR)
260 // determine which address (i.e. port) we got bound to
261 if(getsockname(lsock, (struct sockaddr *)&laddr, &laddrlen) == SOCKET_ERROR)
263 assert(laddrlen == sizeof(laddr));
264 laddr.sin_family = AF_INET;
265 laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
267 // connect and accept
268 if((pipefd[0] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
270 if(connect(pipefd[0], (const struct sockaddr *)&laddr, sizeof(laddr)) == SOCKET_ERROR)
272 if((pipefd[1] = accept(lsock, NULL, NULL)) == SOCKET_ERROR)
275 // close the listener
282 closesocket(pipefd[0]);
287 int uname(struct utsname *buf)
290 const char *arch = "unknown";
292 memset(buf, 0, sizeof(struct utsname));
295 strncpy(buf->sysname, "Windows", sizeof(buf->sysname)-1);
296 strncpy(buf->release, "unknown", sizeof(buf->sysname)-1); // we don't need it
297 strncpy(buf->version, "unknown", sizeof(buf->sysname)-1); // we don't need it
299 // computer (node) name
300 DWORD nodename_size = sizeof(buf->nodename)-1;
301 if(GetComputerName(buf->nodename, &nodename_size) == 0) {
308 switch(si.wProcessorArchitecture) {
309 case PROCESSOR_ARCHITECTURE_AMD64: arch = "amd64"; break;
310 case PROCESSOR_ARCHITECTURE_ARM: arch = "arm"; break;
311 case PROCESSOR_ARCHITECTURE_IA64: arch = "ia64"; break;
312 case PROCESSOR_ARCHITECTURE_INTEL: arch = "x86"; break;
313 default: arch = "unknown";
315 strncpy(buf->machine, arch, sizeof(buf->machine)-1);