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

Last change on this file since 3282 was 3282, checked in by sandervl, 25 years ago

wsastartup/cleanup + select fixes

File size: 32.7 KB
Line 
1/* $Id: wsock32.cpp,v 1.27 2000-03-30 20:52:56 sandervl 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#include <win32wnd.h>
55#include <wprocess.h>
56#include <misc.h>
57
58#include "wsock32.h"
59#include "wsastruct.h"
60#include "asyncthread.h"
61
62#define DBG_LOCALLOG DBG_wsock32
63#include "dbglocal.h"
64
65
66ODINDEBUGCHANNEL(WSOCK32-WSOCK32)
67
68
69/*****************************************************************************
70 * Local variables *
71 *****************************************************************************/
72
73static LPWSINFO lpFirstIData = NULL;
74
75//******************************************************************************
76//******************************************************************************
77LPWSINFO WINSOCK_GetIData(HANDLE tid)
78{
79 LPWSINFO iData;
80 BOOL fCurrentThread = FALSE;
81
82 if(tid == CURRENT_THREAD) {
83 tid = GetCurrentThread();
84 fCurrentThread = TRUE;
85 }
86tryagain:
87 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
88 if (iData->dwThisThread == tid)
89 break;
90 }
91 if(iData == NULL && fCurrentThread) {
92 WINSOCK_CreateIData();
93 fCurrentThread = FALSE; //just to prevent infinite loops
94 goto tryagain;
95 }
96 if(iData == NULL) {
97 dprintf(("WINSOCK_GetIData: couldn't find struct for thread %x", tid));
98 DebugInt3();// should never happen!!!!!!!
99 }
100 return iData;
101}
102//******************************************************************************
103//******************************************************************************
104BOOL WINSOCK_CreateIData(void)
105{
106 LPWSINFO iData;
107
108 iData = (LPWSINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
109 if (!iData)
110 return FALSE;
111 iData->dwThisThread = GetCurrentThread();
112 iData->lpNextIData = lpFirstIData;
113 lpFirstIData = iData;
114 return TRUE;
115}
116//******************************************************************************
117//******************************************************************************
118void WINSOCK_DeleteIData(void)
119{
120 LPWSINFO ppid, iData;
121
122 if (iData) {
123 ppid = lpFirstIData;
124 while(ppid)
125 {
126 iData = ppid;
127 ppid = ppid->lpNextIData;
128
129 if( iData->flags & WSI_BLOCKINGCALL )
130 dprintf(("\tinside blocking call!\n"));
131
132 /* delete scratch buffers */
133
134 if(iData->he) free(iData->he);
135 if(iData->se) free(iData->se);
136 if(iData->pe) free(iData->pe);
137
138 //// if( iData->buffer ) SEGPTR_FREE(iData->buffer);
139 //// if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
140
141 HeapFree(GetProcessHeap(), 0, iData);
142 }
143 }
144}
145//******************************************************************************
146//******************************************************************************
147void WIN32API WSASetLastError(int iError)
148{
149 // according to the docs, WSASetLastError() is just a call-through
150 // to SetLastError()
151 if(iError) {
152 dprintf(("WSASetLastError %x", iError));
153 }
154 SetLastError(iError);
155}
156//******************************************************************************
157//******************************************************************************
158int WIN32API WSAGetLastError()
159{
160 return GetLastError();
161}
162//******************************************************************************
163//******************************************************************************
164ODINFUNCTION2(int,OS2shutdown,
165 SOCKET,s,
166 int,how)
167{
168 int ret;
169
170 if(!fWSAInitialized) {
171 WSASetLastError(WSANOTINITIALISED);
172 return SOCKET_ERROR;
173 }
174 else
175 if(WSAIsBlocking()) {
176 WSASetLastError(WSAEINPROGRESS);
177 return SOCKET_ERROR;
178 }
179 ret = shutdown(s, how);
180
181 if(ret == SOCKET_ERROR) {
182 WSASetLastError(wsaErrno());
183 }
184 else WSASetLastError(NO_ERROR);
185 return ret;
186}
187//******************************************************************************
188//******************************************************************************
189ODINFUNCTION3(SOCKET,OS2socket,
190 int,af,
191 int,type,
192 int,protocol)
193{
194 SOCKET s;
195
196 if(!fWSAInitialized) {
197 WSASetLastError(WSANOTINITIALISED);
198 return SOCKET_ERROR;
199 }
200 else
201 if(WSAIsBlocking()) {
202 WSASetLastError(WSAEINPROGRESS);
203 return SOCKET_ERROR;
204 }
205 s = socket(af, type, protocol);
206
207 if(s == SOCKET_ERROR && sock_errno() == SOCEPFNOSUPPORT) {
208 //map SOCEPFNOSUPPORT to SOCEPFNOSUPPORT
209 WSASetLastError(SOCEPFNOSUPPORT);
210 }
211 else
212 if(s == SOCKET_ERROR) {
213 WSASetLastError(wsaErrno());
214 }
215 else WSASetLastError(NO_ERROR);
216 return s;
217}
218//******************************************************************************
219//******************************************************************************
220ODINFUNCTION1(int,OS2closesocket,SOCKET, s)
221{
222 int ret;
223
224 if(!fWSAInitialized) {
225 WSASetLastError(WSANOTINITIALISED);
226 return SOCKET_ERROR;
227 }
228 else
229 if(WSAIsBlocking()) {
230 WSASetLastError(WSAEINPROGRESS);
231 return SOCKET_ERROR;
232 }
233 ret = soclose(s);
234 //Close WSAAsyncSelect thread if one was created for this socket
235 FindAndSetAsyncEvent(s, 0, 0, 0);
236
237 if(ret == SOCKET_ERROR) {
238 WSASetLastError(wsaErrno());
239 }
240 else WSASetLastError(NO_ERROR);
241 return ret;
242}
243//******************************************************************************
244//******************************************************************************
245ODINFUNCTION3(int,OS2connect,
246 SOCKET, s,
247 const struct sockaddr *,name,
248 int, namelen)
249{
250 int ret;
251
252 if(!fWSAInitialized) {
253 WSASetLastError(WSANOTINITIALISED);
254 return SOCKET_ERROR;
255 }
256 else
257 if(WSAIsBlocking()) {
258 WSASetLastError(WSAEINPROGRESS);
259 return SOCKET_ERROR;
260 }
261 ret = connect(s, (sockaddr *)name, namelen);
262 // map BSD error codes
263 if(ret == SOCKET_ERROR) {
264 int sockerror = sock_errno();
265 if(sockerror && sockerror < SOCBASEERR) {
266 sockerror += SOCBASEERR;
267 }
268 if(sockerror == SOCEINPROGRESS) {
269 WSASetLastError(WSAEWOULDBLOCK);
270 }
271 else
272 if(sockerror == SOCEOPNOTSUPP) {
273 WSASetLastError(WSAEINVAL);
274 }
275 else WSASetLastError(wsaErrno());
276 }
277 else WSASetLastError(NO_ERROR);
278 return ret;
279}
280//******************************************************************************
281//******************************************************************************
282ODINFUNCTION3(int,OS2ioctlsocket,
283 SOCKET,s,
284 long, cmd,
285 u_long *,argp)
286{
287 int ret;
288
289 if(!fWSAInitialized) {
290 WSASetLastError(WSANOTINITIALISED);
291 return SOCKET_ERROR;
292 }
293 else
294 if(WSAIsBlocking()) {
295 WSASetLastError(WSAEINPROGRESS);
296 return SOCKET_ERROR;
297 }
298 // clear high word (not used in OS/2's tcpip stack)
299 cmd = LOUSHORT(cmd);
300
301 if(cmd != FIONBIO && cmd != FIONREAD && cmd != SIOCATMARK) {
302 WSASetLastError(WSAEINVAL);
303 return SOCKET_ERROR;
304 }
305
306 WSASetLastError(NO_ERROR);
307
308 //check if app want to set a socket, which has an outstanding async select,
309 //to blocking mode
310 if (cmd == FIONBIO) {
311 HWND hwnd;
312 int msg;
313 ULONG lEvent;
314
315 if(QueryAsyncEvent(s, &hwnd, &msg, &lEvent) == TRUE) {
316 if(*argp != 0) {
317 //nothing to do; already non-blocking
318 return NO_ERROR;
319 }
320 else {
321 dprintf(("Trying to set socket to blocking mode while async select active -> return error!"));
322 WSASetLastError(WSAEINVAL);
323 return SOCKET_ERROR;
324 }
325 }
326 }
327 ret = ioctl(s, cmd, (char *)argp, sizeof(int));
328
329 // Map EOPNOTSUPP to EINVAL
330 int sockerror = sock_errno();
331 if(sockerror && sockerror < SOCBASEERR) {
332 sockerror += SOCBASEERR;
333 }
334
335 if(ret == SOCKET_ERROR && sockerror == SOCEOPNOTSUPP)
336 WSASetLastError(WSAEINVAL);
337 else
338 if(ret == SOCKET_ERROR) {
339 WSASetLastError(wsaErrno());
340 }
341 else WSASetLastError(NO_ERROR);
342 return ret;
343}
344//******************************************************************************
345//******************************************************************************
346ODINFUNCTION3(int,OS2getpeername,
347 SOCKET, s,
348 struct sockaddr *,name,
349 int *, namelen)
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 else
363 if (namelen == NULL || *namelen < (int)sizeof(struct sockaddr_in)) {
364 WSASetLastError(WSAEFAULT);
365 return SOCKET_ERROR;
366 }
367 ret = getsockname(s, name, namelen);
368 if(ret == SOCKET_ERROR) {
369 WSASetLastError(wsaErrno());
370 }
371 else WSASetLastError(NO_ERROR);
372 return ret;
373}
374//******************************************************************************
375//******************************************************************************
376ODINFUNCTION3(int,OS2getsockname,
377 SOCKET,s,
378 struct sockaddr *,name,
379 int *, namelen)
380{
381 int ret;
382
383 if(!fWSAInitialized) {
384 WSASetLastError(WSANOTINITIALISED);
385 return SOCKET_ERROR;
386 }
387 else
388 if(WSAIsBlocking()) {
389 WSASetLastError(WSAEINPROGRESS);
390 return SOCKET_ERROR;
391 }
392 else
393 if (namelen == NULL || *namelen < (int)sizeof(struct sockaddr_in)) {
394 WSASetLastError(WSAEFAULT);
395 return SOCKET_ERROR;
396 }
397 ret = getsockname(s, name, namelen);
398 if(ret == SOCKET_ERROR) {
399 WSASetLastError(wsaErrno());
400 }
401 else WSASetLastError(NO_ERROR);
402 return ret;
403}
404//******************************************************************************
405//******************************************************************************
406ODINFUNCTION1(u_long,OS2htonl,
407 u_long,hostlong)
408{
409 return(htonl(hostlong));
410}
411//******************************************************************************
412//******************************************************************************
413ODINFUNCTION1(u_short,OS2htons,
414 u_short,hostshort)
415{
416 return(htons(hostshort));
417}
418//******************************************************************************
419//******************************************************************************
420ODINFUNCTION1(u_long,OS2ntohl,
421 u_long,netlong)
422{
423 return(ntohl(netlong));
424}
425//******************************************************************************
426//******************************************************************************
427ODINFUNCTION1(u_short,OS2ntohs,
428 u_short,netshort)
429{
430 return(ntohs(netshort));
431}
432//******************************************************************************
433//******************************************************************************
434ODINFUNCTION1(unsigned long,OS2inet_addr,
435 const char *, cp)
436{
437 dprintf(("WSOCK32: OS2inet_addr(%s)\n",
438 cp));
439
440 return (inet_addr((char *)cp));
441}
442//******************************************************************************
443//******************************************************************************
444ODINFUNCTION1(char *,OS2inet_ntoa,
445 struct in_addr, in)
446{
447 return(inet_ntoa(in));
448}
449//******************************************************************************
450//******************************************************************************
451ODINFUNCTION3(SOCKET,OS2accept, SOCKET, s,
452 struct sockaddr *,addr,
453 int *, addrlen)
454{
455 int ret, msg;
456 HWND hwnd;
457 ULONG lEvent;
458
459 if(!fWSAInitialized) {
460 WSASetLastError(WSANOTINITIALISED);
461 return SOCKET_ERROR;
462 }
463 else
464 if(WSAIsBlocking()) {
465 WSASetLastError(WSAEINPROGRESS);
466 return SOCKET_ERROR;
467 }
468 else
469 if ((addr != NULL) && (addrlen != NULL)) {
470 if (*addrlen < (int)sizeof(struct sockaddr_in)) {
471 WSASetLastError(WSAEFAULT);
472 return SOCKET_ERROR;
473 }
474 }
475 ret = accept(s, addr, addrlen);
476
477 if(ret != SOCKET_ERROR) {
478 //Enable FD_ACCEPT event flag if WSAAsyncSelect was called for this socket
479 EnableAsyncEvent(s, FD_ACCEPT);
480
481 //if this socket has an active async. select pending, then call WSAAsyncSelect
482 //with the same parameters for the new socket (see docs)
483 if(QueryAsyncEvent(s, &hwnd, &msg, &lEvent) == TRUE) {
484 if(WSAAsyncSelect(ret, hwnd, msg, lEvent) == SOCKET_ERROR) {
485 ret = SOCKET_ERROR;
486 }
487 }
488 }
489 if(ret == SOCKET_ERROR) {
490 WSASetLastError(wsaErrno());
491 }
492 else WSASetLastError(NO_ERROR);
493 return ret;
494}
495//******************************************************************************
496//******************************************************************************
497ODINFUNCTION3(int,OS2bind,
498 SOCKET ,s,
499 const struct sockaddr *,addr,
500 int, namelen)
501{
502 int ret;
503
504 if(!fWSAInitialized) {
505 WSASetLastError(WSANOTINITIALISED);
506 return SOCKET_ERROR;
507 }
508 else
509 if(WSAIsBlocking()) {
510 WSASetLastError(WSAEINPROGRESS);
511 return SOCKET_ERROR;
512 }
513 else
514 if(namelen < (int)sizeof(struct sockaddr_in)) {
515 WSASetLastError(WSAEFAULT);
516 return SOCKET_ERROR;
517 }
518 ret = bind(s, (struct sockaddr *)addr, namelen);
519
520 if(ret == SOCKET_ERROR) {
521 WSASetLastError(wsaErrno());
522 }
523 else WSASetLastError(NO_ERROR);
524 return ret;
525}
526//******************************************************************************
527//******************************************************************************
528ODINFUNCTION2(int,OS2listen,
529 SOCKET, s,
530 int, backlog)
531{
532 int ret, tmp, namelen;
533 struct sockaddr_in name;
534
535 if(!fWSAInitialized) {
536 WSASetLastError(WSANOTINITIALISED);
537 return SOCKET_ERROR;
538 }
539 else
540 if(WSAIsBlocking()) {
541 WSASetLastError(WSAEINPROGRESS);
542 return SOCKET_ERROR;
543 }
544 namelen = sizeof(name);
545 ret = getsockname(s, (struct sockaddr *)&name, &namelen);
546 if (ret == 0) {
547 if (name.sin_port == 0 && name.sin_addr.s_addr == 0) {
548 // Socket is not bound
549 WSASetLastError(WSAEINVAL);
550 return SOCKET_ERROR;
551 }
552 ret = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp)) &
553 (SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
554 if(ret) {
555 // Socket is already connected
556 WSASetLastError(WSAEISCONN);
557 return SOCKET_ERROR;
558 }
559 ret = listen(s, backlog);
560 //todo: reset FD_ACCEPT bit? (wine seems to do this, but it's not documented)
561 }
562 if(ret == SOCKET_ERROR) {
563 WSASetLastError(wsaErrno());
564 }
565 else WSASetLastError(NO_ERROR);
566 return ret;
567}
568//******************************************************************************
569//******************************************************************************
570ODINFUNCTION4(int,OS2recv,
571 SOCKET,s,
572 char *,buf,
573 int,len,
574 int,flags)
575{
576 int ret;
577
578 if(!fWSAInitialized) {
579 WSASetLastError(WSANOTINITIALISED);
580 return SOCKET_ERROR;
581 }
582 else
583 if(WSAIsBlocking()) {
584 WSASetLastError(WSAEINPROGRESS);
585 return SOCKET_ERROR;
586 }
587 ret = recv(s, buf, len, flags);
588
589 if(ret == SOCKET_ERROR) {
590 WSASetLastError(wsaErrno());
591 }
592 else WSASetLastError(NO_ERROR);
593
594 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
595 EnableAsyncEvent(s, FD_READ);
596 return ret;
597}
598//******************************************************************************
599//******************************************************************************
600ODINFUNCTION6(int,OS2recvfrom,
601 SOCKET,s,
602 char *,buf,
603 int,len,
604 int,flags,
605 struct sockaddr *,from,
606 int *,fromlen)
607{
608 int ret;
609
610 if(!fWSAInitialized) {
611 WSASetLastError(WSANOTINITIALISED);
612 return SOCKET_ERROR;
613 }
614 else
615 if(WSAIsBlocking()) {
616 WSASetLastError(WSAEINPROGRESS);
617 return SOCKET_ERROR;
618 }
619 else
620 if(fromlen == NULL || *fromlen < (int)sizeof(struct sockaddr_in)) {
621 WSASetLastError(WSAEFAULT);
622 return SOCKET_ERROR;
623 }
624 ret = recvfrom(s, buf, len, flags, from, fromlen);
625
626 if(ret == SOCKET_ERROR) {
627 WSASetLastError(wsaErrno());
628 }
629 else WSASetLastError(NO_ERROR);
630
631 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
632 EnableAsyncEvent(s, FD_READ);
633 return ret;
634}
635//******************************************************************************
636//******************************************************************************
637ODINFUNCTION4(int,OS2send,
638 SOCKET,s,
639 const char *,buf,
640 int,len,
641 int,flags)
642{
643 int ret;
644
645 if(!fWSAInitialized) {
646 WSASetLastError(WSANOTINITIALISED);
647 return SOCKET_ERROR;
648 }
649 else
650 if(WSAIsBlocking()) {
651 WSASetLastError(WSAEINPROGRESS);
652 return SOCKET_ERROR;
653 }
654 ret = send(s, (char *)buf, len, flags);
655
656 if(ret == SOCKET_ERROR) {
657 WSASetLastError(wsaErrno());
658 }
659 else WSASetLastError(NO_ERROR);
660
661 //Reset FD_WRITE event flagfor WSAAsyncSelect thread if one was created for this socket
662 EnableAsyncEvent(s, FD_WRITE);
663 return ret;
664}
665//******************************************************************************
666//******************************************************************************
667ODINFUNCTION6(int,OS2sendto,
668 SOCKET,s,
669 const char *,buf,
670 int,len,
671 int,flags,
672 const struct sockaddr *,to,
673 int,tolen)
674{
675 int ret;
676
677 if(!fWSAInitialized) {
678 WSASetLastError(WSANOTINITIALISED);
679 return SOCKET_ERROR;
680 }
681 else
682 if(WSAIsBlocking()) {
683 WSASetLastError(WSAEINPROGRESS);
684 return SOCKET_ERROR;
685 }
686 else
687 if(tolen < (int)sizeof(struct sockaddr_in)) {
688 WSASetLastError(WSAEFAULT);
689 return SOCKET_ERROR;
690 }
691 ret = sendto(s, (char *)buf, len, flags, (struct sockaddr *)to, tolen);
692
693 if(ret == SOCKET_ERROR) {
694 WSASetLastError(wsaErrno());
695 }
696 else WSASetLastError(NO_ERROR);
697
698 //Reset FD_WRITE event flagfor WSAAsyncSelect thread if one was created for this socket
699 EnableAsyncEvent(s, FD_WRITE);
700 return ret;
701}
702//******************************************************************************
703//******************************************************************************
704ODINFUNCTION5(int,OS2select,
705 int,nfds,
706 ws_fd_set *,readfds,
707 ws_fd_set *,writefds,
708 ws_fd_set *,exceptfds,
709 const struct timeval *,timeout)
710{
711 int ret, i, j;
712 int *sockets, *socktmp;
713 int nrread, nrwrite, nrexcept;
714 ULONG ttimeout;
715
716 WSASetLastError(NO_ERROR);
717
718 if(!fWSAInitialized) {
719 WSASetLastError(WSANOTINITIALISED);
720 return SOCKET_ERROR;
721 }
722 else
723 if(WSAIsBlocking()) {
724 WSASetLastError(WSAEINPROGRESS);
725 return SOCKET_ERROR;
726 }
727 else {
728 nrread = nrwrite = nrexcept = 0;
729 if(readfds) {
730 nrread += readfds->fd_count;
731 }
732 if(writefds) {
733 nrwrite += writefds->fd_count;
734 }
735 if(exceptfds) {
736 nrexcept += exceptfds->fd_count;
737 }
738 if(nrread + nrwrite + nrexcept == 0) {
739 WSASetLastError(WSAEINVAL);
740 return SOCKET_ERROR;
741 }
742 if(timeout != NULL && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) {
743 WSASetLastError(WSAEINVAL);
744 return SOCKET_ERROR;
745 }
746 if(timeout == NULL) {
747 ttimeout = -1L; // no timeout
748 }
749 else ttimeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
750
751 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
752 if(readfds) {
753 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
754 }
755 if(writefds) {
756 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
757 }
758 if(exceptfds) {
759 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
760 }
761
762 ret = select(sockets, nrread, nrwrite, nrexcept, ttimeout);
763
764 if(ret == SOCKET_ERROR)
765 {
766 if(readfds != NULL)
767 readfds->fd_count = 0;
768
769 if(writefds != NULL)
770 writefds->fd_count = 0;
771
772 if(exceptfds != NULL)
773 exceptfds->fd_count = 0;
774
775 WSASetLastError(wsaErrno());
776 free(sockets);
777 return SOCKET_ERROR;
778 }
779
780 if(ret != 0) {
781 socktmp = sockets;
782 if(readfds != NULL) {
783 j = 0;
784 for(i=0;i<nrread;i++) {
785 if(socktmp[i] != -1) {
786 readfds->fd_array[i] = socktmp[i];
787 j++;
788 }
789 }
790 readfds->fd_count = j;
791 socktmp += nrread;
792 }
793
794 if(writefds != NULL) {
795 j = 0;
796 for(i=0;i<nrwrite;i++) {
797 if(socktmp[i] != -1) {
798 writefds->fd_array[i] = socktmp[i];
799 j++;
800 }
801 }
802 writefds->fd_count = j;
803 socktmp += nrwrite;
804 }
805 if(exceptfds != NULL) {
806 j = 0;
807 for(i=0;i<nrexcept;i++) {
808 if(socktmp[i] != -1) {
809 exceptfds->fd_array[i] = socktmp[i];
810 j++;
811 }
812 }
813 exceptfds->fd_count = j;
814 }
815 }
816 else {
817 if(readfds != NULL)
818 readfds->fd_count = 0;
819
820 if(writefds != NULL)
821 writefds->fd_count = 0;
822
823 if(exceptfds != NULL)
824 exceptfds->fd_count = 0;
825 }
826 free(sockets);
827 }
828 return ret;
829}
830//******************************************************************************
831//******************************************************************************
832ODINFUNCTION5(int,OS2setsockopt,
833 SOCKET,s,
834 int,level,
835 int,optname,
836 const char *,optval,
837 int,optlen)
838{
839 struct ws_linger *yy;
840 struct linger xx;
841 int ret;
842 ULONG size;
843
844 if(!fWSAInitialized) {
845 WSASetLastError(WSANOTINITIALISED);
846 return SOCKET_ERROR;
847 }
848 else
849 if(WSAIsBlocking()) {
850 WSASetLastError(WSAEINPROGRESS);
851 return SOCKET_ERROR;
852 }
853 if (level == SOL_SOCKET) {
854 switch(optname) {
855 case SO_DONTLINGER:
856 case SO_LINGER:
857 if(optlen < (int)sizeof(ws_linger)) {
858 WSASetLastError(WSAEFAULT);
859 return SOCKET_ERROR;
860 }
861 yy = (struct ws_linger *)optval;
862 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
863 xx.l_linger = yy->l_linger;
864
865 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
866 break;
867 case SO_SNDBUF:
868 case SO_RCVBUF:
869 if(optlen < (int)sizeof(int)) {
870 WSASetLastError(WSAEFAULT);
871 return SOCKET_ERROR;
872 }
873
874 size = *(ULONG *)optval;
875tryagain:
876 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
877 if(ret == SOCKET_ERROR && size > 65535) {
878 dprintf(("setsockopt: change size from %d to 65000", size));
879 //SvL: Limit send & receive buffer length to 64k
880 // (only happens with 16 bits tcpip stack?)
881 size = 65000;
882 goto tryagain;
883 }
884 break;
885
886 case SO_BROADCAST:
887 case SO_DEBUG:
888 case SO_KEEPALIVE:
889 case SO_DONTROUTE:
890 case SO_OOBINLINE:
891 case SO_REUSEADDR:
892 if(optlen < (int)sizeof(int)) {
893 WSASetLastError(WSAEFAULT);
894 return SOCKET_ERROR;
895 }
896 ret = setsockopt(s, level, optname, (char *)optval, optlen);
897 break;
898 default:
899 dprintf(("setsockopt: unknown option %x", optname));
900 WSASetLastError(WSAENOPROTOOPT);
901 return SOCKET_ERROR;
902 }
903 }
904 else
905 if(level == IPPROTO_TCP) {
906 if(optname == TCP_NODELAY) {
907 if(optlen < (int)sizeof(int)) {
908 WSASetLastError(WSAEFAULT);
909 return SOCKET_ERROR;
910 }
911 ret = setsockopt(s, level, optname, (char *)optval, optlen);
912 }
913 else {
914 dprintf(("setsockopt: unknown option %x", optname));
915 WSASetLastError(WSAENOPROTOOPT);
916 return SOCKET_ERROR;
917 }
918 }
919 else {
920 WSASetLastError(WSAEINVAL);
921 return SOCKET_ERROR;
922 }
923
924 if(ret == SOCKET_ERROR) {
925 WSASetLastError(wsaErrno());
926 }
927 else WSASetLastError(NO_ERROR);
928 return ret;
929}
930//******************************************************************************
931//******************************************************************************
932ODINFUNCTION5(int,OS2getsockopt,
933 SOCKET, s,
934 int, level,
935 int, optname,
936 char *, optval,
937 int *,optlen)
938{
939 struct ws_linger *yy;
940 struct linger xx;
941 int ret;
942 int size, options;
943
944 if(!fWSAInitialized) {
945 WSASetLastError(WSANOTINITIALISED);
946 return SOCKET_ERROR;
947 }
948 else
949 if(WSAIsBlocking()) {
950 WSASetLastError(WSAEINPROGRESS);
951 return SOCKET_ERROR;
952 }
953 if (level == SOL_SOCKET) {
954 switch(optname) {
955 case SO_DONTLINGER:
956 case SO_LINGER:
957 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
958 WSASetLastError(WSAEFAULT);
959 return SOCKET_ERROR;
960 }
961 size = sizeof(xx);
962 ret = getsockopt(s,level,optname,(char *)&xx, &size);
963 yy = (struct ws_linger *)optval;
964 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
965 yy->l_linger = xx.l_linger;
966 *optlen = size;
967 break;
968
969 case SO_SNDBUF:
970 case SO_RCVBUF:
971 case SO_BROADCAST:
972 case SO_DEBUG:
973 case SO_KEEPALIVE:
974 case SO_DONTROUTE:
975 case SO_OOBINLINE:
976 case SO_REUSEADDR:
977 case SO_TYPE:
978 if(optlen == NULL || *optlen < sizeof(int)) {
979 WSASetLastError(WSAEFAULT);
980 return SOCKET_ERROR;
981 }
982 ret = getsockopt(s, level, optname, (char *)optval, optlen);
983 break;
984 case SO_ACCEPTCONN:
985 if(optlen == NULL || *optlen < sizeof(int)) {
986 WSASetLastError(WSAEFAULT);
987 return SOCKET_ERROR;
988 }
989 size = sizeof(options);
990 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
991 if(ret != SOCKET_ERROR) {
992 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
993 *optlen = sizeof(BOOL);
994 }
995 break;
996 default:
997 dprintf(("getsockopt: unknown option %x", optname));
998 WSASetLastError(WSAENOPROTOOPT);
999 return SOCKET_ERROR;
1000 }
1001 }
1002 else
1003 if(level == IPPROTO_TCP) {
1004 if(optname == TCP_NODELAY) {
1005 if(optlen == NULL || *optlen < sizeof(int)) {
1006 WSASetLastError(WSAEFAULT);
1007 return SOCKET_ERROR;
1008 }
1009 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1010 }
1011 else {
1012 dprintf(("getsockopt: unknown option %x", optname));
1013 WSASetLastError(WSAENOPROTOOPT);
1014 return SOCKET_ERROR;
1015 }
1016 }
1017 else {
1018 WSASetLastError(WSAEINVAL);
1019 return SOCKET_ERROR;
1020 }
1021
1022 if(ret == SOCKET_ERROR) {
1023 WSASetLastError(wsaErrno());
1024 }
1025 else WSASetLastError(NO_ERROR);
1026 return ret;
1027}
1028//******************************************************************************
1029//******************************************************************************
1030/* Database function prototypes */
1031//******************************************************************************
1032//******************************************************************************
1033ODINFUNCTION2(int,OS2gethostname,
1034 char *,name,
1035 int,namelen)
1036{
1037 int ret;
1038
1039 ret = gethostname(name, namelen);
1040 if(ret == NULL) {
1041 WSASetLastError(NO_ERROR);
1042 return 0;
1043 }
1044 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1045 return SOCKET_ERROR;
1046}
1047//******************************************************************************
1048//******************************************************************************
1049ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1050 const char *,addr,
1051 int,len,
1052 int,type)
1053{
1054 LPWSINFO pwsi = WINSOCK_GetIData();
1055
1056 if( pwsi )
1057 {
1058 struct hostent* host;
1059 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1060 if( WS_dup_he(pwsi, host) ) {
1061 WSASetLastError(NO_ERROR);
1062 return pwsi->he;
1063 }
1064 else WSASetLastError(WSAENOBUFS);
1065 }
1066 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1067 }
1068 else WSASetLastError(WSANOTINITIALISED);
1069 return NULL;
1070}
1071//******************************************************************************
1072//******************************************************************************
1073ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1074 const char *,name)
1075{
1076 LPWSINFO pwsi = WINSOCK_GetIData();
1077
1078 if( pwsi )
1079 {
1080 struct hostent* host;
1081 if( (host = gethostbyname((char *)name)) != NULL ) {
1082 if( WS_dup_he(pwsi, host) ) {
1083 WSASetLastError(NO_ERROR);
1084 return pwsi->he;
1085 }
1086 else WSASetLastError(WSAENOBUFS);
1087 }
1088 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1089 }
1090 else WSASetLastError(WSANOTINITIALISED);
1091 return NULL;
1092}
1093//******************************************************************************
1094//******************************************************************************
1095ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1096 int, port,
1097 const char *, proto)
1098{
1099 LPWSINFO pwsi = WINSOCK_GetIData();
1100
1101 if( pwsi )
1102 {
1103 struct servent* serv;
1104 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1105 if( WS_dup_se(pwsi, serv) ) {
1106 WSASetLastError(NO_ERROR);
1107 return pwsi->se;
1108 }
1109 else WSASetLastError(WSAENOBUFS);
1110 }
1111 else WSASetLastError(WSANO_DATA);
1112 }
1113 else WSASetLastError(WSANOTINITIALISED);
1114 return NULL;
1115}
1116//******************************************************************************
1117//******************************************************************************
1118ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1119 const char *, name,
1120 const char *, proto)
1121{
1122 LPWSINFO pwsi = WINSOCK_GetIData();
1123
1124 if( pwsi )
1125 {
1126 struct servent *serv;
1127 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1128 if( WS_dup_se(pwsi, serv) ) {
1129 WSASetLastError(NO_ERROR);
1130 return pwsi->se;
1131 }
1132 else WSASetLastError(WSAENOBUFS);
1133 }
1134 else WSASetLastError(WSANO_DATA);
1135 }
1136 else WSASetLastError(WSANOTINITIALISED);
1137 return NULL;
1138}
1139//******************************************************************************
1140//******************************************************************************
1141ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1142 int,number)
1143{
1144 LPWSINFO pwsi = WINSOCK_GetIData();
1145
1146 if( pwsi )
1147 {
1148 struct protoent* proto;
1149 if( (proto = getprotobynumber(number)) != NULL ) {
1150 if( WS_dup_pe(pwsi, proto) ) {
1151 WSASetLastError(NO_ERROR);
1152 return pwsi->pe;
1153 }
1154 else WSASetLastError(WSAENOBUFS);
1155 }
1156 else WSASetLastError(WSANO_DATA);
1157 }
1158 else WSASetLastError(WSANOTINITIALISED);
1159 return NULL;
1160}
1161//******************************************************************************
1162//******************************************************************************
1163ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1164 const char *,name)
1165{
1166 LPWSINFO pwsi = WINSOCK_GetIData();
1167
1168 if( pwsi )
1169 {
1170 struct protoent * proto;
1171 if( (proto = getprotobyname((char *)name)) != NULL ) {
1172 if(WS_dup_pe(pwsi, proto)) {
1173 WSASetLastError(NO_ERROR);
1174 return pwsi->pe;
1175 }
1176 else WSASetLastError(WSAENOBUFS);
1177 }
1178 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1179 }
1180 else WSASetLastError(WSANOTINITIALISED);
1181 return NULL;
1182}
1183//******************************************************************************
1184//******************************************************************************
Note: See TracBrowser for help on using the repository browser.