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

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

socket error fixes

File size: 32.7 KB
Line 
1/* $Id: wsock32.cpp,v 1.26 2000-03-28 17:13:06 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 for(i=0;i<nrread;i++) {
784 if(socktmp[i] != -1) {
785 readfds->fd_array[j] = socktmp[i];
786 }
787 }
788 readfds->fd_count = i;
789 socktmp += nrread;
790 }
791
792 if(writefds != NULL) {
793 for(i=0;i<nrwrite;i++) {
794 if(socktmp[i] != -1) {
795 writefds->fd_array[j] = socktmp[i];
796 }
797 }
798 writefds->fd_count = i;
799 socktmp += nrwrite;
800 }
801 if(exceptfds != NULL) {
802 for(i=0;i<nrexcept;i++) {
803 if(socktmp[i] != -1) {
804 exceptfds->fd_array[j] = socktmp[i];
805 }
806 }
807 exceptfds->fd_count = i;
808 }
809 }
810 else {
811 if(readfds != NULL)
812 readfds->fd_count = 0;
813
814 if(writefds != NULL)
815 writefds->fd_count = 0;
816
817 if(exceptfds != NULL)
818 exceptfds->fd_count = 0;
819 }
820 free(sockets);
821 }
822 return ret;
823}
824//******************************************************************************
825//******************************************************************************
826ODINFUNCTION5(int,OS2setsockopt,
827 SOCKET,s,
828 int,level,
829 int,optname,
830 const char *,optval,
831 int,optlen)
832{
833 struct ws_linger *yy;
834 struct linger xx;
835 int ret;
836 ULONG size;
837
838 if(!fWSAInitialized) {
839 WSASetLastError(WSANOTINITIALISED);
840 return SOCKET_ERROR;
841 }
842 else
843 if(WSAIsBlocking()) {
844 WSASetLastError(WSAEINPROGRESS);
845 return SOCKET_ERROR;
846 }
847 if (level == SOL_SOCKET) {
848 switch(optname) {
849 case SO_DONTLINGER:
850 case SO_LINGER:
851 if(optlen < (int)sizeof(ws_linger)) {
852 WSASetLastError(WSAEFAULT);
853 return SOCKET_ERROR;
854 }
855 yy = (struct ws_linger *)optval;
856 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
857 xx.l_linger = yy->l_linger;
858
859 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
860 break;
861 case SO_SNDBUF:
862 case SO_RCVBUF:
863 if(optlen < (int)sizeof(int)) {
864 WSASetLastError(WSAEFAULT);
865 return SOCKET_ERROR;
866 }
867
868 size = *(ULONG *)optval;
869tryagain:
870 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
871 if(ret == SOCKET_ERROR && size > 65535) {
872 dprintf(("setsockopt: change size from %d to 65000", size));
873 //SvL: Limit send & receive buffer length to 64k
874 // (only happens with 16 bits tcpip stack?)
875 size = 65000;
876 goto tryagain;
877 }
878 break;
879
880 case SO_BROADCAST:
881 case SO_DEBUG:
882 case SO_KEEPALIVE:
883 case SO_DONTROUTE:
884 case SO_OOBINLINE:
885 case SO_REUSEADDR:
886 if(optlen < (int)sizeof(int)) {
887 WSASetLastError(WSAEFAULT);
888 return SOCKET_ERROR;
889 }
890 ret = setsockopt(s, level, optname, (char *)optval, optlen);
891 break;
892 default:
893 dprintf(("setsockopt: unknown option %x", optname));
894 WSASetLastError(WSAENOPROTOOPT);
895 return SOCKET_ERROR;
896 }
897 }
898 else
899 if(level == IPPROTO_TCP) {
900 if(optname == TCP_NODELAY) {
901 if(optlen < (int)sizeof(int)) {
902 WSASetLastError(WSAEFAULT);
903 return SOCKET_ERROR;
904 }
905 ret = setsockopt(s, level, optname, (char *)optval, optlen);
906 }
907 else {
908 dprintf(("setsockopt: unknown option %x", optname));
909 WSASetLastError(WSAENOPROTOOPT);
910 return SOCKET_ERROR;
911 }
912 }
913 else {
914 WSASetLastError(WSAEINVAL);
915 return SOCKET_ERROR;
916 }
917
918 if(ret == SOCKET_ERROR) {
919 WSASetLastError(wsaErrno());
920 }
921 else WSASetLastError(NO_ERROR);
922 return ret;
923}
924//******************************************************************************
925//******************************************************************************
926ODINFUNCTION5(int,OS2getsockopt,
927 SOCKET, s,
928 int, level,
929 int, optname,
930 char *, optval,
931 int *,optlen)
932{
933 struct ws_linger *yy;
934 struct linger xx;
935 int ret;
936 int size, options;
937
938 if(!fWSAInitialized) {
939 WSASetLastError(WSANOTINITIALISED);
940 return SOCKET_ERROR;
941 }
942 else
943 if(WSAIsBlocking()) {
944 WSASetLastError(WSAEINPROGRESS);
945 return SOCKET_ERROR;
946 }
947 if (level == SOL_SOCKET) {
948 switch(optname) {
949 case SO_DONTLINGER:
950 case SO_LINGER:
951 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
952 WSASetLastError(WSAEFAULT);
953 return SOCKET_ERROR;
954 }
955 size = sizeof(xx);
956 ret = getsockopt(s,level,optname,(char *)&xx, &size);
957 yy = (struct ws_linger *)optval;
958 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
959 yy->l_linger = xx.l_linger;
960 *optlen = size;
961 break;
962
963 case SO_SNDBUF:
964 case SO_RCVBUF:
965 case SO_BROADCAST:
966 case SO_DEBUG:
967 case SO_KEEPALIVE:
968 case SO_DONTROUTE:
969 case SO_OOBINLINE:
970 case SO_REUSEADDR:
971 case SO_TYPE:
972 if(optlen == NULL || *optlen < sizeof(int)) {
973 WSASetLastError(WSAEFAULT);
974 return SOCKET_ERROR;
975 }
976 ret = getsockopt(s, level, optname, (char *)optval, optlen);
977 break;
978 case SO_ACCEPTCONN:
979 if(optlen == NULL || *optlen < sizeof(int)) {
980 WSASetLastError(WSAEFAULT);
981 return SOCKET_ERROR;
982 }
983 size = sizeof(options);
984 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
985 if(ret != SOCKET_ERROR) {
986 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
987 *optlen = sizeof(BOOL);
988 }
989 break;
990 default:
991 dprintf(("getsockopt: unknown option %x", optname));
992 WSASetLastError(WSAENOPROTOOPT);
993 return SOCKET_ERROR;
994 }
995 }
996 else
997 if(level == IPPROTO_TCP) {
998 if(optname == TCP_NODELAY) {
999 if(optlen == NULL || *optlen < sizeof(int)) {
1000 WSASetLastError(WSAEFAULT);
1001 return SOCKET_ERROR;
1002 }
1003 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1004 }
1005 else {
1006 dprintf(("getsockopt: unknown option %x", optname));
1007 WSASetLastError(WSAENOPROTOOPT);
1008 return SOCKET_ERROR;
1009 }
1010 }
1011 else {
1012 WSASetLastError(WSAEINVAL);
1013 return SOCKET_ERROR;
1014 }
1015
1016 if(ret == SOCKET_ERROR) {
1017 WSASetLastError(wsaErrno());
1018 }
1019 else WSASetLastError(NO_ERROR);
1020 return ret;
1021}
1022//******************************************************************************
1023//******************************************************************************
1024/* Database function prototypes */
1025//******************************************************************************
1026//******************************************************************************
1027ODINFUNCTION2(int,OS2gethostname,
1028 char *,name,
1029 int,namelen)
1030{
1031 int ret;
1032
1033 ret = gethostname(name, namelen);
1034 if(ret == NULL) {
1035 WSASetLastError(NO_ERROR);
1036 return 0;
1037 }
1038 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1039 return SOCKET_ERROR;
1040}
1041//******************************************************************************
1042//******************************************************************************
1043ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1044 const char *,addr,
1045 int,len,
1046 int,type)
1047{
1048 LPWSINFO pwsi = WINSOCK_GetIData();
1049
1050 if( pwsi )
1051 {
1052 struct hostent* host;
1053 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1054 if( WS_dup_he(pwsi, host) ) {
1055 WSASetLastError(NO_ERROR);
1056 return pwsi->he;
1057 }
1058 else WSASetLastError(WSAENOBUFS);
1059 }
1060 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1061 }
1062 else WSASetLastError(WSANOTINITIALISED);
1063 return NULL;
1064}
1065//******************************************************************************
1066//******************************************************************************
1067ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1068 const char *,name)
1069{
1070 LPWSINFO pwsi = WINSOCK_GetIData();
1071
1072 if( pwsi )
1073 {
1074 struct hostent* host;
1075 if( (host = gethostbyname((char *)name)) != NULL ) {
1076 if( WS_dup_he(pwsi, host) ) {
1077 WSASetLastError(NO_ERROR);
1078 return pwsi->he;
1079 }
1080 else WSASetLastError(WSAENOBUFS);
1081 }
1082 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1083 }
1084 else WSASetLastError(WSANOTINITIALISED);
1085 return NULL;
1086}
1087//******************************************************************************
1088//******************************************************************************
1089ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1090 int, port,
1091 const char *, proto)
1092{
1093 LPWSINFO pwsi = WINSOCK_GetIData();
1094
1095 if( pwsi )
1096 {
1097 struct servent* serv;
1098 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1099 if( WS_dup_se(pwsi, serv) ) {
1100 WSASetLastError(NO_ERROR);
1101 return pwsi->se;
1102 }
1103 else WSASetLastError(WSAENOBUFS);
1104 }
1105 else WSASetLastError(WSANO_DATA);
1106 }
1107 else WSASetLastError(WSANOTINITIALISED);
1108 return NULL;
1109}
1110//******************************************************************************
1111//******************************************************************************
1112ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1113 const char *, name,
1114 const char *, proto)
1115{
1116 LPWSINFO pwsi = WINSOCK_GetIData();
1117
1118 if( pwsi )
1119 {
1120 struct servent *serv;
1121 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1122 if( WS_dup_se(pwsi, serv) ) {
1123 WSASetLastError(NO_ERROR);
1124 return pwsi->se;
1125 }
1126 else WSASetLastError(WSAENOBUFS);
1127 }
1128 else WSASetLastError(WSANO_DATA);
1129 }
1130 else WSASetLastError(WSANOTINITIALISED);
1131 return NULL;
1132}
1133//******************************************************************************
1134//******************************************************************************
1135ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1136 int,number)
1137{
1138 LPWSINFO pwsi = WINSOCK_GetIData();
1139
1140 if( pwsi )
1141 {
1142 struct protoent* proto;
1143 if( (proto = getprotobynumber(number)) != NULL ) {
1144 if( WS_dup_pe(pwsi, proto) ) {
1145 WSASetLastError(NO_ERROR);
1146 return pwsi->pe;
1147 }
1148 else WSASetLastError(WSAENOBUFS);
1149 }
1150 else WSASetLastError(WSANO_DATA);
1151 }
1152 else WSASetLastError(WSANOTINITIALISED);
1153 return NULL;
1154}
1155//******************************************************************************
1156//******************************************************************************
1157ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1158 const char *,name)
1159{
1160 LPWSINFO pwsi = WINSOCK_GetIData();
1161
1162 if( pwsi )
1163 {
1164 struct protoent * proto;
1165 if( (proto = getprotobyname((char *)name)) != NULL ) {
1166 if(WS_dup_pe(pwsi, proto)) {
1167 WSASetLastError(NO_ERROR);
1168 return pwsi->pe;
1169 }
1170 else WSASetLastError(WSAENOBUFS);
1171 }
1172 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1173 }
1174 else WSASetLastError(WSANOTINITIALISED);
1175 return NULL;
1176}
1177//******************************************************************************
1178//******************************************************************************
Note: See TracBrowser for help on using the repository browser.