OSDN Git Service

8.4 pgindent run, with new combined Linux/FreeBSD/MinGW typedef list
[pg-rex/syncrep.git] / src / backend / port / win32 / socket.c
1 /*-------------------------------------------------------------------------
2  *
3  * socket.c
4  *        Microsoft Windows Win32 Socket Functions
5  *
6  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  *        $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.22 2009/06/11 14:49:00 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #include "postgres.h"
15
16 #undef socket
17 #undef accept
18 #undef connect
19 #undef select
20 #undef recv
21 #undef send
22
23 /*
24  * Blocking socket functions implemented so they listen on both
25  * the socket and the signal event, required for signal handling.
26  */
27
28 /*
29  * Convert the last socket error code into errno
30  */
31 static void
32 TranslateSocketError(void)
33 {
34         switch (WSAGetLastError())
35         {
36                 case WSANOTINITIALISED:
37                 case WSAENETDOWN:
38                 case WSAEINPROGRESS:
39                 case WSAEINVAL:
40                 case WSAESOCKTNOSUPPORT:
41                 case WSAEFAULT:
42                 case WSAEINVALIDPROVIDER:
43                 case WSAEINVALIDPROCTABLE:
44                 case WSAEMSGSIZE:
45                         errno = EINVAL;
46                         break;
47                 case WSAEAFNOSUPPORT:
48                         errno = EAFNOSUPPORT;
49                         break;
50                 case WSAEMFILE:
51                         errno = EMFILE;
52                         break;
53                 case WSAENOBUFS:
54                         errno = ENOBUFS;
55                         break;
56                 case WSAEPROTONOSUPPORT:
57                 case WSAEPROTOTYPE:
58                         errno = EPROTONOSUPPORT;
59                         break;
60                 case WSAECONNREFUSED:
61                         errno = ECONNREFUSED;
62                         break;
63                 case WSAEINTR:
64                         errno = EINTR;
65                         break;
66                 case WSAENOTSOCK:
67                         errno = EBADFD;
68                         break;
69                 case WSAEOPNOTSUPP:
70                         errno = EOPNOTSUPP;
71                         break;
72                 case WSAEWOULDBLOCK:
73                         errno = EWOULDBLOCK;
74                         break;
75                 case WSAEACCES:
76                         errno = EACCES;
77                         break;
78                 case WSAENOTCONN:
79                 case WSAENETRESET:
80                 case WSAECONNRESET:
81                 case WSAESHUTDOWN:
82                 case WSAECONNABORTED:
83                 case WSAEDISCON:
84                         errno = ECONNREFUSED;           /* ENOTCONN? */
85                         break;
86                 default:
87                         ereport(NOTICE,
88                                         (errmsg_internal("Unknown win32 socket error code: %i", WSAGetLastError())));
89                         errno = EINVAL;
90         }
91 }
92
93 static int
94 pgwin32_poll_signals(void)
95 {
96         if (UNBLOCKED_SIGNAL_QUEUE())
97         {
98                 pgwin32_dispatch_queued_signals();
99                 errno = EINTR;
100                 return 1;
101         }
102         return 0;
103 }
104
105 static int
106 isDataGram(SOCKET s)
107 {
108         int                     type;
109         int                     typelen = sizeof(type);
110
111         if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &type, &typelen))
112                 return 1;
113
114         return (type == SOCK_DGRAM) ? 1 : 0;
115 }
116
117 int
118 pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
119 {
120         static HANDLE waitevent = INVALID_HANDLE_VALUE;
121         static SOCKET current_socket = -1;
122         static int      isUDP = 0;
123         HANDLE          events[2];
124         int                     r;
125
126         if (waitevent == INVALID_HANDLE_VALUE)
127         {
128                 waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);
129
130                 if (waitevent == INVALID_HANDLE_VALUE)
131                         ereport(ERROR,
132                                         (errmsg_internal("Failed to create socket waiting event: %i", (int) GetLastError())));
133         }
134         else if (!ResetEvent(waitevent))
135                 ereport(ERROR,
136                                 (errmsg_internal("Failed to reset socket waiting event: %i", (int) GetLastError())));
137
138         /*
139          * make sure we don't multiplex this kernel event object with a different
140          * socket from a previous call
141          */
142
143         if (current_socket != s)
144         {
145                 if (current_socket != -1)
146                         WSAEventSelect(current_socket, waitevent, 0);
147                 isUDP = isDataGram(s);
148         }
149
150         current_socket = s;
151
152         if (WSAEventSelect(s, waitevent, what) == SOCKET_ERROR)
153         {
154                 TranslateSocketError();
155                 return 0;
156         }
157
158         events[0] = pgwin32_signal_event;
159         events[1] = waitevent;
160
161         /*
162          * Just a workaround of unknown locking problem with writing in UDP socket
163          * under high load: Client's pgsql backend sleeps infinitely in
164          * WaitForMultipleObjectsEx, pgstat process sleeps in pgwin32_select().
165          * So, we will wait with small timeout(0.1 sec) and if sockect is still
166          * blocked, try WSASend (see comments in pgwin32_select) and wait again.
167          */
168         if ((what & FD_WRITE) && isUDP)
169         {
170                 for (;;)
171                 {
172                         r = WaitForMultipleObjectsEx(2, events, FALSE, 100, TRUE);
173
174                         if (r == WAIT_TIMEOUT)
175                         {
176                                 char            c;
177                                 WSABUF          buf;
178                                 DWORD           sent;
179
180                                 buf.buf = &c;
181                                 buf.len = 0;
182
183                                 r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
184                                 if (r == 0)             /* Completed - means things are fine! */
185                                         return 1;
186                                 else if (WSAGetLastError() != WSAEWOULDBLOCK)
187                                 {
188                                         TranslateSocketError();
189                                         return 0;
190                                 }
191                         }
192                         else
193                                 break;
194                 }
195         }
196         else
197                 r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
198
199         if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
200         {
201                 pgwin32_dispatch_queued_signals();
202                 errno = EINTR;
203                 return 0;
204         }
205         if (r == WAIT_OBJECT_0 + 1)
206                 return 1;
207         if (r == WAIT_TIMEOUT)
208                 return 0;
209         ereport(ERROR,
210                         (errmsg_internal("Bad return from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError())));
211         return 0;
212 }
213
214 /*
215  * Create a socket, setting it to overlapped and non-blocking
216  */
217 SOCKET
218 pgwin32_socket(int af, int type, int protocol)
219 {
220         SOCKET          s;
221         unsigned long on = 1;
222
223         s = WSASocket(af, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
224         if (s == INVALID_SOCKET)
225         {
226                 TranslateSocketError();
227                 return INVALID_SOCKET;
228         }
229
230         if (ioctlsocket(s, FIONBIO, &on))
231         {
232                 TranslateSocketError();
233                 return INVALID_SOCKET;
234         }
235         errno = 0;
236
237         return s;
238 }
239
240
241 SOCKET
242 pgwin32_accept(SOCKET s, struct sockaddr * addr, int *addrlen)
243 {
244         SOCKET          rs;
245
246         /*
247          * Poll for signals, but don't return with EINTR, since we don't handle
248          * that in pqcomm.c
249          */
250         pgwin32_poll_signals();
251
252         rs = WSAAccept(s, addr, addrlen, NULL, 0);
253         if (rs == INVALID_SOCKET)
254         {
255                 TranslateSocketError();
256                 return INVALID_SOCKET;
257         }
258         return rs;
259 }
260
261
262 /* No signal delivery during connect. */
263 int
264 pgwin32_connect(SOCKET s, const struct sockaddr * addr, int addrlen)
265 {
266         int                     r;
267
268         r = WSAConnect(s, addr, addrlen, NULL, NULL, NULL, NULL);
269         if (r == 0)
270                 return 0;
271
272         if (WSAGetLastError() != WSAEWOULDBLOCK)
273         {
274                 TranslateSocketError();
275                 return -1;
276         }
277
278         while (pgwin32_waitforsinglesocket(s, FD_CONNECT, INFINITE) == 0)
279         {
280                 /* Loop endlessly as long as we are just delivering signals */
281         }
282
283         return 0;
284 }
285
286 int
287 pgwin32_recv(SOCKET s, char *buf, int len, int f)
288 {
289         WSABUF          wbuf;
290         int                     r;
291         DWORD           b;
292         DWORD           flags = f;
293         int                     n;
294
295         if (pgwin32_poll_signals())
296                 return -1;
297
298         wbuf.len = len;
299         wbuf.buf = buf;
300
301         r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
302         if (r != SOCKET_ERROR && b > 0)
303                 /* Read succeeded right away */
304                 return b;
305
306         if (r == SOCKET_ERROR &&
307                 WSAGetLastError() != WSAEWOULDBLOCK)
308         {
309                 TranslateSocketError();
310                 return -1;
311         }
312
313         /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
314
315         for (n = 0; n < 5; n++)
316         {
317                 if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT,
318                                                                                 INFINITE) == 0)
319                         return -1;                      /* errno already set */
320
321                 r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
322                 if (r == SOCKET_ERROR)
323                 {
324                         if (WSAGetLastError() == WSAEWOULDBLOCK)
325                         {
326                                 /*
327                                  * There seem to be cases on win2k (at least) where WSARecv
328                                  * can return WSAEWOULDBLOCK even when
329                                  * pgwin32_waitforsinglesocket claims the socket is readable.
330                                  * In this case, just sleep for a moment and try again. We try
331                                  * up to 5 times - if it fails more than that it's not likely
332                                  * to ever come back.
333                                  */
334                                 pg_usleep(10000);
335                                 continue;
336                         }
337                         TranslateSocketError();
338                         return -1;
339                 }
340                 return b;
341         }
342         ereport(NOTICE,
343           (errmsg_internal("Failed to read from ready socket (after retries)")));
344         errno = EWOULDBLOCK;
345         return -1;
346 }
347
348 int
349 pgwin32_send(SOCKET s, char *buf, int len, int flags)
350 {
351         WSABUF          wbuf;
352         int                     r;
353         DWORD           b;
354
355         if (pgwin32_poll_signals())
356                 return -1;
357
358         wbuf.len = len;
359         wbuf.buf = buf;
360
361         /*
362          * Readiness of socket to send data to UDP socket may be not true: socket
363          * can become busy again! So loop until send or error occurs.
364          */
365         for (;;)
366         {
367                 r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
368                 if (r != SOCKET_ERROR && b > 0)
369                         /* Write succeeded right away */
370                         return b;
371
372                 if (r == SOCKET_ERROR &&
373                         WSAGetLastError() != WSAEWOULDBLOCK)
374                 {
375                         TranslateSocketError();
376                         return -1;
377                 }
378
379                 /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
380
381                 if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE, INFINITE) == 0)
382                         return -1;
383         }
384
385         return -1;
386 }
387
388
389 /*
390  * Wait for activity on one or more sockets.
391  * While waiting, allow signals to run
392  *
393  * NOTE! Currently does not implement exceptfds check,
394  * since it is not used in postgresql!
395  */
396 int
397 pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval * timeout)
398 {
399         WSAEVENT        events[FD_SETSIZE * 2]; /* worst case is readfds totally
400                                                                                  * different from writefds, so
401                                                                                  * 2*FD_SETSIZE sockets */
402         SOCKET          sockets[FD_SETSIZE * 2];
403         int                     numevents = 0;
404         int                     i;
405         int                     r;
406         DWORD           timeoutval = WSA_INFINITE;
407         FD_SET          outreadfds;
408         FD_SET          outwritefds;
409         int                     nummatches = 0;
410
411         Assert(exceptfds == NULL);
412
413         if (pgwin32_poll_signals())
414                 return -1;
415
416         FD_ZERO(&outreadfds);
417         FD_ZERO(&outwritefds);
418
419         /*
420          * Write FDs are different in the way that it is only flagged by
421          * WSASelectEvent() if we have tried to write to them first. So try an
422          * empty write
423          */
424         if (writefds)
425         {
426                 for (i = 0; i < writefds->fd_count; i++)
427                 {
428                         char            c;
429                         WSABUF          buf;
430                         DWORD           sent;
431
432                         buf.buf = &c;
433                         buf.len = 0;
434
435                         r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL);
436                         if (r == 0)                     /* Completed - means things are fine! */
437                                 FD_SET          (writefds->fd_array[i], &outwritefds);
438
439                         else
440                         {                                       /* Not completed */
441                                 if (WSAGetLastError() != WSAEWOULDBLOCK)
442
443                                         /*
444                                          * Not completed, and not just "would block", so an error
445                                          * occured
446                                          */
447                                         FD_SET          (writefds->fd_array[i], &outwritefds);
448                         }
449                 }
450                 if (outwritefds.fd_count > 0)
451                 {
452                         memcpy(writefds, &outwritefds, sizeof(fd_set));
453                         if (readfds)
454                                 FD_ZERO(readfds);
455                         return outwritefds.fd_count;
456                 }
457         }
458
459
460         /* Now set up for an actual select */
461
462         if (timeout != NULL)
463         {
464                 /* timeoutval is in milliseconds */
465                 timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
466         }
467
468         if (readfds != NULL)
469         {
470                 for (i = 0; i < readfds->fd_count; i++)
471                 {
472                         events[numevents] = WSACreateEvent();
473                         sockets[numevents] = readfds->fd_array[i];
474                         numevents++;
475                 }
476         }
477         if (writefds != NULL)
478         {
479                 for (i = 0; i < writefds->fd_count; i++)
480                 {
481                         if (!readfds ||
482                                 !FD_ISSET(writefds->fd_array[i], readfds))
483                         {
484                                 /* If the socket is not in the read list */
485                                 events[numevents] = WSACreateEvent();
486                                 sockets[numevents] = writefds->fd_array[i];
487                                 numevents++;
488                         }
489                 }
490         }
491
492         for (i = 0; i < numevents; i++)
493         {
494                 int                     flags = 0;
495
496                 if (readfds && FD_ISSET(sockets[i], readfds))
497                         flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
498
499                 if (writefds && FD_ISSET(sockets[i], writefds))
500                         flags |= FD_WRITE | FD_CLOSE;
501
502                 if (WSAEventSelect(sockets[i], events[i], flags) == SOCKET_ERROR)
503                 {
504                         TranslateSocketError();
505                         for (i = 0; i < numevents; i++)
506                                 WSACloseEvent(events[i]);
507                         return -1;
508                 }
509         }
510
511         events[numevents] = pgwin32_signal_event;
512         r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE);
513         if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents))
514         {
515                 /*
516                  * We scan all events, even those not signalled, in case more than one
517                  * event has been tagged but Wait.. can only return one.
518                  */
519                 WSANETWORKEVENTS resEvents;
520
521                 for (i = 0; i < numevents; i++)
522                 {
523                         ZeroMemory(&resEvents, sizeof(resEvents));
524                         if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) == SOCKET_ERROR)
525                                 ereport(FATAL,
526                                                 (errmsg_internal("failed to enumerate network events: %i", (int) GetLastError())));
527                         /* Read activity? */
528                         if (readfds && FD_ISSET(sockets[i], readfds))
529                         {
530                                 if ((resEvents.lNetworkEvents & FD_READ) ||
531                                         (resEvents.lNetworkEvents & FD_ACCEPT) ||
532                                         (resEvents.lNetworkEvents & FD_CLOSE))
533                                 {
534                                         FD_SET          (sockets[i], &outreadfds);
535
536                                         nummatches++;
537                                 }
538                         }
539                         /* Write activity? */
540                         if (writefds && FD_ISSET(sockets[i], writefds))
541                         {
542                                 if ((resEvents.lNetworkEvents & FD_WRITE) ||
543                                         (resEvents.lNetworkEvents & FD_CLOSE))
544                                 {
545                                         FD_SET          (sockets[i], &outwritefds);
546
547                                         nummatches++;
548                                 }
549                         }
550                 }
551         }
552
553         /* Clean up all handles */
554         for (i = 0; i < numevents; i++)
555         {
556                 WSAEventSelect(sockets[i], events[i], 0);
557                 WSACloseEvent(events[i]);
558         }
559
560         if (r == WSA_WAIT_TIMEOUT)
561         {
562                 if (readfds)
563                         FD_ZERO(readfds);
564                 if (writefds)
565                         FD_ZERO(writefds);
566                 return 0;
567         }
568
569         if (r == WAIT_OBJECT_0 + numevents)
570         {
571                 pgwin32_dispatch_queued_signals();
572                 errno = EINTR;
573                 if (readfds)
574                         FD_ZERO(readfds);
575                 if (writefds)
576                         FD_ZERO(writefds);
577                 return -1;
578         }
579
580         /* Overwrite socket sets with our resulting values */
581         if (readfds)
582                 memcpy(readfds, &outreadfds, sizeof(fd_set));
583         if (writefds)
584                 memcpy(writefds, &outwritefds, sizeof(fd_set));
585         return nummatches;
586 }
587
588
589 /*
590  * Return win32 error string, since strerror can't
591  * handle winsock codes
592  */
593 static char wserrbuf[256];
594 const char *
595 pgwin32_socket_strerror(int err)
596 {
597         static HANDLE handleDLL = INVALID_HANDLE_VALUE;
598
599         if (handleDLL == INVALID_HANDLE_VALUE)
600         {
601                 handleDLL = LoadLibraryEx("netmsg.dll", NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
602                 if (handleDLL == NULL)
603                         ereport(FATAL,
604                                         (errmsg_internal("Failed to load netmsg.dll: %i", (int) GetLastError())));
605         }
606
607         ZeroMemory(&wserrbuf, sizeof(wserrbuf));
608         if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,
609                                           handleDLL,
610                                           err,
611                                           MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
612                                           wserrbuf,
613                                           sizeof(wserrbuf) - 1,
614                                           NULL) == 0)
615         {
616                 /* Failed to get id */
617                 sprintf(wserrbuf, "Unknown winsock error %i", err);
618         }
619         return wserrbuf;
620 }