| OLD | NEW |
| 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| 2 /* This Source Code Form is subject to the terms of the Mozilla Public | 2 /* This Source Code Form is subject to the terms of the Mozilla Public |
| 3 * License, v. 2.0. If a copy of the MPL was not distributed with this | 3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 5 | 5 |
| 6 /* Win95 Sockets module | 6 /* Win95 Sockets module |
| 7 * | 7 * |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 #include "primpl.h" | 10 #include "primpl.h" |
| 11 | 11 |
| 12 #define READ_FD 1 | 12 #define READ_FD 1 |
| 13 #define WRITE_FD 2 | 13 #define WRITE_FD 2 |
| 14 #define CONNECT_FD 3 | 14 #define CONNECT_FD 3 |
| 15 | 15 |
| 16 static PRInt32 socket_io_wait( | 16 static PRInt32 socket_io_wait( |
| 17 PROsfd osfd, | 17 PROsfd osfd, |
| 18 PRInt32 fd_type, | 18 PRInt32 fd_type, |
| 19 PRIntervalTime timeout); | 19 PRIntervalTime timeout); |
| 20 | 20 |
| 21 | 21 |
| 22 /* --- SOCKET IO --------------------------------------------------------- */ | 22 /* --- SOCKET IO --------------------------------------------------------- */ |
| 23 | 23 |
| 24 /* | |
| 25 * we only want to call WSAIoctl() on Vista and later | |
| 26 * so don't pay for it at build time (and avoid including winsock2.h) | |
| 27 */ | |
| 28 | |
| 29 /* from ws2def.h */ | |
| 30 #define IOC_IN 0x80000000 /* copy in parameters */ | |
| 31 #define IOC_VENDOR 0x18000000 | |
| 32 #define _WSAIOW(x,y) (IOC_IN|(x)|(y)) | |
| 33 /* from MSWSockDef.h */ | |
| 34 #define SIO_SET_COMPATIBILITY_MODE _WSAIOW(IOC_VENDOR,300) | |
| 35 | |
| 36 typedef enum _WSA_COMPATIBILITY_BEHAVIOR_ID { | |
| 37 WsaBehaviorAll = 0, | |
| 38 WsaBehaviorReceiveBuffering, | |
| 39 WsaBehaviorAutoTuning | |
| 40 } WSA_COMPATIBILITY_BEHAVIOR_ID, *PWSA_COMPATIBILITY_BEHAVIOR_ID; | |
| 41 | |
| 42 /* from sdkddkver.h */ | |
| 43 #define NTDDI_WIN6 0x06000000 /* Windows Vista */ | |
| 44 | |
| 45 /* from winsock2.h */ | |
| 46 #define WSAEVENT HANDLE | |
| 47 | |
| 48 #define WSAOVERLAPPED OVERLAPPED | |
| 49 typedef struct _OVERLAPPED * LPWSAOVERLAPPED; | |
| 50 | |
| 51 typedef void (CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE)( | |
| 52 IN DWORD dwError, | |
| 53 IN DWORD cbTransferred, | |
| 54 IN LPWSAOVERLAPPED lpOverlapped, | |
| 55 IN DWORD dwFlags | |
| 56 ); | |
| 57 | |
| 58 typedef int (__stdcall * WSAIOCTLPROC) ( | |
| 59 SOCKET s, | |
| 60 DWORD dwIoControlCode, | |
| 61 LPVOID lpvInBuffer, | |
| 62 DWORD cbInBuffer, | |
| 63 LPVOID lpvOutBuffer, | |
| 64 DWORD cbOutBuffer, | |
| 65 LPDWORD lpcbBytesReturned, | |
| 66 LPWSAOVERLAPPED lpOverlapped, | |
| 67 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine | |
| 68 ); | |
| 69 | |
| 70 typedef struct _WSA_COMPATIBILITY_MODE { | |
| 71 WSA_COMPATIBILITY_BEHAVIOR_ID BehaviorId; | |
| 72 ULONG TargetOsVersion; | |
| 73 } WSA_COMPATIBILITY_MODE, *PWSA_COMPATIBILITY_MODE; | |
| 74 | |
| 75 static HMODULE libWinsock2 = NULL; | |
| 76 static WSAIOCTLPROC wsaioctlProc = NULL; | |
| 77 static PRBool socketSetCompatMode = PR_FALSE; | |
| 78 static PRBool socketFixInet6RcvBuf = PR_FALSE; | 24 static PRBool socketFixInet6RcvBuf = PR_FALSE; |
| 79 | 25 |
| 80 void _PR_MD_InitSockets(void) | 26 void _PR_MD_InitSockets(void) |
| 81 { | 27 { |
| 82 OSVERSIONINFO osvi; | 28 OSVERSIONINFO osvi; |
| 83 | 29 |
| 84 memset(&osvi, 0, sizeof(osvi)); | 30 memset(&osvi, 0, sizeof(osvi)); |
| 85 osvi.dwOSVersionInfoSize = sizeof(osvi); | 31 osvi.dwOSVersionInfoSize = sizeof(osvi); |
| 86 GetVersionEx(&osvi); | 32 GetVersionEx(&osvi); |
| 87 | 33 |
| 88 /* if Vista or later... */ | 34 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) |
| 89 if (osvi.dwMajorVersion >= 6) | |
| 90 { | |
| 91 libWinsock2 = LoadLibraryW(L"Ws2_32.dll"); | |
| 92 if (libWinsock2) | |
| 93 { | |
| 94 wsaioctlProc = (WSAIOCTLPROC)GetProcAddress(libWinsock2, | |
| 95 "WSAIoctl"); | |
| 96 if (wsaioctlProc) | |
| 97 { | |
| 98 socketSetCompatMode = PR_TRUE; | |
| 99 } | |
| 100 } | |
| 101 } | |
| 102 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) | |
| 103 { | 35 { |
| 104 /* if Windows XP (32-bit) */ | 36 /* if Windows XP (32-bit) */ |
| 105 socketFixInet6RcvBuf = PR_TRUE; | 37 socketFixInet6RcvBuf = PR_TRUE; |
| 106 } | 38 } |
| 107 } | 39 } |
| 108 | 40 |
| 109 void _PR_MD_CleanupSockets(void) | 41 void _PR_MD_CleanupSockets(void) |
| 110 { | 42 { |
| 111 socketSetCompatMode = PR_FALSE; | 43 socketFixInet6RcvBuf = PR_FALSE; |
| 112 wsaioctlProc = NULL; | |
| 113 if (libWinsock2) | |
| 114 { | |
| 115 FreeLibrary(libWinsock2); | |
| 116 libWinsock2 = NULL; | |
| 117 } | |
| 118 } | 44 } |
| 119 | 45 |
| 120 PROsfd | 46 PROsfd |
| 121 _PR_MD_SOCKET(int af, int type, int flags) | 47 _PR_MD_SOCKET(int af, int type, int flags) |
| 122 { | 48 { |
| 123 SOCKET sock; | 49 SOCKET sock; |
| 124 u_long one = 1; | 50 u_long one = 1; |
| 125 | 51 |
| 126 sock = socket(af, type, flags); | 52 sock = socket(af, type, flags); |
| 127 | 53 |
| 128 if (sock == INVALID_SOCKET ) | 54 if (sock == INVALID_SOCKET ) |
| 129 { | 55 { |
| 130 _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError()); | 56 _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError()); |
| 131 return (PROsfd)sock; | 57 return (PROsfd)sock; |
| 132 } | 58 } |
| 133 | 59 |
| 134 /* | 60 /* |
| 135 ** Make the socket Non-Blocking | 61 ** Make the socket Non-Blocking |
| 136 */ | 62 */ |
| 137 if (ioctlsocket( sock, FIONBIO, &one) != 0) | 63 if (ioctlsocket( sock, FIONBIO, &one) != 0) |
| 138 { | 64 { |
| 139 PR_SetError(PR_UNKNOWN_ERROR, WSAGetLastError()); | 65 PR_SetError(PR_UNKNOWN_ERROR, WSAGetLastError()); |
| 140 closesocket(sock); | 66 closesocket(sock); |
| 141 return -1; | 67 return -1; |
| 142 } | 68 } |
| 143 | 69 |
| 144 if ((af == AF_INET || af == AF_INET6) && | |
| 145 type == SOCK_STREAM && socketSetCompatMode) | |
| 146 { | |
| 147 WSA_COMPATIBILITY_MODE mode; | |
| 148 char dummy[4]; | |
| 149 int ret_dummy; | |
| 150 | |
| 151 mode.BehaviorId = WsaBehaviorAutoTuning; | |
| 152 mode.TargetOsVersion = NTDDI_WIN6; | |
| 153 if (wsaioctlProc(sock, SIO_SET_COMPATIBILITY_MODE, | |
| 154 (char *)&mode, sizeof(mode), | |
| 155 dummy, 4, &ret_dummy, 0, NULL) == SOCKET_ERROR) | |
| 156 { | |
| 157 int err = WSAGetLastError(); | |
| 158 PR_LOG(_pr_io_lm, PR_LOG_DEBUG, ("WSAIoctl() failed with %d", err)); | |
| 159 | |
| 160 /* SIO_SET_COMPATIBILITY_MODE may not be supported. | |
| 161 ** If the call to WSAIoctl() fails with WSAEOPNOTSUPP, | |
| 162 ** don't close the socket. | |
| 163 */ | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 if (af == AF_INET6 && socketFixInet6RcvBuf) | 70 if (af == AF_INET6 && socketFixInet6RcvBuf) |
| 168 { | 71 { |
| 169 int bufsize; | 72 int bufsize; |
| 170 int len = sizeof(bufsize); | 73 int len = sizeof(bufsize); |
| 171 int rv; | 74 int rv; |
| 172 | 75 |
| 173 /* Windows XP 32-bit returns an error on getpeername() for AF_INET6 | 76 /* Windows XP 32-bit returns an error on getpeername() for AF_INET6 |
| 174 * sockets if the receive buffer size is greater than 65535 before | 77 * sockets if the receive buffer size is greater than 65535 before |
| 175 * the connection is initiated. The default receive buffer size may | 78 * the connection is initiated. The default receive buffer size may |
| 176 * be 128000 so fix it here to always be <= 65535. See bug 513659 | 79 * be 128000 so fix it here to always be <= 65535. See bug 513659 |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 break; | 660 break; |
| 758 } else { | 661 } else { |
| 759 remaining = remaining - elapsed; | 662 remaining = remaining - elapsed; |
| 760 } | 663 } |
| 761 } | 664 } |
| 762 } while (rv == 0 ); | 665 } while (rv == 0 ); |
| 763 break; | 666 break; |
| 764 } | 667 } |
| 765 return(rv); | 668 return(rv); |
| 766 } /* end socket_io_wait() */ | 669 } /* end socket_io_wait() */ |
| OLD | NEW |