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

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

experimental recv fix

File size: 33.5 KB
Line 
1/* $Id: wsock32.cpp,v 1.31 2000-05-09 19:01: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
597 if(ret == 0) {
598 int tmp, state;
599
600 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
601 if(state & SS_ISCONNECTED && flags != MSG_PEEK) {
602 dprintf(("recv returned 0, but socket is still connected -> return WSAWOULDBLOCK"));
603 WSASetLastError(WSAEWOULDBLOCK);
604 ret = SOCKET_ERROR;
605 }
606 }
607 else WSASetLastError(NO_ERROR);
608
609 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
610 EnableAsyncEvent(s, FD_READ);
611 return ret;
612}
613//******************************************************************************
614//******************************************************************************
615ODINFUNCTION6(int,OS2recvfrom,
616 SOCKET,s,
617 char *,buf,
618 int,len,
619 int,flags,
620 struct sockaddr *,from,
621 int *,fromlen)
622{
623 int ret;
624
625 if(!fWSAInitialized) {
626 WSASetLastError(WSANOTINITIALISED);
627 return SOCKET_ERROR;
628 }
629 else
630 if(WSAIsBlocking()) {
631 WSASetLastError(WSAEINPROGRESS);
632 return SOCKET_ERROR;
633 }
634 else
635 if(fromlen == NULL || *fromlen < (int)sizeof(struct sockaddr_in)) {
636 WSASetLastError(WSAEFAULT);
637 return SOCKET_ERROR;
638 }
639 ret = recvfrom(s, buf, len, flags, from, fromlen);
640
641 if(ret == SOCKET_ERROR) {
642 WSASetLastError(wsaErrno());
643 }
644 else WSASetLastError(NO_ERROR);
645
646 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
647 EnableAsyncEvent(s, FD_READ);
648 return ret;
649}
650//******************************************************************************
651//******************************************************************************
652ODINFUNCTION4(int,OS2send,
653 SOCKET,s,
654 const char *,buf,
655 int,len,
656 int,flags)
657{
658 int ret;
659
660 if(!fWSAInitialized) {
661 WSASetLastError(WSANOTINITIALISED);
662 return SOCKET_ERROR;
663 }
664 else
665 if(WSAIsBlocking()) {
666 WSASetLastError(WSAEINPROGRESS);
667 return SOCKET_ERROR;
668 }
669 ret = send(s, (char *)buf, len, flags);
670
671 if(ret == SOCKET_ERROR) {
672 WSASetLastError(wsaErrno());
673 }
674 else WSASetLastError(NO_ERROR);
675
676 //Reset FD_WRITE event flagfor WSAAsyncSelect thread if one was created for this socket
677 EnableAsyncEvent(s, FD_WRITE);
678 return ret;
679}
680//******************************************************************************
681//******************************************************************************
682ODINFUNCTION6(int,OS2sendto,
683 SOCKET,s,
684 const char *,buf,
685 int,len,
686 int,flags,
687 const struct sockaddr *,to,
688 int,tolen)
689{
690 int ret;
691
692 if(!fWSAInitialized) {
693 WSASetLastError(WSANOTINITIALISED);
694 return SOCKET_ERROR;
695 }
696 else
697 if(WSAIsBlocking()) {
698 WSASetLastError(WSAEINPROGRESS);
699 return SOCKET_ERROR;
700 }
701 else
702 if(tolen < (int)sizeof(struct sockaddr_in)) {
703 WSASetLastError(WSAEFAULT);
704 return SOCKET_ERROR;
705 }
706 ret = sendto(s, (char *)buf, len, flags, (struct sockaddr *)to, tolen);
707
708 if(ret == SOCKET_ERROR) {
709 WSASetLastError(wsaErrno());
710 }
711 else WSASetLastError(NO_ERROR);
712
713 //Reset FD_WRITE event flagfor WSAAsyncSelect thread if one was created for this socket
714 EnableAsyncEvent(s, FD_WRITE);
715 return ret;
716}
717//******************************************************************************
718//******************************************************************************
719ODINFUNCTION5(int,OS2select,
720 int,nfds,
721 ws_fd_set *,readfds,
722 ws_fd_set *,writefds,
723 ws_fd_set *,exceptfds,
724 const struct timeval *,timeout)
725{
726 int ret, i, j;
727 int *sockets, *socktmp;
728 int nrread, nrwrite, nrexcept;
729 ULONG ttimeout;
730
731 WSASetLastError(NO_ERROR);
732
733 if(!fWSAInitialized) {
734 WSASetLastError(WSANOTINITIALISED);
735 return SOCKET_ERROR;
736 }
737 else
738 if(WSAIsBlocking()) {
739 WSASetLastError(WSAEINPROGRESS);
740 return SOCKET_ERROR;
741 }
742 else {
743 nrread = nrwrite = nrexcept = 0;
744 if(readfds) {
745 nrread += readfds->fd_count;
746 }
747 if(writefds) {
748 nrwrite += writefds->fd_count;
749 }
750 if(exceptfds) {
751 nrexcept += exceptfds->fd_count;
752 }
753 if(nrread + nrwrite + nrexcept == 0) {
754 WSASetLastError(WSAEINVAL);
755 return SOCKET_ERROR;
756 }
757 if(timeout != NULL && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) {
758 WSASetLastError(WSAEINVAL);
759 return SOCKET_ERROR;
760 }
761 if(timeout == NULL) {
762 ttimeout = -1L; // no timeout
763 }
764 else ttimeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
765
766 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
767 if(readfds) {
768 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
769 }
770 if(writefds) {
771 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
772 }
773 if(exceptfds) {
774 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
775 }
776
777 ret = select(sockets, nrread, nrwrite, nrexcept, ttimeout);
778
779 if(ret == SOCKET_ERROR)
780 {
781 if(readfds != NULL)
782 readfds->fd_count = 0;
783
784 if(writefds != NULL)
785 writefds->fd_count = 0;
786
787 if(exceptfds != NULL)
788 exceptfds->fd_count = 0;
789
790 WSASetLastError(wsaErrno());
791 free(sockets);
792 return SOCKET_ERROR;
793 }
794
795 if(ret != 0) {
796 socktmp = sockets;
797 if(readfds != NULL) {
798 j = 0;
799 for(i=0;i<nrread;i++) {
800 if(socktmp[i] != -1) {
801 readfds->fd_array[i] = socktmp[i];
802 j++;
803 }
804 }
805 readfds->fd_count = j;
806 socktmp += nrread;
807 }
808
809 if(writefds != NULL) {
810 j = 0;
811 for(i=0;i<nrwrite;i++) {
812 if(socktmp[i] != -1) {
813 writefds->fd_array[i] = socktmp[i];
814 j++;
815 }
816 }
817 writefds->fd_count = j;
818 socktmp += nrwrite;
819 }
820 if(exceptfds != NULL) {
821 j = 0;
822 for(i=0;i<nrexcept;i++) {
823 if(socktmp[i] != -1) {
824 exceptfds->fd_array[i] = socktmp[i];
825 j++;
826 }
827 }
828 exceptfds->fd_count = j;
829 }
830 }
831 else {
832 if(readfds != NULL)
833 readfds->fd_count = 0;
834
835 if(writefds != NULL)
836 writefds->fd_count = 0;
837
838 if(exceptfds != NULL)
839 exceptfds->fd_count = 0;
840 }
841 free(sockets);
842 }
843 return ret;
844}
845//******************************************************************************
846//******************************************************************************
847ODINFUNCTION5(int,OS2setsockopt,
848 SOCKET,s,
849 int,level,
850 int,optname,
851 const char *,optval,
852 int,optlen)
853{
854 struct ws_linger *yy;
855 struct linger xx;
856 int ret;
857 ULONG size;
858 char *safeoptval;
859
860 if(!fWSAInitialized) {
861 WSASetLastError(WSANOTINITIALISED);
862 return SOCKET_ERROR;
863 }
864 else
865 if(WSAIsBlocking()) {
866 WSASetLastError(WSAEINPROGRESS);
867 return SOCKET_ERROR;
868 }
869 //SvL: The 16 bits TCP/IP stack doesn't like high addresses, so copy
870 // the option value(s) on the stack.
871 safeoptval = (char *)alloca(optlen);
872 if(safeoptval == NULL) {
873 DebugInt3();
874 WSASetLastError(WSAEFAULT);
875 return SOCKET_ERROR;
876 }
877 memcpy(safeoptval, optval, optlen);
878 optval = safeoptval;
879
880 if (level == SOL_SOCKET) {
881 switch(optname) {
882 case SO_DONTLINGER:
883 case SO_LINGER:
884 if(optlen < (int)sizeof(ws_linger)) {
885 WSASetLastError(WSAEFAULT);
886 return SOCKET_ERROR;
887 }
888 yy = (struct ws_linger *)optval;
889 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
890 xx.l_linger = yy->l_linger;
891
892 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
893 break;
894 case SO_SNDBUF:
895 case SO_RCVBUF:
896 if(optlen < (int)sizeof(int)) {
897 WSASetLastError(WSAEFAULT);
898 return SOCKET_ERROR;
899 }
900
901 size = *(ULONG *)optval;
902tryagain:
903 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
904 if(ret == SOCKET_ERROR && wsaErrno() == WSAENOBUFS && size > 4096) {
905 int newsize = (size > 65535) ? 63*1024 : (size-1024);
906 dprintf(("setsockopt: change size from %d to %d", size, newsize));
907 //SvL: Limit send & receive buffer length to 64k
908 // (only happens with 16 bits tcpip stack?)
909 size = newsize;
910 goto tryagain;
911 }
912 break;
913
914 case SO_BROADCAST:
915 case SO_DEBUG:
916 case SO_KEEPALIVE:
917 case SO_DONTROUTE:
918 case SO_OOBINLINE:
919 case SO_REUSEADDR:
920 if(optlen < (int)sizeof(int)) {
921 WSASetLastError(WSAEFAULT);
922 return SOCKET_ERROR;
923 }
924 ret = setsockopt(s, level, optname, (char *)optval, optlen);
925 break;
926 default:
927 dprintf(("setsockopt: unknown option %x", optname));
928 WSASetLastError(WSAENOPROTOOPT);
929 return SOCKET_ERROR;
930 }
931 }
932 else
933 if(level == IPPROTO_TCP) {
934 if(optname == TCP_NODELAY) {
935 if(optlen < (int)sizeof(int)) {
936 WSASetLastError(WSAEFAULT);
937 return SOCKET_ERROR;
938 }
939 ret = setsockopt(s, level, optname, (char *)optval, optlen);
940 }
941 else {
942 dprintf(("setsockopt: unknown option %x", optname));
943 WSASetLastError(WSAENOPROTOOPT);
944 return SOCKET_ERROR;
945 }
946 }
947 else {
948 WSASetLastError(WSAEINVAL);
949 return SOCKET_ERROR;
950 }
951
952 if(ret == SOCKET_ERROR) {
953 WSASetLastError(wsaErrno());
954 }
955 else WSASetLastError(NO_ERROR);
956 return ret;
957}
958//******************************************************************************
959//******************************************************************************
960ODINFUNCTION5(int,OS2getsockopt,
961 SOCKET, s,
962 int, level,
963 int, optname,
964 char *, optval,
965 int *,optlen)
966{
967 struct ws_linger *yy;
968 struct linger xx;
969 int ret;
970 int size, options;
971
972 if(!fWSAInitialized) {
973 WSASetLastError(WSANOTINITIALISED);
974 return SOCKET_ERROR;
975 }
976 else
977 if(WSAIsBlocking()) {
978 WSASetLastError(WSAEINPROGRESS);
979 return SOCKET_ERROR;
980 }
981 if (level == SOL_SOCKET) {
982 switch(optname) {
983 case SO_DONTLINGER:
984 case SO_LINGER:
985 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
986 WSASetLastError(WSAEFAULT);
987 return SOCKET_ERROR;
988 }
989 size = sizeof(xx);
990 ret = getsockopt(s,level,optname,(char *)&xx, &size);
991 yy = (struct ws_linger *)optval;
992 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
993 yy->l_linger = xx.l_linger;
994 *optlen = size;
995 break;
996
997 case SO_SNDBUF:
998 case SO_RCVBUF:
999 case SO_BROADCAST:
1000 case SO_DEBUG:
1001 case SO_KEEPALIVE:
1002 case SO_DONTROUTE:
1003 case SO_OOBINLINE:
1004 case SO_REUSEADDR:
1005 case SO_TYPE:
1006 if(optlen == NULL || *optlen < sizeof(int)) {
1007 WSASetLastError(WSAEFAULT);
1008 return SOCKET_ERROR;
1009 }
1010 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1011 break;
1012 case SO_ACCEPTCONN:
1013 if(optlen == NULL || *optlen < sizeof(int)) {
1014 WSASetLastError(WSAEFAULT);
1015 return SOCKET_ERROR;
1016 }
1017 size = sizeof(options);
1018 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
1019 if(ret != SOCKET_ERROR) {
1020 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
1021 *optlen = sizeof(BOOL);
1022 }
1023 break;
1024 default:
1025 dprintf(("getsockopt: unknown option %x", optname));
1026 WSASetLastError(WSAENOPROTOOPT);
1027 return SOCKET_ERROR;
1028 }
1029 }
1030 else
1031 if(level == IPPROTO_TCP) {
1032 if(optname == TCP_NODELAY) {
1033 if(optlen == NULL || *optlen < sizeof(int)) {
1034 WSASetLastError(WSAEFAULT);
1035 return SOCKET_ERROR;
1036 }
1037 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1038 }
1039 else {
1040 dprintf(("getsockopt: unknown option %x", optname));
1041 WSASetLastError(WSAENOPROTOOPT);
1042 return SOCKET_ERROR;
1043 }
1044 }
1045 else {
1046 WSASetLastError(WSAEINVAL);
1047 return SOCKET_ERROR;
1048 }
1049
1050 if(ret == SOCKET_ERROR) {
1051 WSASetLastError(wsaErrno());
1052 }
1053 else WSASetLastError(NO_ERROR);
1054 return ret;
1055}
1056//******************************************************************************
1057//******************************************************************************
1058/* Database function prototypes */
1059//******************************************************************************
1060//******************************************************************************
1061ODINFUNCTION2(int,OS2gethostname,
1062 char *,name,
1063 int,namelen)
1064{
1065 int ret;
1066
1067 ret = gethostname(name, namelen);
1068 if(ret == NULL) {
1069 WSASetLastError(NO_ERROR);
1070 return 0;
1071 }
1072 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1073 return SOCKET_ERROR;
1074}
1075//******************************************************************************
1076//******************************************************************************
1077ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1078 const char *,addr,
1079 int,len,
1080 int,type)
1081{
1082 LPWSINFO pwsi = WINSOCK_GetIData();
1083
1084 if( pwsi )
1085 {
1086 struct hostent* host;
1087 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1088 if( WS_dup_he(pwsi, host) ) {
1089 WSASetLastError(NO_ERROR);
1090 return pwsi->he;
1091 }
1092 else WSASetLastError(WSAENOBUFS);
1093 }
1094 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1095 }
1096 else WSASetLastError(WSANOTINITIALISED);
1097 return NULL;
1098}
1099//******************************************************************************
1100//******************************************************************************
1101ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1102 const char *,name)
1103{
1104 LPWSINFO pwsi = WINSOCK_GetIData();
1105
1106 if( pwsi )
1107 {
1108 struct hostent* host;
1109 if( (host = gethostbyname((char *)name)) != NULL ) {
1110 if( WS_dup_he(pwsi, host) ) {
1111 WSASetLastError(NO_ERROR);
1112 return pwsi->he;
1113 }
1114 else WSASetLastError(WSAENOBUFS);
1115 }
1116 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1117 }
1118 else WSASetLastError(WSANOTINITIALISED);
1119 return NULL;
1120}
1121//******************************************************************************
1122//******************************************************************************
1123ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1124 int, port,
1125 const char *, proto)
1126{
1127 LPWSINFO pwsi = WINSOCK_GetIData();
1128
1129 if( pwsi )
1130 {
1131 struct servent* serv;
1132 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1133 if( WS_dup_se(pwsi, serv) ) {
1134 WSASetLastError(NO_ERROR);
1135 return pwsi->se;
1136 }
1137 else WSASetLastError(WSAENOBUFS);
1138 }
1139 else WSASetLastError(WSANO_DATA);
1140 }
1141 else WSASetLastError(WSANOTINITIALISED);
1142 return NULL;
1143}
1144//******************************************************************************
1145//******************************************************************************
1146ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1147 const char *, name,
1148 const char *, proto)
1149{
1150 LPWSINFO pwsi = WINSOCK_GetIData();
1151
1152 if( pwsi )
1153 {
1154 struct servent *serv;
1155 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1156 if( WS_dup_se(pwsi, serv) ) {
1157 WSASetLastError(NO_ERROR);
1158 return pwsi->se;
1159 }
1160 else WSASetLastError(WSAENOBUFS);
1161 }
1162 else WSASetLastError(WSANO_DATA);
1163 }
1164 else WSASetLastError(WSANOTINITIALISED);
1165 return NULL;
1166}
1167//******************************************************************************
1168//******************************************************************************
1169ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1170 int,number)
1171{
1172 LPWSINFO pwsi = WINSOCK_GetIData();
1173
1174 if( pwsi )
1175 {
1176 struct protoent* proto;
1177 if( (proto = getprotobynumber(number)) != NULL ) {
1178 if( WS_dup_pe(pwsi, proto) ) {
1179 WSASetLastError(NO_ERROR);
1180 return pwsi->pe;
1181 }
1182 else WSASetLastError(WSAENOBUFS);
1183 }
1184 else WSASetLastError(WSANO_DATA);
1185 }
1186 else WSASetLastError(WSANOTINITIALISED);
1187 return NULL;
1188}
1189//******************************************************************************
1190//******************************************************************************
1191ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1192 const char *,name)
1193{
1194 LPWSINFO pwsi = WINSOCK_GetIData();
1195
1196 if( pwsi )
1197 {
1198 struct protoent * proto;
1199 if( (proto = getprotobyname((char *)name)) != NULL ) {
1200 if(WS_dup_pe(pwsi, proto)) {
1201 WSASetLastError(NO_ERROR);
1202 return pwsi->pe;
1203 }
1204 else WSASetLastError(WSAENOBUFS);
1205 }
1206 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1207 }
1208 else WSASetLastError(WSANOTINITIALISED);
1209 return NULL;
1210}
1211//******************************************************************************
1212//******************************************************************************
Note: See TracBrowser for help on using the repository browser.