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

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

send/receive bufsize setsockopt bugfix for 16 bits tcpip stack

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