source: trunk/src/wsock32/wsock32.cpp@ 7073

Last change on this file since 7073 was 7073, checked in by phaller, 24 years ago

Support for socket timeouts

File size: 44.7 KB
Line 
1/* $Id: wsock32.cpp,v 1.44 2001-10-16 07:26:43 phaller Exp $ */
2
3/*
4 *
5 * Project Odin Software License can be found in LICENSE.TXT
6 *
7 * Win32 SOCK32 for OS/2
8 *
9 * Copyright (C) 1999 Patrick Haller <phaller@gmx.net>
10 * Copyright (C) 2000 Sander van Leeuwen (sandervl@xs4all.nl)
11 *
12 * Some parts based on Wine code: (dlls\winsock\socket.c)
13 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
14 *
15 */
16
17/* Remark:
18 * 1999/11/21 experimental rewrite using IBM's PMWSock only
19 * -> some structural differences remain! (hostent)
20 * 1999/12/01 experimental rewrite works (TELNET)
21 * -> open issue: WSASetLastError / WSAGetLastError
22 * call SetLastError / GetLastError according to docs
23 *
24 * 2000/22/03 Complete rewrite -> got rid of pmwsock
25 *
26 * identical structures:
27 * - sockaddr_in
28 * - WSADATA
29 * - sockaddr
30 * - fd_set
31 * - timeval
32 *
33 * incompatible structures:
34 * - hostent
35 * - netent
36 * - servent
37 * - protent
38 * - linger
39 */
40
41
42/*****************************************************************************
43 * Includes *
44 *****************************************************************************/
45
46#define INCL_BASE
47#include <os2wrap.h> //Odin32 OS/2 api wrappers
48
49#include <string.h>
50#include <odinwrap.h>
51#include <os2sel.h>
52#include <stdlib.h>
53#include <win32api.h>
54#define NO_DCDATA
55#include <winuser32.h>
56#include <wprocess.h>
57#include <misc.h>
58
59#include "wsock32.h"
60#include <ws2tcpip.h>
61#include "wsastruct.h"
62#include "asyncthread.h"
63
64#define DBG_LOCALLOG DBG_wsock32
65#include "dbglocal.h"
66
67//kso: dirty fix to make this compile! not permanent!
68BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *p);
69#define LowPart u.LowPart
70
71
72ODINDEBUGCHANNEL(WSOCK32-WSOCK32)
73
74
75/*****************************************************************************
76 * Local variables *
77 *****************************************************************************/
78
79static LPWSINFO lpFirstIData = NULL;
80
81
82//******************************************************************************
83//******************************************************************************
84
85// Note: for the TCP/IP 4.0 headers, SO_SNDTIMEO and SO_RCDTIMEO are
86// unfortunately not defined, so we do this here.
87#ifndef SO_SNDTIMEO
88#define SO_SNDTIMEO 0x1005
89#endif
90
91#ifndef SO_RCVTIMEO
92#define SO_RCVTIMEO 0x1006
93#endif
94
95
96//******************************************************************************
97//******************************************************************************
98LPWSINFO WINSOCK_GetIData(HANDLE tid)
99{
100 LPWSINFO iData;
101 BOOL fCurrentThread = FALSE;
102
103 if(tid == CURRENT_THREAD) {
104 tid = GetCurrentThread();
105 fCurrentThread = TRUE;
106 }
107tryagain:
108 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
109 if (iData->dwThisThread == tid)
110 break;
111 }
112 if(iData == NULL && fCurrentThread) {
113 WINSOCK_CreateIData();
114 fCurrentThread = FALSE; //just to prevent infinite loops
115 goto tryagain;
116 }
117 if(iData == NULL) {
118 dprintf(("WINSOCK_GetIData: couldn't find struct for thread %x", tid));
119 DebugInt3();// should never happen!!!!!!!
120 }
121 return iData;
122}
123//******************************************************************************
124//******************************************************************************
125BOOL WINSOCK_CreateIData(void)
126{
127 LPWSINFO iData;
128
129 iData = (LPWSINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
130 if (!iData)
131 return FALSE;
132 iData->dwThisThread = GetCurrentThread();
133 iData->lpNextIData = lpFirstIData;
134 lpFirstIData = iData;
135 return TRUE;
136}
137//******************************************************************************
138//******************************************************************************
139void WINSOCK_DeleteIData(void)
140{
141 LPWSINFO iData = WINSOCK_GetIData();
142 LPWSINFO* ppid;
143 if (iData) {
144 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
145 if (*ppid == iData) {
146 *ppid = iData->lpNextIData;
147 break;
148 }
149 }
150
151 if( iData->flags & WSI_BLOCKINGCALL )
152 dprintf(("\tinside blocking call!\n"));
153
154 /* delete scratch buffers */
155 if(iData->he) free(iData->he);
156 if(iData->se) free(iData->se);
157 if(iData->pe) free(iData->pe);
158
159 //// if( iData->buffer ) SEGPTR_FREE(iData->buffer);
160 //// if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
161
162 HeapFree(GetProcessHeap(), 0, iData);
163 }
164}
165//******************************************************************************
166//******************************************************************************
167void WIN32API WSASetLastError(int iError)
168{
169#ifdef DEBUG
170 char msg[20];
171#endif
172 // according to the docs, WSASetLastError() is just a call-through
173 // to SetLastError()
174 SetLastError(iError);
175#ifdef DEBUG
176 switch (iError)
177 {
178 case NO_ERROR:
179 strcpy(msg, "no error");
180 break;
181 case WSAEINTR:
182 strcpy(msg, "WSAEINTR");
183 break;
184 case WSAEBADF:
185 strcpy(msg, "WSAEBADF");
186 break;
187 case WSAEACCES:
188 strcpy(msg, "WSAEACCES");
189 break;
190 case WSAEFAULT:
191 strcpy(msg, "WSAEFAULT");
192 break;
193 case WSAEINVAL:
194 strcpy(msg, "WSAEINVAL");
195 break;
196 case WSAEMFILE:
197 strcpy(msg, "WSAEMFILE");
198 break;
199 case WSAEWOULDBLOCK:
200 strcpy(msg, "WSAEWOULDBLOCK");
201 break;
202 case WSAEINPROGRESS:
203 strcpy(msg, "WSAEINPROGRESS");
204 break;
205 case WSAEALREADY:
206 strcpy(msg, "WSAEALREADY");
207 break;
208 default:
209 strcpy(msg, "unknown");
210 }
211 if (iError != 0)
212 {
213 dprintf(("WSASetLastError 0x%x - %s", iError, msg));
214 }
215#endif
216}
217//******************************************************************************
218//******************************************************************************
219int WIN32API WSAGetLastError()
220{
221 return GetLastError();
222}
223//******************************************************************************
224//******************************************************************************
225ODINFUNCTION2(int,OS2shutdown,
226 SOCKET,s,
227 int,how)
228{
229 int ret;
230
231 if(!fWSAInitialized) {
232 WSASetLastError(WSANOTINITIALISED);
233 return SOCKET_ERROR;
234 }
235 else
236 if(WSAIsBlocking()) {
237 WSASetLastError(WSAEINPROGRESS);
238 return SOCKET_ERROR;
239 }
240 ret = shutdown(s, how);
241
242 if(ret == SOCKET_ERROR) {
243 WSASetLastError(wsaErrno());
244 }
245 else WSASetLastError(NO_ERROR);
246 return ret;
247}
248//******************************************************************************
249//******************************************************************************
250ODINFUNCTION3(SOCKET,OS2socket,
251 int,af,
252 int,type,
253 int,protocol)
254{
255 SOCKET s;
256
257 if(!fWSAInitialized) {
258 WSASetLastError(WSANOTINITIALISED);
259 return SOCKET_ERROR;
260 }
261 else
262 if(WSAIsBlocking()) {
263 WSASetLastError(WSAEINPROGRESS);
264 return SOCKET_ERROR;
265 }
266 s = socket(af, type, protocol);
267
268 if(s == SOCKET_ERROR && sock_errno() == SOCEPFNOSUPPORT) {
269 //map SOCEPFNOSUPPORT to SOCEPFNOSUPPORT
270 WSASetLastError(SOCEPFNOSUPPORT);
271 }
272 else
273 if(s == SOCKET_ERROR) {
274 WSASetLastError(wsaErrno());
275 }
276 else WSASetLastError(NO_ERROR);
277 return s;
278}
279//******************************************************************************
280//******************************************************************************
281ODINFUNCTION1(int,OS2closesocket,SOCKET, s)
282{
283 int ret;
284
285 if(!fWSAInitialized) {
286 WSASetLastError(WSANOTINITIALISED);
287 return SOCKET_ERROR;
288 }
289 else
290 if(WSAIsBlocking()) {
291 WSASetLastError(WSAEINPROGRESS);
292 return SOCKET_ERROR;
293 }
294 //Close WSAAsyncSelect thread if one was created for this socket
295 FindAndSetAsyncEvent(s, WSA_SELECT_HWND, 0, 0, 0);
296
297 // wait thread termination
298 DosSleep(10);
299 ret = soclose(s);
300
301 if(ret == SOCKET_ERROR) {
302 WSASetLastError(wsaErrno());
303 }
304 else WSASetLastError(NO_ERROR);
305 return ret;
306}
307//******************************************************************************
308//******************************************************************************
309ODINFUNCTION3(int,OS2connect,
310 SOCKET, s,
311 const struct sockaddr *,name,
312 int, namelen)
313{
314 int ret;
315
316 if(!fWSAInitialized) {
317 WSASetLastError(WSANOTINITIALISED);
318 return SOCKET_ERROR;
319 }
320 else
321 if(WSAIsBlocking()) {
322 WSASetLastError(WSAEINPROGRESS);
323 return SOCKET_ERROR;
324 }
325 ret = connect(s, (sockaddr *)name, namelen);
326 // map BSD error codes
327 if(ret == SOCKET_ERROR) {
328 int sockerror = sock_errno();
329 if(sockerror && sockerror < SOCBASEERR) {
330 sockerror += SOCBASEERR;
331 }
332 if(sockerror == SOCEINPROGRESS) {
333 WSASetLastError(WSAEWOULDBLOCK);
334 }
335 else
336 if(sockerror == SOCEOPNOTSUPP) {
337 WSASetLastError(WSAEINVAL);
338 }
339 else WSASetLastError(wsaErrno());
340 }
341 else WSASetLastError(NO_ERROR);
342 return ret;
343}
344//******************************************************************************
345//******************************************************************************
346ODINFUNCTION3(int,OS2ioctlsocket,
347 SOCKET,s,
348 long, cmd,
349 u_long *,argp)
350{
351 int ret;
352
353 if(!fWSAInitialized) {
354 WSASetLastError(WSANOTINITIALISED);
355 return SOCKET_ERROR;
356 }
357 else
358 if(WSAIsBlocking()) {
359 WSASetLastError(WSAEINPROGRESS);
360 return SOCKET_ERROR;
361 }
362 // clear high word (not used in OS/2's tcpip stack)
363 cmd = LOUSHORT(cmd);
364
365 if(cmd != FIONBIO && cmd != FIONREAD && cmd != SIOCATMARK) {
366 WSASetLastError(WSAEINVAL);
367 return SOCKET_ERROR;
368 }
369
370 WSASetLastError(NO_ERROR);
371
372 //check if app want to set a socket, which has an outstanding async select,
373 //to blocking mode
374 if (cmd == FIONBIO) {
375 HWND hwnd;
376 int msg;
377 ULONG lEvent;
378
379 if(QueryAsyncEvent(s, &hwnd, &msg, &lEvent) == TRUE) {
380 if(*argp != 0) {
381 //nothing to do; already non-blocking
382 return NO_ERROR;
383 }
384 else
385 if(lEvent != 0) {
386 dprintf(("Trying to set socket to blocking mode while async select active -> return error!"));
387 WSASetLastError(WSAEINVAL);
388 return SOCKET_ERROR;
389 }
390 }
391 }
392 ret = ioctl(s, cmd, (char *)argp, sizeof(int));
393
394 // Map EOPNOTSUPP to EINVAL
395 int sockerror = sock_errno();
396 if(sockerror && sockerror < SOCBASEERR) {
397 sockerror += SOCBASEERR;
398 }
399
400 if(ret == SOCKET_ERROR && sockerror == SOCEOPNOTSUPP)
401 WSASetLastError(WSAEINVAL);
402 else
403 if(ret == SOCKET_ERROR) {
404 WSASetLastError(wsaErrno());
405 }
406 else WSASetLastError(NO_ERROR);
407 return ret;
408}
409//******************************************************************************
410//******************************************************************************
411ODINFUNCTION3(int,OS2getpeername,
412 SOCKET, s,
413 struct sockaddr *,name,
414 int *, namelen)
415{
416 int ret;
417
418 if(!fWSAInitialized) {
419 WSASetLastError(WSANOTINITIALISED);
420 return SOCKET_ERROR;
421 }
422 else
423 if(WSAIsBlocking()) {
424 WSASetLastError(WSAEINPROGRESS);
425 return SOCKET_ERROR;
426 }
427 else
428 if (namelen == NULL || *namelen < (int)sizeof(struct sockaddr_in)) {
429 WSASetLastError(WSAEFAULT);
430 return SOCKET_ERROR;
431 }
432 ret = getsockname(s, name, namelen);
433 if(ret == SOCKET_ERROR) {
434 WSASetLastError(wsaErrno());
435 }
436 else WSASetLastError(NO_ERROR);
437 return ret;
438}
439//******************************************************************************
440//******************************************************************************
441ODINFUNCTION3(int,OS2getsockname,
442 SOCKET,s,
443 struct sockaddr *,name,
444 int *, namelen)
445{
446 int ret;
447
448 if(!fWSAInitialized) {
449 WSASetLastError(WSANOTINITIALISED);
450 return SOCKET_ERROR;
451 }
452 else
453 if(WSAIsBlocking()) {
454 WSASetLastError(WSAEINPROGRESS);
455 return SOCKET_ERROR;
456 }
457 else
458 if (namelen == NULL || *namelen < (int)sizeof(struct sockaddr_in)) {
459 WSASetLastError(WSAEFAULT);
460 return SOCKET_ERROR;
461 }
462 ret = getsockname(s, name, namelen);
463 if(ret == SOCKET_ERROR) {
464 WSASetLastError(wsaErrno());
465 }
466 else WSASetLastError(NO_ERROR);
467 return ret;
468}
469//******************************************************************************
470//******************************************************************************
471ODINFUNCTION1(u_long,OS2htonl,
472 u_long,hostlong)
473{
474 return(htonl(hostlong));
475}
476//******************************************************************************
477//******************************************************************************
478ODINFUNCTION1(u_short,OS2htons,
479 u_short,hostshort)
480{
481 return(htons(hostshort));
482}
483//******************************************************************************
484//******************************************************************************
485ODINFUNCTION1(u_long,OS2ntohl,
486 u_long,netlong)
487{
488 return(ntohl(netlong));
489}
490//******************************************************************************
491//******************************************************************************
492ODINFUNCTION1(u_short,OS2ntohs,
493 u_short,netshort)
494{
495 return(ntohs(netshort));
496}
497//******************************************************************************
498//******************************************************************************
499ODINFUNCTION1(unsigned long,OS2inet_addr,
500 const char *, cp)
501{
502 dprintf(("WSOCK32: OS2inet_addr(%s)\n",
503 cp));
504
505 return (inet_addr((char *)cp));
506}
507//******************************************************************************
508//******************************************************************************
509ODINFUNCTION1(char *,OS2inet_ntoa,
510 struct in_addr, in)
511{
512 return(inet_ntoa(in));
513}
514//******************************************************************************
515//******************************************************************************
516ODINFUNCTION3(SOCKET,OS2accept, SOCKET, s,
517 struct sockaddr *,addr,
518 int *, addrlen)
519{
520 int ret, msg;
521 HWND hwnd;
522 ULONG lEvent;
523
524 if(!fWSAInitialized) {
525 WSASetLastError(WSANOTINITIALISED);
526 return SOCKET_ERROR;
527 }
528 else
529 if(WSAIsBlocking()) {
530 WSASetLastError(WSAEINPROGRESS);
531 return SOCKET_ERROR;
532 }
533 else
534 if ((addr != NULL) && (addrlen != NULL)) {
535 if (*addrlen < (int)sizeof(struct sockaddr_in)) {
536 WSASetLastError(WSAEFAULT);
537 return SOCKET_ERROR;
538 }
539 }
540 ret = accept(s, addr, addrlen);
541
542 if(ret != SOCKET_ERROR) {
543 //Enable FD_ACCEPT event flag if WSAAsyncSelect was called for this socket
544 EnableAsyncEvent(s, FD_ACCEPT);
545
546 //if this socket has an active async. select pending, then call WSAAsyncSelect
547 //with the same parameters for the new socket (see docs)
548 if(QueryAsyncEvent(s, &hwnd, &msg, &lEvent) == TRUE) {
549 if(WSAAsyncSelect(ret, hwnd, msg, lEvent) == SOCKET_ERROR) {
550 ret = SOCKET_ERROR;
551 }
552 }
553 }
554 if(ret == SOCKET_ERROR) {
555 WSASetLastError(wsaErrno());
556 }
557 else WSASetLastError(NO_ERROR);
558 return ret;
559}
560//******************************************************************************
561//******************************************************************************
562ODINFUNCTION3(int,OS2bind,
563 SOCKET ,s,
564 const struct sockaddr *,addr,
565 int, namelen)
566{
567 int ret;
568
569 if(!fWSAInitialized) {
570 WSASetLastError(WSANOTINITIALISED);
571 return SOCKET_ERROR;
572 }
573 else
574 if(WSAIsBlocking()) {
575 WSASetLastError(WSAEINPROGRESS);
576 return SOCKET_ERROR;
577 }
578 else
579 if(namelen < (int)sizeof(struct sockaddr_in)) {
580 WSASetLastError(WSAEFAULT);
581 return SOCKET_ERROR;
582 }
583 ret = bind(s, (struct sockaddr *)addr, namelen);
584
585 if(ret == SOCKET_ERROR) {
586 WSASetLastError(wsaErrno());
587 }
588 else WSASetLastError(NO_ERROR);
589 return ret;
590}
591//******************************************************************************
592//******************************************************************************
593ODINFUNCTION2(int,OS2listen,
594 SOCKET, s,
595 int, backlog)
596{
597 int ret, tmp, namelen;
598 struct sockaddr_in name;
599
600 if(!fWSAInitialized) {
601 WSASetLastError(WSANOTINITIALISED);
602 return SOCKET_ERROR;
603 }
604 else
605 if(WSAIsBlocking()) {
606 WSASetLastError(WSAEINPROGRESS);
607 return SOCKET_ERROR;
608 }
609 namelen = sizeof(name);
610 ret = getsockname(s, (struct sockaddr *)&name, &namelen);
611 if (ret == 0) {
612 if (name.sin_port == 0 && name.sin_addr.s_addr == 0) {
613 // Socket is not bound
614 WSASetLastError(WSAEINVAL);
615 return SOCKET_ERROR;
616 }
617 ret = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp)) &
618 (SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
619 if(ret) {
620 // Socket is already connected
621 WSASetLastError(WSAEISCONN);
622 return SOCKET_ERROR;
623 }
624 ret = listen(s, backlog);
625 //todo: reset FD_ACCEPT bit? (wine seems to do this, but it's not documented)
626 }
627 if(ret == SOCKET_ERROR) {
628 WSASetLastError(wsaErrno());
629 }
630 else WSASetLastError(NO_ERROR);
631 return ret;
632}
633//******************************************************************************
634//******************************************************************************
635ODINFUNCTION4(int,OS2recv,
636 SOCKET,s,
637 char *,buf,
638 int,len,
639 int,flags)
640{
641 int ret;
642
643 if(!fWSAInitialized) {
644 WSASetLastError(WSANOTINITIALISED);
645 return SOCKET_ERROR;
646 }
647 else
648 if(WSAIsBlocking()) {
649 WSASetLastError(WSAEINPROGRESS);
650 return SOCKET_ERROR;
651 }
652 ret = recv(s, buf, len, flags);
653
654 if(ret == SOCKET_ERROR) {
655 WSASetLastError(wsaErrno());
656 }
657 else
658 if(ret == 0) {
659 int tmp, state;
660
661 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
662 if(state & SS_ISCONNECTED && flags != MSG_PEEK) {
663 dprintf(("recv returned 0, but socket is still connected -> return WSAWOULDBLOCK"));
664 WSASetLastError(WSAEWOULDBLOCK);
665 ret = 0; //graceful close
666 }
667 }
668 else WSASetLastError(NO_ERROR);
669
670 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
671 EnableAsyncEvent(s, FD_READ);
672 return ret;
673}
674//******************************************************************************
675//******************************************************************************
676ODINFUNCTION6(int,OS2recvfrom,
677 SOCKET,s,
678 char *,buf,
679 int,len,
680 int,flags,
681 struct sockaddr *,from,
682 int *,fromlen)
683{
684 int ret;
685
686 if(!fWSAInitialized) {
687 WSASetLastError(WSANOTINITIALISED);
688 return SOCKET_ERROR;
689 }
690 else
691 if(WSAIsBlocking()) {
692 WSASetLastError(WSAEINPROGRESS);
693 return SOCKET_ERROR;
694 }
695 else
696 if(fromlen == NULL || *fromlen < (int)sizeof(struct sockaddr_in)) {
697 WSASetLastError(WSAEFAULT);
698 return SOCKET_ERROR;
699 }
700 ret = recvfrom(s, buf, len, flags, from, fromlen);
701
702 if(ret == SOCKET_ERROR) {
703 WSASetLastError(wsaErrno());
704 }
705 else WSASetLastError(NO_ERROR);
706
707 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
708 EnableAsyncEvent(s, FD_READ);
709 return ret;
710}
711//******************************************************************************
712//******************************************************************************
713ODINFUNCTION4(int,OS2send,
714 SOCKET,s,
715 const char *,buf,
716 int,len,
717 int,flags)
718{
719 int ret;
720
721 if(!fWSAInitialized) {
722 WSASetLastError(WSANOTINITIALISED);
723 return SOCKET_ERROR;
724 }
725 else
726 if(WSAIsBlocking()) {
727 WSASetLastError(WSAEINPROGRESS);
728 return SOCKET_ERROR;
729 }
730 ret = send(s, (char *)buf, len, flags);
731
732 if(ret == SOCKET_ERROR) {
733 WSASetLastError(wsaErrno());
734 }
735 else WSASetLastError(NO_ERROR);
736
737 //Reset FD_WRITE event flagfor WSAAsyncSelect thread if one was created for this socket
738 EnableAsyncEvent(s, FD_WRITE);
739 return ret;
740}
741//******************************************************************************
742//******************************************************************************
743ODINFUNCTION6(int,OS2sendto,
744 SOCKET,s,
745 const char *,buf,
746 int,len,
747 int,flags,
748 const struct sockaddr *,to,
749 int,tolen)
750{
751 int ret;
752 int optlen;
753 int option;
754
755 if(!fWSAInitialized) {
756 WSASetLastError(WSANOTINITIALISED);
757 return SOCKET_ERROR;
758 }
759 else
760 if(WSAIsBlocking()) {
761 WSASetLastError(WSAEINPROGRESS);
762 return SOCKET_ERROR;
763 }
764 else
765 if(tolen < (int)sizeof(struct sockaddr_in)) {
766 WSASetLastError(WSAEFAULT);
767 return SOCKET_ERROR;
768 }
769 // check if the socket is a raw socket and has the IP_HDRINCL switch
770 // if this is the case, we overwrite the IP header length field with
771 // the actual length because some apps tend to put in garbage in there
772 // and rely on Windows correcting this
773 optlen = sizeof(option);
774 option = 0;
775 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&option, &optlen);
776 if(ret == 0 && option != FALSE) {
777 *(u_short *)&buf[2] = len;
778 }
779 dprintf(("sending to %s", inet_ntoa(((sockaddr_in*)to)->sin_addr)));
780 ret = sendto(s, (char *)buf, len, flags, (struct sockaddr *)to, tolen);
781
782 if(ret == SOCKET_ERROR) {
783 WSASetLastError(wsaErrno());
784 }
785 else WSASetLastError(NO_ERROR);
786
787 //Reset FD_WRITE event flag for WSAAsyncSelect thread if one was created for this socket
788 EnableAsyncEvent(s, FD_WRITE);
789 return ret;
790}
791//******************************************************************************
792//******************************************************************************
793ODINFUNCTION5(int,OS2select,
794 int,nfds,
795 ws_fd_set *,readfds,
796 ws_fd_set *,writefds,
797 ws_fd_set *,exceptfds,
798 const struct timeval *,timeout)
799{
800 int ret, i, j;
801 int *sockets, *socktmp;
802 int nrread, nrwrite, nrexcept;
803 ULONG ttimeout;
804
805 WSASetLastError(NO_ERROR);
806
807 if(!fWSAInitialized) {
808 WSASetLastError(WSANOTINITIALISED);
809 return SOCKET_ERROR;
810 }
811 else
812 if(WSAIsBlocking()) {
813 WSASetLastError(WSAEINPROGRESS);
814 return SOCKET_ERROR;
815 }
816 else {
817 nrread = nrwrite = nrexcept = 0;
818 if(readfds) {
819 nrread += readfds->fd_count;
820 }
821 if(writefds) {
822 nrwrite += writefds->fd_count;
823 }
824 if(exceptfds) {
825 nrexcept += exceptfds->fd_count;
826 }
827#if 0
828 if(nrread + nrwrite + nrexcept == 0) {
829 dprintf(("ERROR: nrread + nrwrite + nrexcept == 0"));
830 WSASetLastError(WSAEINVAL);
831 return SOCKET_ERROR;
832 }
833#endif
834 if(timeout != NULL && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) {
835 dprintf(("ERROR: timeout->tv_sec < 0 || timeout->tv_usec < 0"));
836 WSASetLastError(WSAEINVAL);
837 return SOCKET_ERROR;
838 }
839 if(timeout == NULL) {
840 ttimeout = -1L; // no timeout
841 }
842 else ttimeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
843
844 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
845 if(readfds) {
846 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
847 }
848 if(writefds) {
849 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
850 }
851 if(exceptfds) {
852 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
853 }
854
855 ret = select(sockets, nrread, nrwrite, nrexcept, ttimeout);
856
857 if(ret == SOCKET_ERROR)
858 {
859 if(readfds != NULL)
860 readfds->fd_count = 0;
861
862 if(writefds != NULL)
863 writefds->fd_count = 0;
864
865 if(exceptfds != NULL)
866 exceptfds->fd_count = 0;
867
868 WSASetLastError(wsaErrno());
869 free(sockets);
870 return SOCKET_ERROR;
871 }
872
873 if(ret != 0) {
874 socktmp = sockets;
875 if(readfds != NULL) {
876 j = 0;
877 for(i=0;i<nrread;i++) {
878 if(socktmp[i] != -1) {
879 readfds->fd_array[i] = socktmp[i];
880 j++;
881 }
882 }
883 readfds->fd_count = j;
884 socktmp += nrread;
885 }
886
887 if(writefds != NULL) {
888 j = 0;
889 for(i=0;i<nrwrite;i++) {
890 if(socktmp[i] != -1) {
891 writefds->fd_array[i] = socktmp[i];
892 j++;
893 }
894 }
895 writefds->fd_count = j;
896 socktmp += nrwrite;
897 }
898 if(exceptfds != NULL) {
899 j = 0;
900 for(i=0;i<nrexcept;i++) {
901 if(socktmp[i] != -1) {
902 exceptfds->fd_array[i] = socktmp[i];
903 j++;
904 }
905 }
906 exceptfds->fd_count = j;
907 }
908 }
909 else {
910 if(readfds != NULL)
911 readfds->fd_count = 0;
912
913 if(writefds != NULL)
914 writefds->fd_count = 0;
915
916 if(exceptfds != NULL)
917 exceptfds->fd_count = 0;
918 }
919 free(sockets);
920 }
921 return ret;
922}
923//******************************************************************************
924//******************************************************************************
925ODINFUNCTION5(int,OS2setsockopt,
926 SOCKET,s,
927 int,level,
928 int,optname,
929 const char *,optval,
930 int,optlen)
931{
932 struct ws_linger *yy;
933 struct linger xx;
934 int ret;
935 ULONG size;
936 char *safeoptval;
937
938 if(!fWSAInitialized) {
939 dprintf(("WSA not initialized"));
940 WSASetLastError(WSANOTINITIALISED);
941 return SOCKET_ERROR;
942 }
943 else
944 if(WSAIsBlocking()) {
945 dprintf(("WSA is blocking"));
946 WSASetLastError(WSAEINPROGRESS);
947 return SOCKET_ERROR;
948 }
949 //SvL: The 16 bits TCP/IP stack doesn't like high addresses, so copy
950 // the option value(s) on the stack.
951 safeoptval = (char *)alloca(optlen);
952 if(safeoptval == NULL) {
953 DebugInt3();
954 WSASetLastError(WSAEFAULT);
955 return SOCKET_ERROR;
956 }
957 memcpy(safeoptval, optval, optlen);
958 optval = safeoptval;
959
960 if (level == SOL_SOCKET)
961 {
962 switch(optname)
963 {
964 case SO_DONTLINGER:
965 case SO_LINGER:
966 if(optlen < (int)sizeof(ws_linger))
967 {
968 dprintf(("SOL_SOCKET, SO_LINGER, optlen too small"));
969 WSASetLastError(WSAEFAULT);
970 return SOCKET_ERROR;
971 }
972 yy = (struct ws_linger *)optval;
973 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
974 xx.l_linger = yy->l_linger;
975
976 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
977 break;
978 case SO_SNDBUF:
979 case SO_RCVBUF:
980 if(optlen < (int)sizeof(int))
981 {
982 dprintf(("SOL_SOCKET, SO_RCVBUF, optlen too small"));
983 WSASetLastError(WSAEFAULT);
984 return SOCKET_ERROR;
985 }
986
987 size = *(ULONG *)optval;
988tryagain:
989 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
990 if(ret == SOCKET_ERROR && wsaErrno() == WSAENOBUFS && size > 4096) {
991 int newsize = (size > 65535) ? 63*1024 : (size-1024);
992 dprintf(("setsockopt: change size from %d to %d", size, newsize));
993 //SvL: Limit send & receive buffer length to 64k
994 // (only happens with 16 bits tcpip stack?)
995 size = newsize;
996 goto tryagain;
997 }
998 break;
999
1000 case SO_SNDTIMEO:
1001 case SO_RCVTIMEO:
1002 // convert "int" to "struct timeval"
1003 struct timeval tv;
1004 tv.tv_sec = *optval / 1000;
1005 tv.tv_usec = (*optval % 1000) * 1000;
1006 ret = setsockopt(s, level, optname, (char *)&tv, sizeof(tv) );
1007 break;
1008
1009 case SO_BROADCAST:
1010 case SO_DEBUG:
1011 case SO_KEEPALIVE:
1012 case SO_DONTROUTE:
1013 case SO_OOBINLINE:
1014 case SO_REUSEADDR:
1015 if(optlen < (int)sizeof(int)) {
1016 dprintf(("SOL_SOCKET, SO_REUSEADDR, optlen too small"));
1017 WSASetLastError(WSAEFAULT);
1018 return SOCKET_ERROR;
1019 }
1020 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1021 break;
1022 default:
1023 dprintf(("setsockopt: SOL_SOCKET, unknown option %x", optname));
1024 WSASetLastError(WSAENOPROTOOPT);
1025 return SOCKET_ERROR;
1026 }
1027 }
1028 else
1029 if(level == IPPROTO_TCP)
1030 {
1031 if(optname == TCP_NODELAY) {
1032 if(optlen < (int)sizeof(int)) {
1033 dprintf(("IPPROTO_TCP, TCP_NODELAY, optlen too small"));
1034 WSASetLastError(WSAEFAULT);
1035 return SOCKET_ERROR;
1036 }
1037 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1038 }
1039 else {
1040 dprintf(("setsockopt: IPPROTO_TCP, unknown option %x", optname));
1041 WSASetLastError(WSAENOPROTOOPT);
1042 return SOCKET_ERROR;
1043 }
1044 }
1045 else
1046 if (level == IPPROTO_IP)
1047 {
1048 switch (optname)
1049 {
1050 case IP_MULTICAST_IF:
1051 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1052 {
1053 if (optlen < sizeof(in_addr))
1054 {
1055 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1056 WSASetLastError(WSAEFAULT);
1057 return SOCKET_ERROR;
1058 }
1059 //TODO convert common interface names!
1060 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1061 break;
1062 }
1063
1064 case IP_ADD_MEMBERSHIP:
1065 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1066 if (optlen < sizeof(struct ip_mreq))
1067 {
1068 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1069 WSASetLastError(WSAEFAULT);
1070 return SOCKET_ERROR;
1071 }
1072 ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1073 break;
1074
1075 case IP_DROP_MEMBERSHIP:
1076 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1077 if (optlen < sizeof(struct ip_mreq))
1078 {
1079 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1080 WSASetLastError(WSAEFAULT);
1081 return SOCKET_ERROR;
1082 }
1083 ret = setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1084 break;
1085
1086 case IP_MULTICAST_LOOP:
1087 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1088 {
1089 u_int flLoop;
1090 if (optlen < sizeof(u_char))
1091 {
1092 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1093 WSASetLastError(WSAEFAULT);
1094 return SOCKET_ERROR;
1095 }
1096 flLoop = (*optval == 0) ? 0 : 1;
1097 dprintf(("IP_MULTICAST_LOOP %d", *optval));
1098 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, optlen);
1099 break;
1100 }
1101
1102 case IP_MULTICAST_TTL:
1103 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1104 if (optlen < sizeof(u_char))
1105 {
1106 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1107 WSASetLastError(WSAEFAULT);
1108 return SOCKET_ERROR;
1109 }
1110 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1111 break;
1112
1113 case IP_TTL:
1114 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1115 if (optlen < sizeof(u_int))
1116 {
1117 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1118 WSASetLastError(WSAEFAULT);
1119 return SOCKET_ERROR;
1120 }
1121 dprintf(("IPPROTO_IP, IP_TTL 0x%x", *optval));
1122 ret = setsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1123 break;
1124
1125 case IP_TOS:
1126 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1127 if (optlen < sizeof(u_int))
1128 {
1129 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1130 WSASetLastError(WSAEFAULT);
1131 return SOCKET_ERROR;
1132 }
1133 dprintf(("IPPROTO_IP, IP_TOS 0x%x", *optval));
1134 ret = setsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1135 break;
1136
1137 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1138 if (optlen < sizeof(u_int))
1139 {
1140 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1141 WSASetLastError(WSAEFAULT);
1142 return SOCKET_ERROR;
1143 }
1144 dprintf(("IPPROTO_IP, IP_HDRINCL 0x%x", *optval));
1145 ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1146 break;
1147
1148 default:
1149 dprintf(("setsockopt: IPPROTO_IP, unknown option %x", optname));
1150 WSASetLastError(WSAENOPROTOOPT);
1151 return SOCKET_ERROR;
1152 }
1153 }
1154 else {
1155 dprintf(("unknown level code!"));
1156 WSASetLastError(WSAEINVAL);
1157 return SOCKET_ERROR;
1158 }
1159
1160 if(ret == SOCKET_ERROR) {
1161 WSASetLastError(wsaErrno());
1162 }
1163 else WSASetLastError(NO_ERROR);
1164 return ret;
1165}
1166//******************************************************************************
1167//******************************************************************************
1168ODINFUNCTION5(int,OS2getsockopt,
1169 SOCKET, s,
1170 int, level,
1171 int, optname,
1172 char *, optval,
1173 int *,optlen)
1174{
1175 struct ws_linger *yy;
1176 struct linger xx;
1177 int ret;
1178 int size, options;
1179
1180 if(!fWSAInitialized) {
1181 WSASetLastError(WSANOTINITIALISED);
1182 return SOCKET_ERROR;
1183 }
1184 else
1185 if(WSAIsBlocking()) {
1186 WSASetLastError(WSAEINPROGRESS);
1187 return SOCKET_ERROR;
1188 }
1189 if (level == SOL_SOCKET) {
1190 switch(optname) {
1191 case SO_DONTLINGER:
1192 case SO_LINGER:
1193 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
1194 WSASetLastError(WSAEFAULT);
1195 return SOCKET_ERROR;
1196 }
1197 size = sizeof(xx);
1198 ret = getsockopt(s,level,optname,(char *)&xx, &size);
1199 yy = (struct ws_linger *)optval;
1200 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
1201 yy->l_linger = xx.l_linger;
1202 *optlen = size;
1203 break;
1204
1205 case SO_SNDBUF:
1206 case SO_RCVBUF:
1207 case SO_BROADCAST:
1208 case SO_DEBUG:
1209 case SO_KEEPALIVE:
1210 case SO_DONTROUTE:
1211 case SO_OOBINLINE:
1212 case SO_REUSEADDR:
1213 case SO_TYPE:
1214 if(optlen == NULL || *optlen < sizeof(int)) {
1215 WSASetLastError(WSAEFAULT);
1216 return SOCKET_ERROR;
1217 }
1218 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1219 break;
1220 case SO_ACCEPTCONN:
1221 if(optlen == NULL || *optlen < sizeof(int)) {
1222 WSASetLastError(WSAEFAULT);
1223 return SOCKET_ERROR;
1224 }
1225 size = sizeof(options);
1226 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
1227 if(ret != SOCKET_ERROR) {
1228 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
1229 *optlen = sizeof(BOOL);
1230 }
1231 break;
1232 default:
1233 dprintf(("getsockopt: unknown option %x", optname));
1234 WSASetLastError(WSAENOPROTOOPT);
1235 return SOCKET_ERROR;
1236 }
1237 }
1238 else
1239 if(level == IPPROTO_TCP) {
1240 if(optname == TCP_NODELAY) {
1241 if(optlen == NULL || *optlen < sizeof(int)) {
1242 WSASetLastError(WSAEFAULT);
1243 return SOCKET_ERROR;
1244 }
1245 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1246 }
1247 else {
1248 dprintf(("getsockopt: unknown option %x", optname));
1249 WSASetLastError(WSAENOPROTOOPT);
1250 return SOCKET_ERROR;
1251 }
1252 }
1253 else
1254 if(level == IPPROTO_IP) {
1255 switch (optname)
1256 {
1257 case IP_MULTICAST_IF:
1258 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1259 {
1260 if (*optlen < sizeof(in_addr))
1261 {
1262 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1263 WSASetLastError(WSAEFAULT);
1264 return SOCKET_ERROR;
1265 }
1266 //TODO convert common interface names!
1267 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1268 break;
1269 }
1270
1271 case IP_ADD_MEMBERSHIP:
1272 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1273 if (*optlen < sizeof(struct ip_mreq))
1274 {
1275 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1276 WSASetLastError(WSAEFAULT);
1277 return SOCKET_ERROR;
1278 }
1279 ret = getsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1280 break;
1281
1282 case IP_DROP_MEMBERSHIP:
1283 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1284 if (*optlen < sizeof(struct ip_mreq))
1285 {
1286 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1287 WSASetLastError(WSAEFAULT);
1288 return SOCKET_ERROR;
1289 }
1290 ret = getsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1291 break;
1292
1293 case IP_MULTICAST_LOOP:
1294 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1295 {
1296 if (*optlen < sizeof(u_char))
1297 {
1298 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1299 WSASetLastError(WSAEFAULT);
1300 return SOCKET_ERROR;
1301 }
1302 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)optval, optlen);
1303 break;
1304 }
1305
1306 case IP_MULTICAST_TTL:
1307 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1308 if (*optlen < sizeof(u_char))
1309 {
1310 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1311 WSASetLastError(WSAEFAULT);
1312 return SOCKET_ERROR;
1313 }
1314 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1315 break;
1316
1317 case IP_TTL:
1318 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1319 if (*optlen < sizeof(u_int))
1320 {
1321 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1322 WSASetLastError(WSAEFAULT);
1323 return SOCKET_ERROR;
1324 }
1325 ret = getsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1326 break;
1327
1328 case IP_TOS:
1329 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1330 if (*optlen < sizeof(u_int))
1331 {
1332 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1333 WSASetLastError(WSAEFAULT);
1334 return SOCKET_ERROR;
1335 }
1336 ret = getsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1337 break;
1338
1339 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1340 if (*optlen < sizeof(u_int))
1341 {
1342 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1343 WSASetLastError(WSAEFAULT);
1344 return SOCKET_ERROR;
1345 }
1346 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1347 if(ret == 0) {
1348 ret = (ret != FALSE) ? TRUE : FALSE;
1349 }
1350 break;
1351
1352 default:
1353 dprintf(("getsockopt: IPPROTO_IP, unknown option %x", optname));
1354 WSASetLastError(WSAENOPROTOOPT);
1355 return SOCKET_ERROR;
1356 }
1357 }
1358 else {
1359 WSASetLastError(WSAEINVAL);
1360 return SOCKET_ERROR;
1361 }
1362
1363 if(ret == SOCKET_ERROR) {
1364 WSASetLastError(wsaErrno());
1365 }
1366 else WSASetLastError(NO_ERROR);
1367 return ret;
1368}
1369//******************************************************************************
1370//******************************************************************************
1371/* Database function prototypes */
1372//******************************************************************************
1373//******************************************************************************
1374ODINFUNCTION2(int,OS2gethostname,
1375 char *,name,
1376 int,namelen)
1377{
1378 int ret;
1379
1380 ret = gethostname(name, namelen);
1381 if(ret == NULL) {
1382 WSASetLastError(NO_ERROR);
1383 return 0;
1384 }
1385 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1386 return SOCKET_ERROR;
1387}
1388//******************************************************************************
1389//******************************************************************************
1390ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1391 const char *,addr,
1392 int,len,
1393 int,type)
1394{
1395 LPWSINFO pwsi = WINSOCK_GetIData();
1396
1397 if( pwsi )
1398 {
1399 struct hostent* host;
1400 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1401 if( WS_dup_he(pwsi, host) ) {
1402 WSASetLastError(NO_ERROR);
1403 return pwsi->he;
1404 }
1405 else WSASetLastError(WSAENOBUFS);
1406 }
1407 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1408 }
1409 else WSASetLastError(WSANOTINITIALISED);
1410 return NULL;
1411}
1412//******************************************************************************
1413//******************************************************************************
1414ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1415 const char *,name)
1416{
1417 LPWSINFO pwsi = WINSOCK_GetIData();
1418
1419 if( pwsi )
1420 {
1421 struct hostent* host;
1422
1423 USHORT sel = RestoreOS2FS();
1424 host = gethostbyname( (char*) name);
1425 SetFS(sel);
1426
1427 if( host != NULL )
1428 {
1429 if( WS_dup_he(pwsi, host) )
1430 {
1431 WSASetLastError(NO_ERROR);
1432 return pwsi->he;
1433 }
1434 else
1435 WSASetLastError(WSAENOBUFS);
1436 }
1437 else
1438 WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1439 }
1440 else
1441 WSASetLastError(WSANOTINITIALISED);
1442
1443 return NULL;
1444}
1445//******************************************************************************
1446//******************************************************************************
1447ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1448 int, port,
1449 const char *, proto)
1450{
1451 LPWSINFO pwsi = WINSOCK_GetIData();
1452
1453 if( pwsi )
1454 {
1455 struct servent* serv;
1456 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1457 if( WS_dup_se(pwsi, serv) ) {
1458 WSASetLastError(NO_ERROR);
1459 return pwsi->se;
1460 }
1461 else WSASetLastError(WSAENOBUFS);
1462 }
1463 else WSASetLastError(WSANO_DATA);
1464 }
1465 else WSASetLastError(WSANOTINITIALISED);
1466 return NULL;
1467}
1468//******************************************************************************
1469//******************************************************************************
1470ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1471 const char *, name,
1472 const char *, proto)
1473{
1474 LPWSINFO pwsi = WINSOCK_GetIData();
1475
1476 if( pwsi )
1477 {
1478 struct servent *serv;
1479 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1480 if( WS_dup_se(pwsi, serv) ) {
1481 WSASetLastError(NO_ERROR);
1482 return pwsi->se;
1483 }
1484 else WSASetLastError(WSAENOBUFS);
1485 }
1486 else WSASetLastError(WSANO_DATA);
1487 }
1488 else WSASetLastError(WSANOTINITIALISED);
1489 return NULL;
1490}
1491//******************************************************************************
1492//******************************************************************************
1493ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1494 int,number)
1495{
1496 LPWSINFO pwsi = WINSOCK_GetIData();
1497
1498 if( pwsi )
1499 {
1500 struct protoent* proto;
1501 if( (proto = getprotobynumber(number)) != NULL ) {
1502 if( WS_dup_pe(pwsi, proto) ) {
1503 WSASetLastError(NO_ERROR);
1504 return pwsi->pe;
1505 }
1506 else WSASetLastError(WSAENOBUFS);
1507 }
1508 else WSASetLastError(WSANO_DATA);
1509 }
1510 else WSASetLastError(WSANOTINITIALISED);
1511 return NULL;
1512}
1513//******************************************************************************
1514//******************************************************************************
1515ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1516 const char *,name)
1517{
1518 LPWSINFO pwsi = WINSOCK_GetIData();
1519
1520 if( pwsi )
1521 {
1522 struct protoent * proto;
1523 if( (proto = getprotobyname((char *)name)) != NULL ) {
1524 if(WS_dup_pe(pwsi, proto)) {
1525 WSASetLastError(NO_ERROR);
1526 return pwsi->pe;
1527 }
1528 else WSASetLastError(WSAENOBUFS);
1529 }
1530 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1531 }
1532 else WSASetLastError(WSANOTINITIALISED);
1533 return NULL;
1534}
1535//******************************************************************************
1536//******************************************************************************
Note: See TracBrowser for help on using the repository browser.