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 |