Commit | Line | Data |
68dc0745 |
1 | /* NTSock.C |
2 | * |
3 | * (c) 1995 Microsoft Corporation. All rights reserved. |
4 | * Developed by hip communications inc., http://info.hip.com/info/ |
5 | * Portions (c) 1993 Intergraph Corporation. All rights reserved. |
6 | * |
7 | * You may distribute under the terms of either the GNU General Public |
8 | * License or the Artistic License, as specified in the README file. |
9 | */ |
0a753a76 |
10 | |
11 | #include <windows.h> |
12 | #define WIN32_LEAN_AND_MEAN |
13 | #include "EXTERN.h" |
14 | #include "perl.h" |
15 | #include <sys/socket.h> |
16 | #include <fcntl.h> |
17 | #include <sys/stat.h> |
18 | #include <assert.h> |
19 | |
20 | #define CROAK croak |
21 | |
22 | #ifdef USE_SOCKETS_AS_HANDLES |
68dc0745 |
23 | /* thanks to Beverly Brown (beverly@datacube.com) */ |
0a753a76 |
24 | |
25 | # if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86) |
68dc0745 |
26 | /*# define OPEN_SOCKET(x) _patch_open_osfhandle(x, _O_RDWR | _O_BINARY) */ |
0a753a76 |
27 | # define OPEN_SOCKET(x) _open_osfhandle(x,_O_RDWR|_O_BINARY) |
28 | # else |
29 | # define OPEN_SOCKET(x) _open_osfhandle(x,_O_RDWR|_O_BINARY) |
30 | # endif |
31 | # define TO_SOCKET(x) _get_osfhandle(x) |
32 | |
33 | #else |
34 | |
35 | # define OPEN_SOCKET(x) (x) |
36 | # define TO_SOCKET(x) (x) |
37 | |
68dc0745 |
38 | #endif /* USE_SOCKETS_AS_HANDLES */ |
0a753a76 |
39 | |
68dc0745 |
40 | /* |
41 | * This is a clone of fdopen so that we can handle the version of |
42 | * sockets that NT gets to use. |
43 | * |
44 | * The problem is that sockets are not real file handles and |
45 | * cannot be fdopen'ed. This causes problems in the do_socket |
46 | * routine in doio.c, since it tries to create two file pointers |
47 | * for the socket just created. We'll fake out an fdopen and see |
48 | * if we can prevent perl from trying to do stdio on sockets. |
49 | */ |
0a753a76 |
50 | |
51 | #if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86) |
52 | |
53 | # ifdef __cplusplus |
54 | #define EXT_C_FUNC extern "C" |
55 | # else |
56 | #define EXT_C_FUNC extern |
57 | # endif |
58 | |
59 | EXT_C_FUNC int __cdecl _alloc_osfhnd(void); |
60 | EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value); |
61 | EXT_C_FUNC void __cdecl _lock_fhandle(int); |
62 | EXT_C_FUNC void __cdecl _unlock_fhandle(int); |
63 | EXT_C_FUNC void __cdecl _unlock(int); |
68dc0745 |
64 | EXT_C_FUNC struct servent* win32_savecopyservent(struct servent*d, |
65 | struct servent*s, const char *proto); |
0a753a76 |
66 | |
67 | #if (_MSC_VER >= 1000) |
68dc0745 |
68 | typedef struct { |
69 | long osfhnd; /* underlying OS file HANDLE */ |
70 | char osfile; /* attributes of file (e.g., open in text mode?) */ |
71 | char pipech; /* one char buffer for handles opened on pipes */ |
0a753a76 |
72 | #if defined (_MT) && !defined (DLL_FOR_WIN32S) |
68dc0745 |
73 | int lockinitflag; |
74 | CRITICAL_SECTION lock; |
0a753a76 |
75 | #endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */ |
68dc0745 |
76 | } ioinfo; |
0a753a76 |
77 | |
68dc0745 |
78 | EXT_C_FUNC ioinfo * __pioinfo[]; |
0a753a76 |
79 | |
68dc0745 |
80 | #define IOINFO_L2E 5 |
81 | #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) |
82 | #define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1))) |
83 | #define _osfile(i) (_pioinfo(i)->osfile) |
84 | #else /* (_MSC_VER >= 1000) */ |
85 | extern char _osfile[]; |
86 | #endif /* (_MSC_VER >= 1000) */ |
0a753a76 |
87 | |
68dc0745 |
88 | #define FOPEN 0x01 /* file handle open */ |
89 | #define FAPPEND 0x20 /* file handle opened O_APPEND */ |
90 | #define FDEV 0x40 /* file handle refers to device */ |
91 | #define FTEXT 0x80 /* file handle is in text mode */ |
0a753a76 |
92 | |
68dc0745 |
93 | #define _STREAM_LOCKS 26 /* Table of stream locks */ |
94 | #define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) /* Last stream lock */ |
95 | #define _FH_LOCKS (_LAST_STREAM_LOCK+1) /* Table of fh locks */ |
0a753a76 |
96 | |
97 | /*** |
98 | *int _patch_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle |
99 | * |
100 | *Purpose: |
101 | * This function allocates a free C Runtime file handle and associates |
102 | * it with the Win32 HANDLE specified by the first parameter. This is a |
68dc0745 |
103 | * temperary fix for WIN95's brain damage GetFileType() error on socket |
104 | * we just bypass that call for socket |
0a753a76 |
105 | * |
106 | *Entry: |
107 | * long osfhandle - Win32 HANDLE to associate with C Runtime file handle. |
108 | * int flags - flags to associate with C Runtime file handle. |
109 | * |
110 | *Exit: |
111 | * returns index of entry in fh, if successful |
112 | * return -1, if no free entry is found |
113 | * |
114 | *Exceptions: |
115 | * |
116 | *******************************************************************************/ |
117 | |
68dc0745 |
118 | int __cdecl |
119 | _patch_open_osfhandle(long osfhandle, int flags) |
0a753a76 |
120 | { |
68dc0745 |
121 | int fh; |
122 | char fileflags; /* _osfile flags */ |
0a753a76 |
123 | |
68dc0745 |
124 | /* copy relevant flags from second parameter */ |
125 | fileflags = FDEV; |
0a753a76 |
126 | |
68dc0745 |
127 | if(flags & _O_APPEND) |
128 | fileflags |= FAPPEND; |
0a753a76 |
129 | |
68dc0745 |
130 | if(flags & _O_TEXT) |
131 | fileflags |= FTEXT; |
0a753a76 |
132 | |
68dc0745 |
133 | /* attempt to allocate a C Runtime file handle */ |
134 | if((fh = _alloc_osfhnd()) == -1) { |
135 | errno = EMFILE; /* too many open files */ |
136 | _doserrno = 0L; /* not an OS error */ |
137 | return -1; /* return error to caller */ |
138 | } |
0a753a76 |
139 | |
68dc0745 |
140 | /* the file is open. now, set the info in _osfhnd array */ |
141 | _set_osfhnd(fh, osfhandle); |
0a753a76 |
142 | |
68dc0745 |
143 | fileflags |= FOPEN; /* mark as open */ |
0a753a76 |
144 | |
145 | #if (_MSC_VER >= 1000) |
68dc0745 |
146 | _osfile(fh) = fileflags; /* set osfile entry */ |
147 | _unlock_fhandle(fh); |
0a753a76 |
148 | #else |
68dc0745 |
149 | _osfile[fh] = fileflags; /* set osfile entry */ |
150 | _unlock(fh+_FH_LOCKS); /* unlock handle */ |
0a753a76 |
151 | #endif |
152 | |
68dc0745 |
153 | return fh; /* return handle */ |
0a753a76 |
154 | } |
68dc0745 |
155 | #endif /* _M_IX86 */ |
0a753a76 |
156 | |
157 | #define SOCKETAPI PASCAL |
158 | |
159 | typedef SOCKET (SOCKETAPI *LPSOCKACCEPT)(SOCKET, struct sockaddr *, int *); |
160 | typedef int (SOCKETAPI *LPSOCKBIND)(SOCKET, const struct sockaddr *, int); |
161 | typedef int (SOCKETAPI *LPSOCKCLOSESOCKET)(SOCKET); |
162 | typedef int (SOCKETAPI *LPSOCKCONNECT)(SOCKET, const struct sockaddr *, int); |
163 | typedef int (SOCKETAPI *LPSOCKIOCTLSOCKET)(SOCKET, long, u_long *); |
164 | typedef int (SOCKETAPI *LPSOCKGETPEERNAME)(SOCKET, struct sockaddr *, int *); |
165 | typedef int (SOCKETAPI *LPSOCKGETSOCKNAME)(SOCKET, struct sockaddr *, int *); |
166 | typedef int (SOCKETAPI *LPSOCKGETSOCKOPT)(SOCKET, int, int, char *, int *); |
167 | typedef u_long (SOCKETAPI *LPSOCKHTONL)(u_long); |
168 | typedef u_short (SOCKETAPI *LPSOCKHTONS)(u_short); |
169 | typedef int (SOCKETAPI *LPSOCKLISTEN)(SOCKET, int); |
170 | typedef u_long (SOCKETAPI *LPSOCKNTOHL)(u_long); |
171 | typedef u_short (SOCKETAPI *LPSOCKNTOHS)(u_short); |
172 | typedef int (SOCKETAPI *LPSOCKRECV)(SOCKET, char *, int, int); |
173 | typedef int (SOCKETAPI *LPSOCKRECVFROM)(SOCKET, char *, int, int, struct sockaddr *, int *); |
174 | typedef int (SOCKETAPI *LPSOCKSELECT)(int, fd_set *, fd_set *, fd_set *, const struct timeval *); |
175 | typedef int (SOCKETAPI *LPSOCKSEND)(SOCKET, const char *, int, int); |
176 | typedef int (SOCKETAPI *LPSOCKSENDTO)(SOCKET, const char *, int, int, const struct sockaddr *, int); |
177 | typedef int (SOCKETAPI *LPSOCKSETSOCKOPT)(SOCKET, int, int, const char *, int); |
178 | typedef int (SOCKETAPI *LPSOCKSHUTDOWN)(SOCKET, int); |
179 | typedef SOCKET (SOCKETAPI *LPSOCKSOCKET)(int, int, int); |
180 | typedef char FAR *(SOCKETAPI *LPSOCKINETNTOA)(struct in_addr in); |
181 | typedef unsigned long (SOCKETAPI *LPSOCKINETADDR)(const char FAR * cp); |
182 | |
183 | |
184 | /* Database function prototypes */ |
185 | typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYADDR)(const char *, int, int); |
186 | typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYNAME)(const char *); |
187 | typedef int (SOCKETAPI *LPSOCKGETHOSTNAME)(char *, int); |
188 | typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYPORT)(int, const char *); |
189 | typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYNAME)(const char *, const char *); |
190 | typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNUMBER)(int); |
191 | typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNAME)(const char *); |
192 | |
193 | /* Microsoft Windows Extension function prototypes */ |
194 | typedef int (SOCKETAPI *LPSOCKWSASTARTUP)(unsigned short, LPWSADATA); |
195 | typedef int (SOCKETAPI *LPSOCKWSACLEANUP)(void); |
196 | typedef int (SOCKETAPI *LPSOCKWSAGETLASTERROR)(void); |
197 | typedef int (SOCKETAPI *LPWSAFDIsSet)(SOCKET, fd_set *); |
198 | |
199 | static HINSTANCE hWinSockDll = 0; |
68dc0745 |
200 | /* extern CRITICAL_SECTION csSock; */ |
0a753a76 |
201 | |
202 | static LPSOCKACCEPT paccept = 0; |
203 | static LPSOCKBIND pbind = 0; |
204 | static LPSOCKCLOSESOCKET pclosesocket = 0; |
205 | static LPSOCKCONNECT pconnect = 0; |
206 | static LPSOCKIOCTLSOCKET pioctlsocket = 0; |
207 | static LPSOCKGETPEERNAME pgetpeername = 0; |
208 | static LPSOCKGETSOCKNAME pgetsockname = 0; |
209 | static LPSOCKGETSOCKOPT pgetsockopt = 0; |
210 | static LPSOCKHTONL phtonl = 0; |
211 | static LPSOCKHTONS phtons = 0; |
212 | static LPSOCKLISTEN plisten = 0; |
213 | static LPSOCKNTOHL pntohl = 0; |
214 | static LPSOCKNTOHS pntohs = 0; |
215 | static LPSOCKRECV precv = 0; |
216 | static LPSOCKRECVFROM precvfrom = 0; |
217 | static LPSOCKSELECT pselect = 0; |
218 | static LPSOCKSEND psend = 0; |
219 | static LPSOCKSENDTO psendto = 0; |
220 | static LPSOCKSETSOCKOPT psetsockopt = 0; |
221 | static LPSOCKSHUTDOWN pshutdown = 0; |
222 | static LPSOCKSOCKET psocket = 0; |
223 | static LPSOCKGETHOSTBYADDR pgethostbyaddr = 0; |
224 | static LPSOCKGETHOSTBYNAME pgethostbyname = 0; |
225 | static LPSOCKGETHOSTNAME pgethostname = 0; |
226 | static LPSOCKGETSERVBYPORT pgetservbyport = 0; |
227 | static LPSOCKGETSERVBYNAME pgetservbyname = 0; |
228 | static LPSOCKGETPROTOBYNUMBER pgetprotobynumber = 0; |
229 | static LPSOCKGETPROTOBYNAME pgetprotobyname = 0; |
230 | static LPSOCKWSASTARTUP pWSAStartup = 0; |
231 | static LPSOCKWSACLEANUP pWSACleanup = 0; |
232 | static LPSOCKWSAGETLASTERROR pWSAGetLastError = 0; |
233 | static LPWSAFDIsSet pWSAFDIsSet = 0; |
234 | static LPSOCKINETNTOA pinet_ntoa = 0; |
235 | static LPSOCKINETADDR pinet_addr = 0; |
236 | |
237 | __declspec(thread) struct servent myservent; |
238 | |
239 | |
68dc0745 |
240 | void * |
241 | GetAddress(HINSTANCE hInstance, char *lpFunctionName) |
242 | { |
243 | char buffer[512]; |
244 | FARPROC proc = GetProcAddress(hInstance, lpFunctionName); |
245 | if(proc == 0) { |
246 | sprintf(buffer, "Unable to get address of %s in WSock32.dll", lpFunctionName); |
247 | CROAK(buffer); |
248 | } |
249 | return proc; |
250 | } |
251 | |
252 | void |
253 | LoadWinSock(void) |
254 | { |
255 | /* EnterCriticalSection(&csSock); */ |
256 | if(hWinSockDll == NULL) { |
257 | HINSTANCE hLib = LoadLibrary("WSock32.DLL"); |
258 | if(hLib == NULL) |
259 | CROAK("Could not load WSock32.dll\n"); |
260 | |
261 | paccept = (LPSOCKACCEPT)GetAddress(hLib, "accept"); |
262 | pbind = (LPSOCKBIND)GetAddress(hLib, "bind"); |
263 | pclosesocket = (LPSOCKCLOSESOCKET)GetAddress(hLib, "closesocket"); |
264 | pconnect = (LPSOCKCONNECT)GetAddress(hLib, "connect"); |
265 | pioctlsocket = (LPSOCKIOCTLSOCKET)GetAddress(hLib, "ioctlsocket"); |
266 | pgetpeername = (LPSOCKGETPEERNAME)GetAddress(hLib, "getpeername"); |
267 | pgetsockname = (LPSOCKGETSOCKNAME)GetAddress(hLib, "getsockname"); |
268 | pgetsockopt = (LPSOCKGETSOCKOPT)GetAddress(hLib, "getsockopt"); |
269 | phtonl = (LPSOCKHTONL)GetAddress(hLib, "htonl"); |
270 | phtons = (LPSOCKHTONS)GetAddress(hLib, "htons"); |
271 | plisten = (LPSOCKLISTEN)GetAddress(hLib, "listen"); |
272 | pntohl = (LPSOCKNTOHL)GetAddress(hLib, "ntohl"); |
273 | pntohs = (LPSOCKNTOHS)GetAddress(hLib, "ntohs"); |
274 | precv = (LPSOCKRECV)GetAddress(hLib, "recv"); |
275 | precvfrom = (LPSOCKRECVFROM)GetAddress(hLib, "recvfrom"); |
276 | pselect = (LPSOCKSELECT)GetAddress(hLib, "select"); |
277 | psend = (LPSOCKSEND)GetAddress(hLib, "send"); |
278 | psendto = (LPSOCKSENDTO)GetAddress(hLib, "sendto"); |
279 | psetsockopt = (LPSOCKSETSOCKOPT)GetAddress(hLib, "setsockopt"); |
280 | pshutdown = (LPSOCKSHUTDOWN)GetAddress(hLib, "shutdown"); |
281 | psocket = (LPSOCKSOCKET)GetAddress(hLib, "socket"); |
282 | pgethostbyaddr = (LPSOCKGETHOSTBYADDR)GetAddress(hLib, "gethostbyaddr"); |
283 | pgethostbyname = (LPSOCKGETHOSTBYNAME)GetAddress(hLib, "gethostbyname"); |
284 | pgethostname = (LPSOCKGETHOSTNAME)GetAddress(hLib, "gethostname"); |
285 | pgetservbyport = (LPSOCKGETSERVBYPORT)GetAddress(hLib, "getservbyport"); |
286 | pgetservbyname = (LPSOCKGETSERVBYNAME)GetAddress(hLib, "getservbyname"); |
287 | pgetprotobynumber = (LPSOCKGETPROTOBYNUMBER)GetAddress(hLib, "getprotobynumber"); |
288 | pgetprotobyname = (LPSOCKGETPROTOBYNAME)GetAddress(hLib, "getprotobyname"); |
289 | pWSAStartup = (LPSOCKWSASTARTUP)GetAddress(hLib, "WSAStartup"); |
290 | pWSACleanup = (LPSOCKWSACLEANUP)GetAddress(hLib, "WSACleanup"); |
291 | pWSAGetLastError = (LPSOCKWSAGETLASTERROR)GetAddress(hLib, "WSAGetLastError"); |
292 | pWSAFDIsSet = (LPWSAFDIsSet)GetAddress(hLib, "__WSAFDIsSet"); |
293 | pinet_addr = (LPSOCKINETADDR)GetAddress(hLib,"inet_addr"); |
294 | pinet_ntoa = (LPSOCKINETNTOA)GetAddress(hLib,"inet_ntoa"); |
295 | |
296 | hWinSockDll = hLib; |
297 | } |
298 | /* LeaveCriticalSection(&csSock); */ |
299 | } |
300 | |
301 | void |
302 | EndSockets(void) |
303 | { |
304 | if(hWinSockDll != NULL) { |
305 | pWSACleanup(); |
306 | FreeLibrary(hWinSockDll); |
307 | } |
308 | hWinSockDll = NULL; |
309 | } |
310 | |
311 | void |
312 | StartSockets(void) |
313 | { |
314 | unsigned short version; |
315 | WSADATA retdata; |
316 | int ret; |
317 | int iSockOpt = SO_SYNCHRONOUS_NONALERT; |
318 | |
319 | LoadWinSock(); |
320 | /* |
321 | * initalize the winsock interface and insure that it is |
322 | * cleaned up at exit. |
323 | */ |
324 | version = 0x101; |
325 | if(ret = pWSAStartup(version, &retdata)) |
326 | CROAK("Unable to locate winsock library!\n"); |
327 | if(retdata.wVersion != version) |
328 | CROAK("Could not find version 1.1 of winsock dll\n"); |
329 | |
330 | /* atexit((void (*)(void)) EndSockets); */ |
0a753a76 |
331 | |
332 | #ifdef USE_SOCKETS_AS_HANDLES |
68dc0745 |
333 | /* |
334 | * Enable the use of sockets as filehandles |
335 | */ |
336 | psetsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, |
337 | (char *)&iSockOpt, sizeof(iSockOpt)); |
338 | #endif /* USE_SOCKETS_AS_HANDLES */ |
0a753a76 |
339 | } |
340 | |
341 | |
342 | #ifndef USE_SOCKETS_AS_HANDLES |
68dc0745 |
343 | FILE * |
344 | myfdopen(int fd, char *mode) |
0a753a76 |
345 | { |
68dc0745 |
346 | FILE *fp; |
347 | char sockbuf[256]; |
348 | int optlen = sizeof(sockbuf); |
349 | int retval; |
0a753a76 |
350 | |
68dc0745 |
351 | if (hWinSockDll == 0) |
352 | LoadWinSock(); |
0a753a76 |
353 | |
68dc0745 |
354 | retval = pgetsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen); |
355 | if(retval == SOCKET_ERROR && pWSAGetLastError() == WSAENOTSOCK) { |
356 | return(_fdopen(fd, mode)); |
357 | } |
0a753a76 |
358 | |
68dc0745 |
359 | /* |
360 | * If we get here, then fd is actually a socket. |
361 | */ |
362 | Newz(1601, fp, 1, FILE); |
363 | if(fp == NULL) { |
364 | errno = ENOMEM; |
365 | return NULL; |
366 | } |
0a753a76 |
367 | |
68dc0745 |
368 | fp->_file = fd; |
369 | if(*mode == 'r') |
370 | fp->_flag = _IOREAD; |
371 | else |
372 | fp->_flag = _IOWRT; |
373 | |
374 | return fp; |
0a753a76 |
375 | } |
68dc0745 |
376 | #endif /* USE_SOCKETS_AS_HANDLES */ |
0a753a76 |
377 | |
378 | |
68dc0745 |
379 | u_long |
380 | win32_htonl(u_long hostlong) |
0a753a76 |
381 | { |
68dc0745 |
382 | if(hWinSockDll == 0) |
383 | LoadWinSock(); |
0a753a76 |
384 | |
68dc0745 |
385 | return phtonl(hostlong); |
0a753a76 |
386 | } |
387 | |
68dc0745 |
388 | u_short |
389 | win32_htons(u_short hostshort) |
0a753a76 |
390 | { |
68dc0745 |
391 | if(hWinSockDll == 0) |
392 | LoadWinSock(); |
0a753a76 |
393 | |
68dc0745 |
394 | return phtons(hostshort); |
0a753a76 |
395 | } |
396 | |
68dc0745 |
397 | u_long |
398 | win32_ntohl(u_long netlong) |
0a753a76 |
399 | { |
68dc0745 |
400 | if(hWinSockDll == 0) |
401 | LoadWinSock(); |
0a753a76 |
402 | |
68dc0745 |
403 | return pntohl(netlong); |
0a753a76 |
404 | } |
405 | |
68dc0745 |
406 | u_short |
407 | win32_ntohs(u_short netshort) |
0a753a76 |
408 | { |
68dc0745 |
409 | if(hWinSockDll == 0) |
410 | LoadWinSock(); |
0a753a76 |
411 | |
68dc0745 |
412 | return pntohs(netshort); |
0a753a76 |
413 | } |
414 | |
415 | |
416 | #define SOCKET_TEST(x, y) if(hWinSockDll == 0) StartSockets();\ |
68dc0745 |
417 | if((x) == (y)) errno = pWSAGetLastError() |
0a753a76 |
418 | |
68dc0745 |
419 | #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) |
0a753a76 |
420 | |
68dc0745 |
421 | SOCKET |
422 | win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen) |
0a753a76 |
423 | { |
68dc0745 |
424 | SOCKET r; |
0a753a76 |
425 | |
68dc0745 |
426 | SOCKET_TEST((r = paccept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); |
427 | return OPEN_SOCKET(r); |
0a753a76 |
428 | } |
429 | |
68dc0745 |
430 | int |
431 | win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen) |
0a753a76 |
432 | { |
68dc0745 |
433 | int r; |
0a753a76 |
434 | |
68dc0745 |
435 | SOCKET_TEST_ERROR(r = pbind(TO_SOCKET(s), addr, addrlen)); |
436 | return r; |
0a753a76 |
437 | } |
438 | |
68dc0745 |
439 | int |
440 | win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen) |
0a753a76 |
441 | { |
68dc0745 |
442 | int r; |
0a753a76 |
443 | |
68dc0745 |
444 | SOCKET_TEST_ERROR(r = pconnect(TO_SOCKET(s), addr, addrlen)); |
445 | return r; |
0a753a76 |
446 | } |
447 | |
448 | |
68dc0745 |
449 | int |
450 | win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen) |
0a753a76 |
451 | { |
68dc0745 |
452 | int r; |
0a753a76 |
453 | |
68dc0745 |
454 | SOCKET_TEST_ERROR(r = pgetpeername(TO_SOCKET(s), addr, addrlen)); |
455 | return r; |
0a753a76 |
456 | } |
457 | |
68dc0745 |
458 | int |
459 | win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen) |
0a753a76 |
460 | { |
68dc0745 |
461 | int r; |
0a753a76 |
462 | |
68dc0745 |
463 | SOCKET_TEST_ERROR(r = pgetsockname(TO_SOCKET(s), addr, addrlen)); |
464 | return r; |
0a753a76 |
465 | } |
466 | |
68dc0745 |
467 | int |
468 | win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) |
0a753a76 |
469 | { |
68dc0745 |
470 | int r; |
0a753a76 |
471 | |
68dc0745 |
472 | SOCKET_TEST_ERROR(r = pgetsockopt(TO_SOCKET(s), level, optname, optval, optlen)); |
473 | return r; |
0a753a76 |
474 | } |
475 | |
68dc0745 |
476 | int |
477 | win32_ioctlsocket(SOCKET s, long cmd, u_long *argp) |
0a753a76 |
478 | { |
68dc0745 |
479 | int r; |
0a753a76 |
480 | |
68dc0745 |
481 | SOCKET_TEST_ERROR(r = pioctlsocket(TO_SOCKET(s), cmd, argp)); |
482 | return r; |
0a753a76 |
483 | } |
484 | |
68dc0745 |
485 | int |
486 | win32_listen(SOCKET s, int backlog) |
0a753a76 |
487 | { |
68dc0745 |
488 | int r; |
0a753a76 |
489 | |
68dc0745 |
490 | SOCKET_TEST_ERROR(r = plisten(TO_SOCKET(s), backlog)); |
491 | return r; |
0a753a76 |
492 | } |
493 | |
68dc0745 |
494 | int |
495 | win32_recv(SOCKET s, char *buf, int len, int flags) |
0a753a76 |
496 | { |
68dc0745 |
497 | int r; |
0a753a76 |
498 | |
68dc0745 |
499 | SOCKET_TEST_ERROR(r = precv(TO_SOCKET(s), buf, len, flags)); |
500 | return r; |
0a753a76 |
501 | } |
502 | |
68dc0745 |
503 | int |
504 | win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) |
0a753a76 |
505 | { |
68dc0745 |
506 | int r; |
0a753a76 |
507 | |
68dc0745 |
508 | SOCKET_TEST_ERROR(r = precvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen)); |
509 | return r; |
0a753a76 |
510 | } |
511 | |
68dc0745 |
512 | /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */ |
513 | int |
514 | win32_select(int nfds, int* rd, int* wr, int* ex, const struct timeval* timeout) |
0a753a76 |
515 | { |
68dc0745 |
516 | long r; |
517 | int dummy = 0; |
518 | int i, fd, bit, offset; |
519 | FD_SET nrd, nwr, nex,*prd,*pwr,*pex; |
0a753a76 |
520 | |
68dc0745 |
521 | if (!rd) |
522 | rd = &dummy, prd = NULL; |
523 | else |
524 | prd = &nrd; |
525 | if (!wr) |
526 | wr = &dummy, pwr = NULL; |
527 | else |
528 | pwr = &nwr; |
529 | if (!ex) |
530 | ex = &dummy, pex = NULL; |
531 | else |
532 | pex = &nex; |
0a753a76 |
533 | |
68dc0745 |
534 | FD_ZERO(&nrd); |
535 | FD_ZERO(&nwr); |
536 | FD_ZERO(&nex); |
537 | for (i = 0; i < nfds; i++) { |
538 | fd = TO_SOCKET(i); |
539 | bit = 1L<<(i % (sizeof(int)*8)); |
540 | offset = i / (sizeof(int)*8); |
541 | if (rd[offset] & bit) |
542 | FD_SET(fd, &nrd); |
543 | if (wr[offset] & bit) |
544 | FD_SET(fd, &nwr); |
545 | if (ex[offset] & bit) |
546 | FD_SET(fd, &nex); |
547 | } |
548 | |
549 | SOCKET_TEST_ERROR(r = pselect(nfds, prd, pwr, pex, timeout)); |
0a753a76 |
550 | |
68dc0745 |
551 | for (i = 0; i < nfds; i++) { |
552 | fd = TO_SOCKET(i); |
553 | bit = 1L<<(i % (sizeof(int)*8)); |
554 | offset = i / (sizeof(int)*8); |
555 | if (rd[offset] & bit) { |
556 | if (!pWSAFDIsSet(fd, &nrd)) |
557 | rd[offset] &= ~bit; |
558 | } |
559 | if (wr[offset] & bit) { |
560 | if (!pWSAFDIsSet(fd, &nwr)) |
561 | wr[offset] &= ~bit; |
562 | } |
563 | if (ex[offset] & bit) { |
564 | if (!pWSAFDIsSet(fd, &nex)) |
565 | ex[offset] &= ~bit; |
0a753a76 |
566 | } |
68dc0745 |
567 | } |
568 | return r; |
0a753a76 |
569 | } |
570 | |
68dc0745 |
571 | int |
572 | win32_send(SOCKET s, const char *buf, int len, int flags) |
0a753a76 |
573 | { |
68dc0745 |
574 | int r; |
0a753a76 |
575 | |
68dc0745 |
576 | SOCKET_TEST_ERROR(r = psend(TO_SOCKET(s), buf, len, flags)); |
577 | return r; |
0a753a76 |
578 | } |
579 | |
68dc0745 |
580 | int |
581 | win32_sendto(SOCKET s, const char *buf, int len, int flags, |
582 | const struct sockaddr *to, int tolen) |
0a753a76 |
583 | { |
68dc0745 |
584 | int r; |
0a753a76 |
585 | |
68dc0745 |
586 | SOCKET_TEST_ERROR(r = psendto(TO_SOCKET(s), buf, len, flags, to, tolen)); |
587 | return r; |
0a753a76 |
588 | } |
589 | |
68dc0745 |
590 | int |
591 | win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) |
0a753a76 |
592 | { |
68dc0745 |
593 | int r; |
0a753a76 |
594 | |
68dc0745 |
595 | SOCKET_TEST_ERROR(r = psetsockopt(TO_SOCKET(s), level, optname, optval, optlen)); |
596 | return r; |
0a753a76 |
597 | } |
598 | |
68dc0745 |
599 | int |
600 | win32_shutdown(SOCKET s, int how) |
0a753a76 |
601 | { |
68dc0745 |
602 | int r; |
0a753a76 |
603 | |
68dc0745 |
604 | SOCKET_TEST_ERROR(r = pshutdown(TO_SOCKET(s), how)); |
605 | return r; |
0a753a76 |
606 | } |
607 | |
68dc0745 |
608 | SOCKET |
609 | win32_socket(int af, int type, int protocol) |
0a753a76 |
610 | { |
68dc0745 |
611 | SOCKET s; |
0a753a76 |
612 | |
613 | #ifndef USE_SOCKETS_AS_HANDLES |
68dc0745 |
614 | SOCKET_TEST(s = psocket(af, type, protocol), INVALID_SOCKET); |
0a753a76 |
615 | #else |
68dc0745 |
616 | if(hWinSockDll == 0) |
617 | StartSockets(); |
0a753a76 |
618 | |
68dc0745 |
619 | if((s = psocket(af, type, protocol)) == INVALID_SOCKET) |
620 | errno = pWSAGetLastError(); |
621 | else |
622 | s = OPEN_SOCKET(s); |
623 | #endif /* USE_SOCKETS_AS_HANDLES */ |
0a753a76 |
624 | |
68dc0745 |
625 | return s; |
0a753a76 |
626 | } |
627 | |
68dc0745 |
628 | struct hostent * |
629 | win32_gethostbyaddr(const char *addr, int len, int type) |
0a753a76 |
630 | { |
68dc0745 |
631 | struct hostent *r; |
0a753a76 |
632 | |
68dc0745 |
633 | SOCKET_TEST(r = pgethostbyaddr(addr, len, type), NULL); |
634 | return r; |
0a753a76 |
635 | } |
636 | |
68dc0745 |
637 | struct hostent * |
638 | win32_gethostbyname(const char *name) |
0a753a76 |
639 | { |
68dc0745 |
640 | struct hostent *r; |
0a753a76 |
641 | |
68dc0745 |
642 | SOCKET_TEST(r = pgethostbyname(name), NULL); |
643 | return r; |
0a753a76 |
644 | } |
645 | |
68dc0745 |
646 | int |
647 | win32_gethostname(char *name, int len) |
0a753a76 |
648 | { |
68dc0745 |
649 | int r; |
0a753a76 |
650 | |
68dc0745 |
651 | SOCKET_TEST_ERROR(r = pgethostname(name, len)); |
652 | return r; |
0a753a76 |
653 | } |
654 | |
68dc0745 |
655 | struct protoent * |
656 | win32_getprotobyname(const char *name) |
0a753a76 |
657 | { |
68dc0745 |
658 | struct protoent *r; |
0a753a76 |
659 | |
68dc0745 |
660 | SOCKET_TEST(r = pgetprotobyname(name), NULL); |
661 | return r; |
0a753a76 |
662 | } |
663 | |
68dc0745 |
664 | struct protoent * |
665 | win32_getprotobynumber(int num) |
0a753a76 |
666 | { |
68dc0745 |
667 | struct protoent *r; |
0a753a76 |
668 | |
68dc0745 |
669 | SOCKET_TEST(r = pgetprotobynumber(num), NULL); |
670 | return r; |
0a753a76 |
671 | } |
672 | |
68dc0745 |
673 | struct servent * |
674 | win32_getservbyname(const char *name, const char *proto) |
0a753a76 |
675 | { |
68dc0745 |
676 | struct servent *r; |
677 | |
678 | SOCKET_TEST(r = pgetservbyname(name, proto), NULL); |
679 | if (r) { |
680 | r = win32_savecopyservent(&myservent, r, proto); |
681 | } |
682 | return r; |
0a753a76 |
683 | } |
684 | |
68dc0745 |
685 | struct servent * |
686 | win32_getservbyport(int port, const char *proto) |
0a753a76 |
687 | { |
68dc0745 |
688 | struct servent *r; |
0a753a76 |
689 | |
68dc0745 |
690 | SOCKET_TEST(r = pgetservbyport(port, proto), NULL); |
691 | if (r) { |
692 | r = win32_savecopyservent(&myservent, r, proto); |
693 | } |
694 | return r; |
0a753a76 |
695 | } |
696 | |
68dc0745 |
697 | char FAR * |
698 | win32_inet_ntoa(struct in_addr in) |
0a753a76 |
699 | { |
68dc0745 |
700 | if(hWinSockDll == 0) |
701 | LoadWinSock(); |
0a753a76 |
702 | |
68dc0745 |
703 | return pinet_ntoa(in); |
0a753a76 |
704 | } |
705 | |
68dc0745 |
706 | unsigned long |
707 | win32_inet_addr(const char FAR *cp) |
0a753a76 |
708 | { |
68dc0745 |
709 | if(hWinSockDll == 0) |
710 | LoadWinSock(); |
0a753a76 |
711 | |
68dc0745 |
712 | return pinet_addr(cp); |
0a753a76 |
713 | |
714 | } |
68dc0745 |
715 | |
716 | /* |
717 | * Networking stubs |
718 | */ |
0a753a76 |
719 | #undef CROAK |
720 | #define CROAK croak |
721 | |
68dc0745 |
722 | void |
723 | win32_endhostent() |
0a753a76 |
724 | { |
68dc0745 |
725 | CROAK("endhostent not implemented!\n"); |
0a753a76 |
726 | } |
727 | |
68dc0745 |
728 | void |
729 | win32_endnetent() |
0a753a76 |
730 | { |
68dc0745 |
731 | CROAK("endnetent not implemented!\n"); |
0a753a76 |
732 | } |
733 | |
68dc0745 |
734 | void |
735 | win32_endprotoent() |
0a753a76 |
736 | { |
68dc0745 |
737 | CROAK("endprotoent not implemented!\n"); |
0a753a76 |
738 | } |
739 | |
68dc0745 |
740 | void |
741 | win32_endservent() |
0a753a76 |
742 | { |
68dc0745 |
743 | CROAK("endservent not implemented!\n"); |
0a753a76 |
744 | } |
745 | |
746 | |
68dc0745 |
747 | struct netent * |
748 | win32_getnetent(void) |
0a753a76 |
749 | { |
68dc0745 |
750 | CROAK("getnetent not implemented!\n"); |
751 | return (struct netent *) NULL; |
0a753a76 |
752 | } |
753 | |
68dc0745 |
754 | struct netent * |
755 | win32_getnetbyname(char *name) |
0a753a76 |
756 | { |
68dc0745 |
757 | CROAK("getnetbyname not implemented!\n"); |
758 | return (struct netent *)NULL; |
0a753a76 |
759 | } |
760 | |
68dc0745 |
761 | struct netent * |
762 | win32_getnetbyaddr(long net, int type) |
0a753a76 |
763 | { |
68dc0745 |
764 | CROAK("getnetbyaddr not implemented!\n"); |
765 | return (struct netent *)NULL; |
0a753a76 |
766 | } |
767 | |
68dc0745 |
768 | struct protoent * |
769 | win32_getprotoent(void) |
0a753a76 |
770 | { |
68dc0745 |
771 | CROAK("getprotoent not implemented!\n"); |
772 | return (struct protoent *) NULL; |
0a753a76 |
773 | } |
774 | |
68dc0745 |
775 | struct servent * |
776 | win32_getservent(void) |
0a753a76 |
777 | { |
68dc0745 |
778 | CROAK("getservent not implemented!\n"); |
779 | return (struct servent *) NULL; |
0a753a76 |
780 | } |
781 | |
68dc0745 |
782 | void |
783 | win32_sethostent(int stayopen) |
0a753a76 |
784 | { |
68dc0745 |
785 | CROAK("sethostent not implemented!\n"); |
0a753a76 |
786 | } |
787 | |
788 | |
68dc0745 |
789 | void |
790 | win32_setnetent(int stayopen) |
0a753a76 |
791 | { |
68dc0745 |
792 | CROAK("setnetent not implemented!\n"); |
0a753a76 |
793 | } |
794 | |
795 | |
68dc0745 |
796 | void |
797 | win32_setprotoent(int stayopen) |
0a753a76 |
798 | { |
68dc0745 |
799 | CROAK("setprotoent not implemented!\n"); |
0a753a76 |
800 | } |
801 | |
802 | |
68dc0745 |
803 | void |
804 | win32_setservent(int stayopen) |
0a753a76 |
805 | { |
68dc0745 |
806 | CROAK("setservent not implemented!\n"); |
0a753a76 |
807 | } |
808 | |
809 | |