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

Last change on this file since 6496 was 6253, checked in by achimha, 24 years ago

IPPROTO_IP support for setsockopt, WSAEnumNetworkEvents fixes

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