1 /*-------------------------------------------------------------------------
4 * Microsoft Windows Win32 Socket Functions
6 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
9 * src/backend/port/win32/socket.c
11 *-------------------------------------------------------------------------
17 * Indicate if pgwin32_recv() and pgwin32_send() should operate
18 * in non-blocking mode.
20 * Since the socket emulation layer always sets the actual socket to
21 * non-blocking mode in order to be able to deliver signals, we must
22 * specify this in a separate flag if we actually need non-blocking
25 * This flag changes the behaviour *globally* for all socket operations,
26 * so it should only be set for very short periods of time.
28 int pgwin32_noblock = 0;
38 * Blocking socket functions implemented so they listen on both
39 * the socket and the signal event, required for signal handling.
43 * Convert the last socket error code into errno
46 TranslateSocketError(void)
48 switch (WSAGetLastError())
50 case WSANOTINITIALISED:
54 case WSAESOCKTNOSUPPORT:
56 case WSAEINVALIDPROVIDER:
57 case WSAEINVALIDPROCTABLE:
70 case WSAEPROTONOSUPPORT:
72 errno = EPROTONOSUPPORT;
98 errno = ECONNREFUSED; /* ENOTCONN? */
102 (errmsg_internal("unrecognized win32 socket error code: %d", WSAGetLastError())));
108 pgwin32_poll_signals(void)
110 if (UNBLOCKED_SIGNAL_QUEUE())
112 pgwin32_dispatch_queued_signals();
123 int typelen = sizeof(type);
125 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &type, &typelen))
128 return (type == SOCK_DGRAM) ? 1 : 0;
132 pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
134 static HANDLE waitevent = INVALID_HANDLE_VALUE;
135 static SOCKET current_socket = -1;
136 static int isUDP = 0;
140 /* Create an event object just once and use it on all future calls */
141 if (waitevent == INVALID_HANDLE_VALUE)
143 waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);
145 if (waitevent == INVALID_HANDLE_VALUE)
147 (errmsg_internal("could not create socket waiting event: error code %lu", GetLastError())));
149 else if (!ResetEvent(waitevent))
151 (errmsg_internal("could not reset socket waiting event: error code %lu", GetLastError())));
154 * Track whether socket is UDP or not. (NB: most likely, this is both
155 * useless and wrong; there is no reason to think that the behavior of
156 * WSAEventSelect is different for TCP and UDP.)
158 if (current_socket != s)
159 isUDP = isDataGram(s);
163 * Attach event to socket. NOTE: we must detach it again before returning,
164 * since other bits of code may try to attach other events to the socket.
166 if (WSAEventSelect(s, waitevent, what) != 0)
168 TranslateSocketError();
172 events[0] = pgwin32_signal_event;
173 events[1] = waitevent;
176 * Just a workaround of unknown locking problem with writing in UDP socket
177 * under high load: Client's pgsql backend sleeps infinitely in
178 * WaitForMultipleObjectsEx, pgstat process sleeps in pgwin32_select().
179 * So, we will wait with small timeout(0.1 sec) and if sockect is still
180 * blocked, try WSASend (see comments in pgwin32_select) and wait again.
182 if ((what & FD_WRITE) && isUDP)
186 r = WaitForMultipleObjectsEx(2, events, FALSE, 100, TRUE);
188 if (r == WAIT_TIMEOUT)
197 r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
198 if (r == 0) /* Completed - means things are fine! */
200 WSAEventSelect(s, NULL, 0);
203 else if (WSAGetLastError() != WSAEWOULDBLOCK)
205 TranslateSocketError();
206 WSAEventSelect(s, NULL, 0);
215 r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
217 WSAEventSelect(s, NULL, 0);
219 if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
221 pgwin32_dispatch_queued_signals();
225 if (r == WAIT_OBJECT_0 + 1)
227 if (r == WAIT_TIMEOUT)
233 (errmsg_internal("unrecognized return value from WaitForMultipleObjects: %d (error code %lu)", r, GetLastError())));
238 * Create a socket, setting it to overlapped and non-blocking
241 pgwin32_socket(int af, int type, int protocol)
244 unsigned long on = 1;
246 s = WSASocket(af, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
247 if (s == INVALID_SOCKET)
249 TranslateSocketError();
250 return INVALID_SOCKET;
253 if (ioctlsocket(s, FIONBIO, &on))
255 TranslateSocketError();
256 return INVALID_SOCKET;
265 pgwin32_accept(SOCKET s, struct sockaddr * addr, int *addrlen)
270 * Poll for signals, but don't return with EINTR, since we don't handle
273 pgwin32_poll_signals();
275 rs = WSAAccept(s, addr, addrlen, NULL, 0);
276 if (rs == INVALID_SOCKET)
278 TranslateSocketError();
279 return INVALID_SOCKET;
285 /* No signal delivery during connect. */
287 pgwin32_connect(SOCKET s, const struct sockaddr * addr, int addrlen)
291 r = WSAConnect(s, addr, addrlen, NULL, NULL, NULL, NULL);
295 if (WSAGetLastError() != WSAEWOULDBLOCK)
297 TranslateSocketError();
301 while (pgwin32_waitforsinglesocket(s, FD_CONNECT, INFINITE) == 0)
303 /* Loop endlessly as long as we are just delivering signals */
310 pgwin32_recv(SOCKET s, char *buf, int len, int f)
318 if (pgwin32_poll_signals())
324 r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
325 if (r != SOCKET_ERROR && b > 0)
326 /* Read succeeded right away */
329 if (r == SOCKET_ERROR &&
330 WSAGetLastError() != WSAEWOULDBLOCK)
332 TranslateSocketError();
339 * No data received, and we are in "emulated non-blocking mode", so
340 * return indicating that we'd block if we were to continue.
346 /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
348 for (n = 0; n < 5; n++)
350 if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT,
352 return -1; /* errno already set */
354 r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
355 if (r == SOCKET_ERROR)
357 if (WSAGetLastError() == WSAEWOULDBLOCK)
360 * There seem to be cases on win2k (at least) where WSARecv
361 * can return WSAEWOULDBLOCK even when
362 * pgwin32_waitforsinglesocket claims the socket is readable.
363 * In this case, just sleep for a moment and try again. We try
364 * up to 5 times - if it fails more than that it's not likely
370 TranslateSocketError();
376 (errmsg_internal("could not read from ready socket (after retries)")));
382 * The second argument to send() is defined by SUS to be a "const void *"
383 * and so we use the same signature here to keep compilers happy when
386 * But the buf member of a WSABUF struct is defined as "char *", so we cast
387 * the second argument to that here when assigning it, also to keep compilers
392 pgwin32_send(SOCKET s, const void *buf, int len, int flags)
398 if (pgwin32_poll_signals())
402 wbuf.buf = (char *) buf;
405 * Readiness of socket to send data to UDP socket may be not true: socket
406 * can become busy again! So loop until send or error occurs.
410 r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
411 if (r != SOCKET_ERROR && b > 0)
412 /* Write succeeded right away */
415 if (r == SOCKET_ERROR &&
416 WSAGetLastError() != WSAEWOULDBLOCK)
418 TranslateSocketError();
425 * No data sent, and we are in "emulated non-blocking mode", so
426 * return indicating that we'd block if we were to continue.
432 /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
434 if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE, INFINITE) == 0)
443 * Wait for activity on one or more sockets.
444 * While waiting, allow signals to run
446 * NOTE! Currently does not implement exceptfds check,
447 * since it is not used in postgresql!
450 pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval * timeout)
452 WSAEVENT events[FD_SETSIZE * 2]; /* worst case is readfds totally
453 * different from writefds, so
454 * 2*FD_SETSIZE sockets */
455 SOCKET sockets[FD_SETSIZE * 2];
459 DWORD timeoutval = WSA_INFINITE;
464 Assert(exceptfds == NULL);
466 if (pgwin32_poll_signals())
469 FD_ZERO(&outreadfds);
470 FD_ZERO(&outwritefds);
473 * Write FDs are different in the way that it is only flagged by
474 * WSASelectEvent() if we have tried to write to them first. So try an
479 for (i = 0; i < writefds->fd_count; i++)
488 r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL);
489 if (r == 0) /* Completed - means things are fine! */
490 FD_SET(writefds->fd_array[i], &outwritefds);
493 { /* Not completed */
494 if (WSAGetLastError() != WSAEWOULDBLOCK)
497 * Not completed, and not just "would block", so an error
500 FD_SET(writefds->fd_array[i], &outwritefds);
503 if (outwritefds.fd_count > 0)
505 memcpy(writefds, &outwritefds, sizeof(fd_set));
508 return outwritefds.fd_count;
513 /* Now set up for an actual select */
517 /* timeoutval is in milliseconds */
518 timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
523 for (i = 0; i < readfds->fd_count; i++)
525 events[numevents] = WSACreateEvent();
526 sockets[numevents] = readfds->fd_array[i];
530 if (writefds != NULL)
532 for (i = 0; i < writefds->fd_count; i++)
535 !FD_ISSET(writefds->fd_array[i], readfds))
537 /* If the socket is not in the read list */
538 events[numevents] = WSACreateEvent();
539 sockets[numevents] = writefds->fd_array[i];
545 for (i = 0; i < numevents; i++)
549 if (readfds && FD_ISSET(sockets[i], readfds))
550 flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
552 if (writefds && FD_ISSET(sockets[i], writefds))
553 flags |= FD_WRITE | FD_CLOSE;
555 if (WSAEventSelect(sockets[i], events[i], flags) != 0)
557 TranslateSocketError();
558 /* release already-assigned event objects */
560 WSAEventSelect(sockets[i], NULL, 0);
561 for (i = 0; i < numevents; i++)
562 WSACloseEvent(events[i]);
567 events[numevents] = pgwin32_signal_event;
568 r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE);
569 if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents))
572 * We scan all events, even those not signalled, in case more than one
573 * event has been tagged but Wait.. can only return one.
575 WSANETWORKEVENTS resEvents;
577 for (i = 0; i < numevents; i++)
579 ZeroMemory(&resEvents, sizeof(resEvents));
580 if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) != 0)
581 elog(ERROR, "failed to enumerate network events: error code %u",
584 if (readfds && FD_ISSET(sockets[i], readfds))
586 if ((resEvents.lNetworkEvents & FD_READ) ||
587 (resEvents.lNetworkEvents & FD_ACCEPT) ||
588 (resEvents.lNetworkEvents & FD_CLOSE))
590 FD_SET(sockets[i], &outreadfds);
595 /* Write activity? */
596 if (writefds && FD_ISSET(sockets[i], writefds))
598 if ((resEvents.lNetworkEvents & FD_WRITE) ||
599 (resEvents.lNetworkEvents & FD_CLOSE))
601 FD_SET(sockets[i], &outwritefds);
609 /* Clean up all the event objects */
610 for (i = 0; i < numevents; i++)
612 WSAEventSelect(sockets[i], NULL, 0);
613 WSACloseEvent(events[i]);
616 if (r == WSA_WAIT_TIMEOUT)
625 if (r == WAIT_OBJECT_0 + numevents)
627 pgwin32_dispatch_queued_signals();
636 /* Overwrite socket sets with our resulting values */
638 memcpy(readfds, &outreadfds, sizeof(fd_set));
640 memcpy(writefds, &outwritefds, sizeof(fd_set));
646 * Return win32 error string, since strerror can't
647 * handle winsock codes
649 static char wserrbuf[256];
651 pgwin32_socket_strerror(int err)
653 static HANDLE handleDLL = INVALID_HANDLE_VALUE;
655 if (handleDLL == INVALID_HANDLE_VALUE)
657 handleDLL = LoadLibraryEx("netmsg.dll", NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
658 if (handleDLL == NULL)
660 (errmsg_internal("could not load netmsg.dll: error code %lu", GetLastError())));
663 ZeroMemory(&wserrbuf, sizeof(wserrbuf));
664 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,
667 MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
669 sizeof(wserrbuf) - 1,
672 /* Failed to get id */
673 sprintf(wserrbuf, "unrecognized winsock error %d", err);