1 /*-------------------------------------------------------------------------
4 * Microsoft Windows Win32 Socket Functions
6 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
9 * src/backend/port/win32/socket.c
11 *-------------------------------------------------------------------------
17 * Indicate if pgwin32_recv() should operate in non-blocking mode.
19 * Since the socket emulation layer always sets the actual socket to
20 * non-blocking mode in order to be able to deliver signals, we must
21 * specify this in a separate flag if we actually need non-blocking
24 * This flag changes the behaviour *globally* for all socket operations,
25 * so it should only be set for very short periods of time.
27 int pgwin32_noblock = 0;
37 * Blocking socket functions implemented so they listen on both
38 * the socket and the signal event, required for signal handling.
42 * Convert the last socket error code into errno
45 TranslateSocketError(void)
47 switch (WSAGetLastError())
49 case WSANOTINITIALISED:
53 case WSAESOCKTNOSUPPORT:
55 case WSAEINVALIDPROVIDER:
56 case WSAEINVALIDPROCTABLE:
69 case WSAEPROTONOSUPPORT:
71 errno = EPROTONOSUPPORT;
97 errno = ECONNREFUSED; /* ENOTCONN? */
101 (errmsg_internal("Unknown win32 socket error code: %i", WSAGetLastError())));
107 pgwin32_poll_signals(void)
109 if (UNBLOCKED_SIGNAL_QUEUE())
111 pgwin32_dispatch_queued_signals();
122 int typelen = sizeof(type);
124 if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &type, &typelen))
127 return (type == SOCK_DGRAM) ? 1 : 0;
131 pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
133 static HANDLE waitevent = INVALID_HANDLE_VALUE;
134 static SOCKET current_socket = -1;
135 static int isUDP = 0;
139 if (waitevent == INVALID_HANDLE_VALUE)
141 waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);
143 if (waitevent == INVALID_HANDLE_VALUE)
145 (errmsg_internal("Failed to create socket waiting event: %i", (int) GetLastError())));
147 else if (!ResetEvent(waitevent))
149 (errmsg_internal("Failed to reset socket waiting event: %i", (int) GetLastError())));
152 * make sure we don't multiplex this kernel event object with a different
153 * socket from a previous call
156 if (current_socket != s)
158 if (current_socket != -1)
159 WSAEventSelect(current_socket, waitevent, 0);
160 isUDP = isDataGram(s);
165 if (WSAEventSelect(s, waitevent, what) == SOCKET_ERROR)
167 TranslateSocketError();
171 events[0] = pgwin32_signal_event;
172 events[1] = waitevent;
175 * Just a workaround of unknown locking problem with writing in UDP socket
176 * under high load: Client's pgsql backend sleeps infinitely in
177 * WaitForMultipleObjectsEx, pgstat process sleeps in pgwin32_select().
178 * So, we will wait with small timeout(0.1 sec) and if sockect is still
179 * blocked, try WSASend (see comments in pgwin32_select) and wait again.
181 if ((what & FD_WRITE) && isUDP)
185 r = WaitForMultipleObjectsEx(2, events, FALSE, 100, TRUE);
187 if (r == WAIT_TIMEOUT)
196 r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
197 if (r == 0) /* Completed - means things are fine! */
199 else if (WSAGetLastError() != WSAEWOULDBLOCK)
201 TranslateSocketError();
210 r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
212 if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
214 pgwin32_dispatch_queued_signals();
218 if (r == WAIT_OBJECT_0 + 1)
220 if (r == WAIT_TIMEOUT)
223 (errmsg_internal("Bad return from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError())));
228 * Create a socket, setting it to overlapped and non-blocking
231 pgwin32_socket(int af, int type, int protocol)
234 unsigned long on = 1;
236 s = WSASocket(af, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
237 if (s == INVALID_SOCKET)
239 TranslateSocketError();
240 return INVALID_SOCKET;
243 if (ioctlsocket(s, FIONBIO, &on))
245 TranslateSocketError();
246 return INVALID_SOCKET;
255 pgwin32_accept(SOCKET s, struct sockaddr * addr, int *addrlen)
260 * Poll for signals, but don't return with EINTR, since we don't handle
263 pgwin32_poll_signals();
265 rs = WSAAccept(s, addr, addrlen, NULL, 0);
266 if (rs == INVALID_SOCKET)
268 TranslateSocketError();
269 return INVALID_SOCKET;
275 /* No signal delivery during connect. */
277 pgwin32_connect(SOCKET s, const struct sockaddr * addr, int addrlen)
281 r = WSAConnect(s, addr, addrlen, NULL, NULL, NULL, NULL);
285 if (WSAGetLastError() != WSAEWOULDBLOCK)
287 TranslateSocketError();
291 while (pgwin32_waitforsinglesocket(s, FD_CONNECT, INFINITE) == 0)
293 /* Loop endlessly as long as we are just delivering signals */
300 pgwin32_recv(SOCKET s, char *buf, int len, int f)
308 if (pgwin32_poll_signals())
314 r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
315 if (r != SOCKET_ERROR && b > 0)
316 /* Read succeeded right away */
319 if (r == SOCKET_ERROR &&
320 WSAGetLastError() != WSAEWOULDBLOCK)
322 TranslateSocketError();
329 * No data received, and we are in "emulated non-blocking mode", so
330 * return indicating that we'd block if we were to continue.
336 /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
338 for (n = 0; n < 5; n++)
340 if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT,
342 return -1; /* errno already set */
344 r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
345 if (r == SOCKET_ERROR)
347 if (WSAGetLastError() == WSAEWOULDBLOCK)
350 * There seem to be cases on win2k (at least) where WSARecv
351 * can return WSAEWOULDBLOCK even when
352 * pgwin32_waitforsinglesocket claims the socket is readable.
353 * In this case, just sleep for a moment and try again. We try
354 * up to 5 times - if it fails more than that it's not likely
360 TranslateSocketError();
366 (errmsg_internal("Failed to read from ready socket (after retries)")));
372 pgwin32_send(SOCKET s, char *buf, int len, int flags)
378 if (pgwin32_poll_signals())
385 * Readiness of socket to send data to UDP socket may be not true: socket
386 * can become busy again! So loop until send or error occurs.
390 r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
391 if (r != SOCKET_ERROR && b > 0)
392 /* Write succeeded right away */
395 if (r == SOCKET_ERROR &&
396 WSAGetLastError() != WSAEWOULDBLOCK)
398 TranslateSocketError();
402 /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
404 if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE, INFINITE) == 0)
413 * Wait for activity on one or more sockets.
414 * While waiting, allow signals to run
416 * NOTE! Currently does not implement exceptfds check,
417 * since it is not used in postgresql!
420 pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval * timeout)
422 WSAEVENT events[FD_SETSIZE * 2]; /* worst case is readfds totally
423 * different from writefds, so
424 * 2*FD_SETSIZE sockets */
425 SOCKET sockets[FD_SETSIZE * 2];
429 DWORD timeoutval = WSA_INFINITE;
434 Assert(exceptfds == NULL);
436 if (pgwin32_poll_signals())
439 FD_ZERO(&outreadfds);
440 FD_ZERO(&outwritefds);
443 * Write FDs are different in the way that it is only flagged by
444 * WSASelectEvent() if we have tried to write to them first. So try an
449 for (i = 0; i < writefds->fd_count; i++)
458 r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL);
459 if (r == 0) /* Completed - means things are fine! */
460 FD_SET(writefds->fd_array[i], &outwritefds);
463 { /* Not completed */
464 if (WSAGetLastError() != WSAEWOULDBLOCK)
467 * Not completed, and not just "would block", so an error
470 FD_SET(writefds->fd_array[i], &outwritefds);
473 if (outwritefds.fd_count > 0)
475 memcpy(writefds, &outwritefds, sizeof(fd_set));
478 return outwritefds.fd_count;
483 /* Now set up for an actual select */
487 /* timeoutval is in milliseconds */
488 timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
493 for (i = 0; i < readfds->fd_count; i++)
495 events[numevents] = WSACreateEvent();
496 sockets[numevents] = readfds->fd_array[i];
500 if (writefds != NULL)
502 for (i = 0; i < writefds->fd_count; i++)
505 !FD_ISSET(writefds->fd_array[i], readfds))
507 /* If the socket is not in the read list */
508 events[numevents] = WSACreateEvent();
509 sockets[numevents] = writefds->fd_array[i];
515 for (i = 0; i < numevents; i++)
519 if (readfds && FD_ISSET(sockets[i], readfds))
520 flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
522 if (writefds && FD_ISSET(sockets[i], writefds))
523 flags |= FD_WRITE | FD_CLOSE;
525 if (WSAEventSelect(sockets[i], events[i], flags) == SOCKET_ERROR)
527 TranslateSocketError();
528 for (i = 0; i < numevents; i++)
529 WSACloseEvent(events[i]);
534 events[numevents] = pgwin32_signal_event;
535 r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE);
536 if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents))
539 * We scan all events, even those not signalled, in case more than one
540 * event has been tagged but Wait.. can only return one.
542 WSANETWORKEVENTS resEvents;
544 for (i = 0; i < numevents; i++)
546 ZeroMemory(&resEvents, sizeof(resEvents));
547 if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) == SOCKET_ERROR)
549 (errmsg_internal("failed to enumerate network events: %i", (int) GetLastError())));
551 if (readfds && FD_ISSET(sockets[i], readfds))
553 if ((resEvents.lNetworkEvents & FD_READ) ||
554 (resEvents.lNetworkEvents & FD_ACCEPT) ||
555 (resEvents.lNetworkEvents & FD_CLOSE))
557 FD_SET(sockets[i], &outreadfds);
562 /* Write activity? */
563 if (writefds && FD_ISSET(sockets[i], writefds))
565 if ((resEvents.lNetworkEvents & FD_WRITE) ||
566 (resEvents.lNetworkEvents & FD_CLOSE))
568 FD_SET(sockets[i], &outwritefds);
576 /* Clean up all handles */
577 for (i = 0; i < numevents; i++)
579 WSAEventSelect(sockets[i], events[i], 0);
580 WSACloseEvent(events[i]);
583 if (r == WSA_WAIT_TIMEOUT)
592 if (r == WAIT_OBJECT_0 + numevents)
594 pgwin32_dispatch_queued_signals();
603 /* Overwrite socket sets with our resulting values */
605 memcpy(readfds, &outreadfds, sizeof(fd_set));
607 memcpy(writefds, &outwritefds, sizeof(fd_set));
613 * Return win32 error string, since strerror can't
614 * handle winsock codes
616 static char wserrbuf[256];
618 pgwin32_socket_strerror(int err)
620 static HANDLE handleDLL = INVALID_HANDLE_VALUE;
622 if (handleDLL == INVALID_HANDLE_VALUE)
624 handleDLL = LoadLibraryEx("netmsg.dll", NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
625 if (handleDLL == NULL)
627 (errmsg_internal("Failed to load netmsg.dll: %i", (int) GetLastError())));
630 ZeroMemory(&wserrbuf, sizeof(wserrbuf));
631 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,
634 MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
636 sizeof(wserrbuf) - 1,
639 /* Failed to get id */
640 sprintf(wserrbuf, "Unknown winsock error %i", err);