Commit | Line | Data |
76e3520e |
1 | /* |
2 | |
3 | ipsock.c |
4 | Interface for perl socket functions |
5 | |
6 | */ |
7 | |
8 | #include <ipsock.h> |
9 | #include <fcntl.h> |
10 | |
11 | #define USE_SOCKETS_AS_HANDLES |
12 | |
13 | class CPerlSock : public IPerlSock |
14 | { |
15 | public: |
16 | CPerlSock(); |
17 | ~CPerlSock(); |
18 | virtual u_long Htonl(u_long hostlong); |
19 | virtual u_short Htons(u_short hostshort); |
20 | virtual u_long Ntohl(u_long netlong); |
21 | virtual u_short Ntohs(u_short netshort); |
22 | virtual SOCKET Accept(SOCKET s, struct sockaddr* addr, int* addrlen, int &err); |
23 | virtual int Bind(SOCKET s, const struct sockaddr* name, int namelen, int &err); |
24 | virtual int Connect(SOCKET s, const struct sockaddr* name, int namelen, int &err); |
25 | virtual void Endhostent(int &err); |
26 | virtual void Endnetent(int &err); |
27 | virtual void Endprotoent(int &err); |
28 | virtual void Endservent(int &err); |
29 | virtual struct hostent* Gethostbyaddr(const char* addr, int len, int type, int &err); |
30 | virtual struct hostent* Gethostbyname(const char* name, int &err); |
31 | virtual struct hostent* Gethostent(int &err); |
32 | virtual int Gethostname(char* name, int namelen, int &err); |
33 | virtual struct netent *Getnetbyaddr(long net, int type, int &err); |
34 | virtual struct netent *Getnetbyname(const char *, int &err); |
35 | virtual struct netent *Getnetent(int &err); |
36 | virtual int Getpeername(SOCKET s, struct sockaddr* name, int* namelen, int &err); |
37 | virtual struct protoent* Getprotobyname(const char* name, int &err); |
38 | virtual struct protoent* Getprotobynumber(int number, int &err); |
39 | virtual struct protoent* Getprotoent(int &err); |
40 | virtual struct servent* Getservbyname(const char* name, const char* proto, int &err); |
41 | virtual struct servent* Getservbyport(int port, const char* proto, int &err); |
42 | virtual struct servent* Getservent(int &err); |
43 | virtual int Getsockname(SOCKET s, struct sockaddr* name, int* namelen, int &err); |
44 | virtual int Getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen, int &err); |
45 | virtual unsigned long InetAddr(const char* cp, int &err); |
46 | virtual char* InetNtoa(struct in_addr in, int &err); |
47 | virtual int IoctlSocket(SOCKET s, long cmd, u_long *argp, int& err); |
48 | virtual int Listen(SOCKET s, int backlog, int &err); |
49 | virtual int Recvfrom(SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen, int &err); |
50 | virtual int Select(int nfds, char* readfds, char* writefds, char* exceptfds, const struct timeval* timeout, int &err); |
51 | virtual int Send(SOCKET s, const char* buffer, int len, int flags, int &err); |
52 | virtual int Sendto(SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen, int &err); |
53 | virtual void Sethostent(int stayopen, int &err); |
54 | virtual void Setnetent(int stayopen, int &err); |
55 | virtual void Setprotoent(int stayopen, int &err); |
56 | virtual void Setservent(int stayopen, int &err); |
57 | virtual int Setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen, int &err); |
58 | virtual int Shutdown(SOCKET s, int how, int &err); |
59 | virtual SOCKET Socket(int af, int type, int protocol, int &err); |
60 | virtual int Socketpair(int domain, int type, int protocol, int* fds, int &err); |
61 | |
62 | void CloseSocket(int fh, int& err); |
63 | void* GetAddress(HINSTANCE hInstance, char *lpFunctionName); |
64 | void LoadWinSock(void); |
65 | |
66 | inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; |
67 | inline void SetStdObj(IPerlStdIOWin *p) { pStdIO = p; }; |
68 | protected: |
69 | void Start(void); |
70 | |
71 | inline int OpenOSfhandle(long osfhandle) |
72 | { |
73 | return pStdIO->OpenOSfhandle(osfhandle, O_RDWR|O_BINARY); |
74 | }; |
75 | int GetOSfhandle(int filenum) |
76 | { |
77 | return pStdIO->GetOSfhandle(filenum); |
78 | }; |
79 | |
80 | inline void StartSockets(void) |
81 | { |
82 | if(!bStarted) |
83 | Start(); |
84 | }; |
85 | |
86 | BOOL bStarted; |
87 | CPerlObj *pPerl; |
88 | IPerlStdIOWin *pStdIO; |
89 | }; |
90 | |
91 | |
92 | #define SOCKETAPI PASCAL |
93 | |
94 | typedef SOCKET (SOCKETAPI *LPSOCKACCEPT)(SOCKET, struct sockaddr *, int *); |
95 | typedef int (SOCKETAPI *LPSOCKBIND)(SOCKET, const struct sockaddr *, int); |
96 | typedef int (SOCKETAPI *LPSOCKCLOSESOCKET)(SOCKET); |
97 | typedef int (SOCKETAPI *LPSOCKCONNECT)(SOCKET, const struct sockaddr *, int); |
98 | typedef unsigned long (SOCKETAPI *LPINETADDR)(const char *); |
99 | typedef char* (SOCKETAPI *LPINETNTOA)(struct in_addr); |
100 | typedef int (SOCKETAPI *LPSOCKIOCTLSOCKET)(SOCKET, long, u_long *); |
101 | typedef int (SOCKETAPI *LPSOCKGETPEERNAME)(SOCKET, struct sockaddr *, int *); |
102 | typedef int (SOCKETAPI *LPSOCKGETSOCKNAME)(SOCKET, struct sockaddr *, int *); |
103 | typedef int (SOCKETAPI *LPSOCKGETSOCKOPT)(SOCKET, int, int, char *, int *); |
104 | typedef u_long (SOCKETAPI *LPSOCKHTONL)(u_long); |
105 | typedef u_short (SOCKETAPI *LPSOCKHTONS)(u_short); |
106 | typedef int (SOCKETAPI *LPSOCKLISTEN)(SOCKET, int); |
107 | typedef u_long (SOCKETAPI *LPSOCKNTOHL)(u_long); |
108 | typedef u_short (SOCKETAPI *LPSOCKNTOHS)(u_short); |
109 | typedef int (SOCKETAPI *LPSOCKRECV)(SOCKET, char *, int, int); |
110 | typedef int (SOCKETAPI *LPSOCKRECVFROM)(SOCKET, char *, int, int, struct sockaddr *, int *); |
111 | typedef int (SOCKETAPI *LPSOCKSELECT)(int, fd_set *, fd_set *, fd_set *, const struct timeval *); |
112 | typedef int (SOCKETAPI *LPSOCKSEND)(SOCKET, const char *, int, int); |
113 | typedef int (SOCKETAPI *LPSOCKSENDTO)(SOCKET, const char *, int, int, const struct sockaddr *, int); |
114 | typedef int (SOCKETAPI *LPSOCKSETSOCKOPT)(SOCKET, int, int, const char *, int); |
115 | typedef int (SOCKETAPI *LPSOCKSHUTDOWN)(SOCKET, int); |
116 | typedef SOCKET (SOCKETAPI *LPSOCKSOCKET)(int, int, int); |
117 | |
118 | /* Database function prototypes */ |
119 | typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYADDR)(const char *, int, int); |
120 | typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYNAME)(const char *); |
121 | typedef int (SOCKETAPI *LPSOCKGETHOSTNAME)(char *, int); |
122 | typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYPORT)(int, const char *); |
123 | typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYNAME)(const char *, const char *); |
124 | typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNUMBER)(int); |
125 | typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNAME)(const char *); |
126 | |
127 | /* Microsoft Windows Extension function prototypes */ |
128 | typedef int (SOCKETAPI *LPSOCKWSASTARTUP)(unsigned short, LPWSADATA); |
129 | typedef int (SOCKETAPI *LPSOCKWSACLEANUP)(void); |
130 | typedef int (SOCKETAPI *LPSOCKWSAGETLASTERROR)(void); |
131 | typedef int (SOCKETAPI *LPWSAFDIsSet)(SOCKET, fd_set *); |
132 | |
133 | static HINSTANCE hWinSockDll = 0; |
134 | |
135 | static LPSOCKACCEPT paccept = 0; |
136 | static LPSOCKBIND pbind = 0; |
137 | static LPSOCKCLOSESOCKET pclosesocket = 0; |
138 | static LPSOCKCONNECT pconnect = 0; |
139 | static LPINETADDR pinet_addr = 0; |
140 | static LPINETNTOA pinet_ntoa = 0; |
141 | static LPSOCKIOCTLSOCKET pioctlsocket = 0; |
142 | static LPSOCKGETPEERNAME pgetpeername = 0; |
143 | static LPSOCKGETSOCKNAME pgetsockname = 0; |
144 | static LPSOCKGETSOCKOPT pgetsockopt = 0; |
145 | static LPSOCKHTONL phtonl = 0; |
146 | static LPSOCKHTONS phtons = 0; |
147 | static LPSOCKLISTEN plisten = 0; |
148 | static LPSOCKNTOHL pntohl = 0; |
149 | static LPSOCKNTOHS pntohs = 0; |
150 | static LPSOCKRECV precv = 0; |
151 | static LPSOCKRECVFROM precvfrom = 0; |
152 | static LPSOCKSELECT pselect = 0; |
153 | static LPSOCKSEND psend = 0; |
154 | static LPSOCKSENDTO psendto = 0; |
155 | static LPSOCKSETSOCKOPT psetsockopt = 0; |
156 | static LPSOCKSHUTDOWN pshutdown = 0; |
157 | static LPSOCKSOCKET psocket = 0; |
158 | static LPSOCKGETHOSTBYADDR pgethostbyaddr = 0; |
159 | static LPSOCKGETHOSTBYNAME pgethostbyname = 0; |
160 | static LPSOCKGETHOSTNAME pgethostname = 0; |
161 | static LPSOCKGETSERVBYPORT pgetservbyport = 0; |
162 | static LPSOCKGETSERVBYNAME pgetservbyname = 0; |
163 | static LPSOCKGETPROTOBYNUMBER pgetprotobynumber = 0; |
164 | static LPSOCKGETPROTOBYNAME pgetprotobyname = 0; |
165 | static LPSOCKWSASTARTUP pWSAStartup = 0; |
166 | static LPSOCKWSACLEANUP pWSACleanup = 0; |
167 | static LPSOCKWSAGETLASTERROR pWSAGetLastError = 0; |
168 | static LPWSAFDIsSet pWSAFDIsSet = 0; |
169 | |
170 | void* CPerlSock::GetAddress(HINSTANCE hInstance, char *lpFunctionName) |
171 | { |
172 | char buffer[512]; |
173 | FARPROC proc = GetProcAddress(hInstance, lpFunctionName); |
174 | if(proc == 0) |
175 | { |
176 | sprintf(buffer, "Unable to get address of %s in WSock32.dll", lpFunctionName); |
177 | croak(buffer); |
178 | } |
179 | return proc; |
180 | } |
181 | |
182 | void CPerlSock::LoadWinSock(void) |
183 | { |
184 | if(hWinSockDll == NULL) |
185 | { |
186 | HINSTANCE hLib = LoadLibrary("WSock32.DLL"); |
187 | if(hLib == NULL) |
188 | croak("Could not load WSock32.dll\n"); |
189 | |
190 | paccept = (LPSOCKACCEPT)GetAddress(hLib, "accept"); |
191 | pbind = (LPSOCKBIND)GetAddress(hLib, "bind"); |
192 | pclosesocket = (LPSOCKCLOSESOCKET)GetAddress(hLib, "closesocket"); |
193 | pconnect = (LPSOCKCONNECT)GetAddress(hLib, "connect"); |
194 | pinet_addr = (LPINETADDR)GetAddress(hLib, "inet_addr"); |
195 | pinet_ntoa = (LPINETNTOA)GetAddress(hLib, "inet_ntoa"); |
196 | pioctlsocket = (LPSOCKIOCTLSOCKET)GetAddress(hLib, "ioctlsocket"); |
197 | pgetpeername = (LPSOCKGETPEERNAME)GetAddress(hLib, "getpeername"); |
198 | pgetsockname = (LPSOCKGETSOCKNAME)GetAddress(hLib, "getsockname"); |
199 | pgetsockopt = (LPSOCKGETSOCKOPT)GetAddress(hLib, "getsockopt"); |
200 | phtonl = (LPSOCKHTONL)GetAddress(hLib, "htonl"); |
201 | phtons = (LPSOCKHTONS)GetAddress(hLib, "htons"); |
202 | plisten = (LPSOCKLISTEN)GetAddress(hLib, "listen"); |
203 | pntohl = (LPSOCKNTOHL)GetAddress(hLib, "ntohl"); |
204 | pntohs = (LPSOCKNTOHS)GetAddress(hLib, "ntohs"); |
205 | precv = (LPSOCKRECV)GetAddress(hLib, "recv"); |
206 | precvfrom = (LPSOCKRECVFROM)GetAddress(hLib, "recvfrom"); |
207 | pselect = (LPSOCKSELECT)GetAddress(hLib, "select"); |
208 | psend = (LPSOCKSEND)GetAddress(hLib, "send"); |
209 | psendto = (LPSOCKSENDTO)GetAddress(hLib, "sendto"); |
210 | psetsockopt = (LPSOCKSETSOCKOPT)GetAddress(hLib, "setsockopt"); |
211 | pshutdown = (LPSOCKSHUTDOWN)GetAddress(hLib, "shutdown"); |
212 | psocket = (LPSOCKSOCKET)GetAddress(hLib, "socket"); |
213 | pgethostbyaddr = (LPSOCKGETHOSTBYADDR)GetAddress(hLib, "gethostbyaddr"); |
214 | pgethostbyname = (LPSOCKGETHOSTBYNAME)GetAddress(hLib, "gethostbyname"); |
215 | pgethostname = (LPSOCKGETHOSTNAME)GetAddress(hLib, "gethostname"); |
216 | pgetservbyport = (LPSOCKGETSERVBYPORT)GetAddress(hLib, "getservbyport"); |
217 | pgetservbyname = (LPSOCKGETSERVBYNAME)GetAddress(hLib, "getservbyname"); |
218 | pgetprotobynumber = (LPSOCKGETPROTOBYNUMBER)GetAddress(hLib, "getprotobynumber"); |
219 | pgetprotobyname = (LPSOCKGETPROTOBYNAME)GetAddress(hLib, "getprotobyname"); |
220 | pWSAStartup = (LPSOCKWSASTARTUP)GetAddress(hLib, "WSAStartup"); |
221 | pWSACleanup = (LPSOCKWSACLEANUP)GetAddress(hLib, "WSACleanup"); |
222 | pWSAGetLastError = (LPSOCKWSAGETLASTERROR)GetAddress(hLib, "WSAGetLastError"); |
223 | pWSAFDIsSet = (LPWSAFDIsSet)GetAddress(hLib, "__WSAFDIsSet"); |
224 | hWinSockDll = hLib; |
225 | } |
226 | } |
227 | |
228 | |
229 | CPerlSock::CPerlSock() |
230 | { |
231 | bStarted = FALSE; |
232 | pPerl = NULL; |
233 | pStdIO = NULL; |
234 | } |
235 | |
236 | CPerlSock::~CPerlSock() |
237 | { |
238 | if(bStarted) |
239 | pWSACleanup(); |
240 | } |
241 | |
242 | void |
243 | CPerlSock::Start(void) |
244 | { |
245 | unsigned short version; |
246 | WSADATA retdata; |
247 | int ret; |
248 | int iSockOpt = SO_SYNCHRONOUS_NONALERT; |
249 | |
250 | LoadWinSock(); |
251 | /* |
252 | * initalize the winsock interface and insure that it is |
253 | * cleaned up at exit. |
254 | */ |
255 | version = 0x101; |
256 | if(ret = pWSAStartup(version, &retdata)) |
257 | croak("Unable to locate winsock library!\n"); |
258 | if(retdata.wVersion != version) |
259 | croak("Could not find version 1.1 of winsock dll\n"); |
260 | |
261 | /* atexit((void (*)(void)) EndSockets); */ |
262 | |
263 | #ifdef USE_SOCKETS_AS_HANDLES |
264 | /* |
265 | * Enable the use of sockets as filehandles |
266 | */ |
267 | psetsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, |
268 | (char *)&iSockOpt, sizeof(iSockOpt)); |
269 | #endif /* USE_SOCKETS_AS_HANDLES */ |
270 | bStarted = TRUE; |
271 | } |
272 | |
273 | |
274 | u_long |
275 | CPerlSock::Htonl(u_long hostlong) |
276 | { |
277 | StartSockets(); |
278 | return phtonl(hostlong); |
279 | } |
280 | |
281 | u_short |
282 | CPerlSock::Htons(u_short hostshort) |
283 | { |
284 | StartSockets(); |
285 | return phtons(hostshort); |
286 | } |
287 | |
288 | u_long |
289 | CPerlSock::Ntohl(u_long netlong) |
290 | { |
291 | StartSockets(); |
292 | return pntohl(netlong); |
293 | } |
294 | |
295 | u_short |
296 | CPerlSock::Ntohs(u_short netshort) |
297 | { |
298 | StartSockets(); |
299 | return pntohs(netshort); |
300 | } |
301 | |
302 | |
303 | /* thanks to Beverly Brown (beverly@datacube.com) */ |
304 | #ifdef USE_SOCKETS_AS_HANDLES |
305 | # define OPEN_SOCKET(x) OpenOSfhandle(x) |
306 | # define TO_SOCKET(x) GetOSfhandle(x) |
307 | #else |
308 | # define OPEN_SOCKET(x) (x) |
309 | # define TO_SOCKET(x) (x) |
310 | #endif /* USE_SOCKETS_AS_HANDLES */ |
311 | |
312 | #define SOCKET_TEST(x, y) \ |
313 | STMT_START { \ |
314 | StartSockets(); \ |
315 | if((x) == (y)) \ |
316 | err = pWSAGetLastError(); \ |
317 | } STMT_END |
318 | |
319 | #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) |
320 | |
321 | SOCKET |
322 | CPerlSock::Accept(SOCKET s, struct sockaddr* addr, int* addrlen, int &err) |
323 | { |
324 | SOCKET r; |
325 | |
326 | SOCKET_TEST((r = paccept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); |
327 | return OPEN_SOCKET(r); |
328 | } |
329 | |
330 | int |
331 | CPerlSock::Bind(SOCKET s, const struct sockaddr* addr, int addrlen, int &err) |
332 | { |
333 | int r; |
334 | |
335 | SOCKET_TEST_ERROR(r = pbind(TO_SOCKET(s), addr, addrlen)); |
336 | return r; |
337 | } |
338 | |
339 | void |
340 | CPerlSock::CloseSocket(int fh, int& err) |
341 | { |
342 | SOCKET_TEST_ERROR(pclosesocket(TO_SOCKET(fh))); |
343 | } |
344 | |
345 | int |
346 | CPerlSock::Connect(SOCKET s, const struct sockaddr* addr, int addrlen, int &err) |
347 | { |
348 | int r; |
349 | |
350 | SOCKET_TEST_ERROR(r = pconnect(TO_SOCKET(s), addr, addrlen)); |
351 | return r; |
352 | } |
353 | |
354 | void CPerlSock::Endhostent(int &err) |
355 | { |
356 | croak("endhostent not implemented!\n"); |
357 | } |
358 | |
359 | void CPerlSock::Endnetent(int &err) |
360 | { |
361 | croak("endnetent not implemented!\n"); |
362 | } |
363 | |
364 | void CPerlSock::Endprotoent(int &err) |
365 | { |
366 | croak("endprotoent not implemented!\n"); |
367 | } |
368 | |
369 | void CPerlSock::Endservent(int &err) |
370 | { |
371 | croak("endservent not implemented!\n"); |
372 | } |
373 | |
374 | struct hostent* |
375 | CPerlSock::Gethostbyaddr(const char* addr, int len, int type, int &err) |
376 | { |
377 | struct hostent *r; |
378 | |
379 | SOCKET_TEST(r = pgethostbyaddr(addr, len, type), NULL); |
380 | return r; |
381 | } |
382 | |
383 | struct hostent* |
384 | CPerlSock::Gethostbyname(const char* name, int &err) |
385 | { |
386 | struct hostent *r; |
387 | |
388 | SOCKET_TEST(r = pgethostbyname(name), NULL); |
389 | return r; |
390 | } |
391 | |
392 | struct hostent* CPerlSock::Gethostent(int &err) |
393 | { |
394 | croak("gethostent not implemented!\n"); |
395 | return NULL; |
396 | } |
397 | |
398 | int |
399 | CPerlSock::Gethostname(char* name, int len, int &err) |
400 | { |
401 | int r; |
402 | |
403 | SOCKET_TEST_ERROR(r = pgethostname(name, len)); |
404 | return r; |
405 | } |
406 | |
407 | struct netent *CPerlSock::Getnetbyaddr(long net, int type, int &err) |
408 | { |
409 | croak("getnetbyaddr not implemented!\n"); |
410 | return NULL; |
411 | } |
412 | |
413 | struct netent *CPerlSock::Getnetbyname(const char *, int &err) |
414 | { |
415 | croak("getnetbyname not implemented!\n"); |
416 | return NULL; |
417 | } |
418 | |
419 | struct netent *CPerlSock::Getnetent(int &err) |
420 | { |
421 | croak("getnetent not implemented!\n"); |
422 | return NULL; |
423 | } |
424 | |
425 | int |
426 | CPerlSock::Getpeername(SOCKET s, struct sockaddr* addr, int* addrlen, int &err) |
427 | { |
428 | int r; |
429 | |
430 | SOCKET_TEST_ERROR(r = pgetpeername(TO_SOCKET(s), addr, addrlen)); |
431 | return r; |
432 | } |
433 | |
434 | struct protoent* |
435 | CPerlSock::Getprotobyname(const char* name, int &err) |
436 | { |
437 | struct protoent *r; |
438 | |
439 | SOCKET_TEST(r = pgetprotobyname(name), NULL); |
440 | return r; |
441 | } |
442 | |
443 | struct protoent* |
444 | CPerlSock::Getprotobynumber(int number, int &err) |
445 | { |
446 | struct protoent *r; |
447 | |
448 | SOCKET_TEST(r = pgetprotobynumber(number), NULL); |
449 | return r; |
450 | } |
451 | |
452 | struct protoent* CPerlSock::Getprotoent(int &err) |
453 | { |
454 | croak("getprotoent not implemented!\n"); |
455 | return NULL; |
456 | } |
457 | |
458 | struct servent* |
459 | CPerlSock::Getservbyname(const char* name, const char* proto, int &err) |
460 | { |
461 | struct servent *r; |
462 | dTHR; |
463 | |
464 | SOCKET_TEST(r = pgetservbyname(name, proto), NULL); |
465 | // if (r) { |
466 | // r = win32_savecopyservent(&myservent, r, proto); |
467 | // } |
468 | return r; |
469 | } |
470 | |
471 | struct servent* |
472 | CPerlSock::Getservbyport(int port, const char* proto, int &err) |
473 | { |
474 | struct servent *r; |
475 | dTHR; |
476 | |
477 | SOCKET_TEST(r = pgetservbyport(port, proto), NULL); |
478 | // if (r) { |
479 | // r = win32_savecopyservent(&myservent, r, proto); |
480 | // } |
481 | return r; |
482 | } |
483 | |
484 | struct servent* CPerlSock::Getservent(int &err) |
485 | { |
486 | croak("getservent not implemented!\n"); |
487 | return NULL; |
488 | } |
489 | |
490 | int |
491 | CPerlSock::Getsockname(SOCKET s, struct sockaddr* addr, int* addrlen, int &err) |
492 | { |
493 | int r; |
494 | |
495 | SOCKET_TEST_ERROR(r = pgetsockname(TO_SOCKET(s), addr, addrlen)); |
496 | return r; |
497 | } |
498 | |
499 | int |
500 | CPerlSock::Getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen, int &err) |
501 | { |
502 | int r; |
503 | |
504 | SOCKET_TEST_ERROR(r = pgetsockopt(TO_SOCKET(s), level, optname, optval, optlen)); |
505 | return r; |
506 | } |
507 | |
508 | unsigned long |
509 | CPerlSock::InetAddr(const char* cp, int &err) |
510 | { |
511 | unsigned long r; |
512 | |
513 | SOCKET_TEST(r = pinet_addr(cp), INADDR_NONE); |
514 | return r; |
515 | } |
516 | |
517 | char* |
518 | CPerlSock::InetNtoa(struct in_addr in, int &err) |
519 | { |
520 | char* r; |
521 | |
522 | SOCKET_TEST(r = pinet_ntoa(in), NULL); |
523 | return r; |
524 | } |
525 | |
526 | int |
527 | CPerlSock::IoctlSocket(SOCKET s, long cmd, u_long *argp, int& err) |
528 | { |
529 | int r; |
530 | |
531 | SOCKET_TEST_ERROR(r = pioctlsocket(TO_SOCKET(s), cmd, argp)); |
532 | return r; |
533 | } |
534 | |
535 | int |
536 | CPerlSock::Listen(SOCKET s, int backlog, int &err) |
537 | { |
538 | int r; |
539 | |
540 | SOCKET_TEST_ERROR(r = plisten(TO_SOCKET(s), backlog)); |
541 | return r; |
542 | } |
543 | |
544 | int |
545 | CPerlSock::Recvfrom(SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen, int &err) |
546 | { |
547 | int r; |
548 | |
549 | SOCKET_TEST_ERROR(r = precvfrom(TO_SOCKET(s), buffer, len, flags, from, fromlen)); |
550 | return r; |
551 | } |
552 | |
553 | int |
554 | CPerlSock::Select(int nfds, char* rd, char* wr, char* ex, const struct timeval* timeout, int &err) |
555 | { |
556 | long r; |
557 | int i, fd, bit, offset; |
558 | FD_SET nrd, nwr, nex; |
559 | |
560 | FD_ZERO(&nrd); |
561 | FD_ZERO(&nwr); |
562 | FD_ZERO(&nex); |
563 | for (i = 0; i < nfds; i++) |
564 | { |
565 | fd = TO_SOCKET(i); |
566 | bit = 1L<<(i % (sizeof(char)*8)); |
567 | offset = i / (sizeof(char)*8); |
568 | if(rd != NULL && (rd[offset] & bit)) |
569 | FD_SET(fd, &nrd); |
570 | if(wr != NULL && (wr[offset] & bit)) |
571 | FD_SET(fd, &nwr); |
572 | if(ex != NULL && (ex[offset] & bit)) |
573 | FD_SET(fd, &nex); |
574 | } |
575 | SOCKET_TEST_ERROR(r = pselect(nfds, &nrd, &nwr, &nex, timeout)); |
576 | |
577 | for(i = 0; i < nfds; i++) |
578 | { |
579 | fd = TO_SOCKET(i); |
580 | bit = 1L<<(i % (sizeof(char)*8)); |
581 | offset = i / (sizeof(char)*8); |
582 | if(rd != NULL && (rd[offset] & bit)) |
583 | { |
584 | if(!pWSAFDIsSet(fd, &nrd)) |
585 | rd[offset] &= ~bit; |
586 | } |
587 | if(wr != NULL && (wr[offset] & bit)) |
588 | { |
589 | if(!pWSAFDIsSet(fd, &nwr)) |
590 | wr[offset] &= ~bit; |
591 | } |
592 | if(ex != NULL && (ex[offset] & bit)) |
593 | { |
594 | if(!pWSAFDIsSet(fd, &nex)) |
595 | ex[offset] &= ~bit; |
596 | } |
597 | } |
598 | return r; |
599 | } |
600 | |
601 | int |
602 | CPerlSock::Send(SOCKET s, const char* buffer, int len, int flags, int &err) |
603 | { |
604 | int r; |
605 | |
606 | SOCKET_TEST_ERROR(r = psend(TO_SOCKET(s), buffer, len, flags)); |
607 | return r; |
608 | } |
609 | |
610 | int |
611 | CPerlSock::Sendto(SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen, int &err) |
612 | { |
613 | int r; |
614 | |
615 | SOCKET_TEST_ERROR(r = psendto(TO_SOCKET(s), buffer, len, flags, to, tolen)); |
616 | return r; |
617 | } |
618 | |
619 | void CPerlSock::Sethostent(int stayopen, int &err) |
620 | { |
621 | croak("sethostent not implemented!\n"); |
622 | } |
623 | |
624 | void CPerlSock::Setnetent(int stayopen, int &err) |
625 | { |
626 | croak("setnetent not implemented!\n"); |
627 | } |
628 | |
629 | void CPerlSock::Setprotoent(int stayopen, int &err) |
630 | { |
631 | croak("setprotoent not implemented!\n"); |
632 | } |
633 | |
634 | void CPerlSock::Setservent(int stayopen, int &err) |
635 | { |
636 | croak("setservent not implemented!\n"); |
637 | } |
638 | |
639 | int |
640 | CPerlSock::Setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen, int &err) |
641 | { |
642 | int r; |
643 | |
644 | SOCKET_TEST_ERROR(r = psetsockopt(TO_SOCKET(s), level, optname, optval, optlen)); |
645 | return r; |
646 | } |
647 | |
648 | int |
649 | CPerlSock::Shutdown(SOCKET s, int how, int &err) |
650 | { |
651 | int r; |
652 | |
653 | SOCKET_TEST_ERROR(r = pshutdown(TO_SOCKET(s), how)); |
654 | return r; |
655 | } |
656 | |
657 | SOCKET |
658 | CPerlSock::Socket(int af, int type, int protocol, int &err) |
659 | { |
660 | SOCKET s; |
661 | |
662 | #ifdef USE_SOCKETS_AS_HANDLES |
663 | StartSockets(); |
664 | if((s = psocket(af, type, protocol)) == INVALID_SOCKET) |
665 | err = pWSAGetLastError(); |
666 | else |
667 | s = OPEN_SOCKET(s); |
668 | #else |
669 | SOCKET_TEST(s = psocket(af, type, protocol), INVALID_SOCKET); |
670 | #endif /* USE_SOCKETS_AS_HANDLES */ |
671 | |
672 | return s; |
673 | } |
674 | |
675 | int CPerlSock::Socketpair(int domain, int type, int protocol, int* fds, int &err) |
676 | { |
677 | croak("socketpair not implemented!\n"); |
678 | return 0; |
679 | } |
680 | |
681 | |