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

Last change on this file since 6983 was 6983, checked in by sandervl, 24 years ago

added more IPPROTO_IP options (setsockopt)

File size: 36.9 KB
Line 
1/* $Id: wsock32.cpp,v 1.38 2001-10-10 14:41:22 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#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 0
799 if(nrread + nrwrite + nrexcept == 0) {
800 dprintf(("ERROR: nrread + nrwrite + nrexcept == 0"));
801 WSASetLastError(WSAEINVAL);
802 return SOCKET_ERROR;
803 }
804#endif
805 if(timeout != NULL && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) {
806 dprintf(("ERROR: timeout->tv_sec < 0 || timeout->tv_usec < 0"));
807 WSASetLastError(WSAEINVAL);
808 return SOCKET_ERROR;
809 }
810 if(timeout == NULL) {
811 ttimeout = -1L; // no timeout
812 }
813 else ttimeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
814
815 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
816 if(readfds) {
817 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
818 }
819 if(writefds) {
820 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
821 }
822 if(exceptfds) {
823 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
824 }
825
826 ret = select(sockets, nrread, nrwrite, nrexcept, ttimeout);
827
828 if(ret == SOCKET_ERROR)
829 {
830 if(readfds != NULL)
831 readfds->fd_count = 0;
832
833 if(writefds != NULL)
834 writefds->fd_count = 0;
835
836 if(exceptfds != NULL)
837 exceptfds->fd_count = 0;
838
839 WSASetLastError(wsaErrno());
840 free(sockets);
841 return SOCKET_ERROR;
842 }
843
844 if(ret != 0) {
845 socktmp = sockets;
846 if(readfds != NULL) {
847 j = 0;
848 for(i=0;i<nrread;i++) {
849 if(socktmp[i] != -1) {
850 readfds->fd_array[i] = socktmp[i];
851 j++;
852 }
853 }
854 readfds->fd_count = j;
855 socktmp += nrread;
856 }
857
858 if(writefds != NULL) {
859 j = 0;
860 for(i=0;i<nrwrite;i++) {
861 if(socktmp[i] != -1) {
862 writefds->fd_array[i] = socktmp[i];
863 j++;
864 }
865 }
866 writefds->fd_count = j;
867 socktmp += nrwrite;
868 }
869 if(exceptfds != NULL) {
870 j = 0;
871 for(i=0;i<nrexcept;i++) {
872 if(socktmp[i] != -1) {
873 exceptfds->fd_array[i] = socktmp[i];
874 j++;
875 }
876 }
877 exceptfds->fd_count = j;
878 }
879 }
880 else {
881 if(readfds != NULL)
882 readfds->fd_count = 0;
883
884 if(writefds != NULL)
885 writefds->fd_count = 0;
886
887 if(exceptfds != NULL)
888 exceptfds->fd_count = 0;
889 }
890 free(sockets);
891 }
892 return ret;
893}
894//******************************************************************************
895//******************************************************************************
896ODINFUNCTION5(int,OS2setsockopt,
897 SOCKET,s,
898 int,level,
899 int,optname,
900 const char *,optval,
901 int,optlen)
902{
903 struct ws_linger *yy;
904 struct linger xx;
905 int ret;
906 ULONG size;
907 char *safeoptval;
908
909 if(!fWSAInitialized) {
910 dprintf(("WSA not initialized"));
911 WSASetLastError(WSANOTINITIALISED);
912 return SOCKET_ERROR;
913 }
914 else
915 if(WSAIsBlocking()) {
916 dprintf(("WSA is blocking"));
917 WSASetLastError(WSAEINPROGRESS);
918 return SOCKET_ERROR;
919 }
920 //SvL: The 16 bits TCP/IP stack doesn't like high addresses, so copy
921 // the option value(s) on the stack.
922 safeoptval = (char *)alloca(optlen);
923 if(safeoptval == NULL) {
924 DebugInt3();
925 WSASetLastError(WSAEFAULT);
926 return SOCKET_ERROR;
927 }
928 memcpy(safeoptval, optval, optlen);
929 optval = safeoptval;
930
931 if (level == SOL_SOCKET)
932 {
933 switch(optname)
934 {
935 case SO_DONTLINGER:
936 case SO_LINGER:
937 if(optlen < (int)sizeof(ws_linger))
938 {
939 dprintf(("SOL_SOCKET, SO_LINGER, optlen too small"));
940 WSASetLastError(WSAEFAULT);
941 return SOCKET_ERROR;
942 }
943 yy = (struct ws_linger *)optval;
944 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
945 xx.l_linger = yy->l_linger;
946
947 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
948 break;
949 case SO_SNDBUF:
950 case SO_RCVBUF:
951 if(optlen < (int)sizeof(int))
952 {
953 dprintf(("SOL_SOCKET, SO_RCVBUF, optlen too small"));
954 WSASetLastError(WSAEFAULT);
955 return SOCKET_ERROR;
956 }
957
958 size = *(ULONG *)optval;
959tryagain:
960 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
961 if(ret == SOCKET_ERROR && wsaErrno() == WSAENOBUFS && size > 4096) {
962 int newsize = (size > 65535) ? 63*1024 : (size-1024);
963 dprintf(("setsockopt: change size from %d to %d", size, newsize));
964 //SvL: Limit send & receive buffer length to 64k
965 // (only happens with 16 bits tcpip stack?)
966 size = newsize;
967 goto tryagain;
968 }
969 break;
970
971 case SO_BROADCAST:
972 case SO_DEBUG:
973 case SO_KEEPALIVE:
974 case SO_DONTROUTE:
975 case SO_OOBINLINE:
976 case SO_REUSEADDR:
977 if(optlen < (int)sizeof(int)) {
978 dprintf(("SOL_SOCKET, SO_REUSEADDR, optlen too small"));
979 WSASetLastError(WSAEFAULT);
980 return SOCKET_ERROR;
981 }
982 ret = setsockopt(s, level, optname, (char *)optval, optlen);
983 break;
984 default:
985 dprintf(("setsockopt: SOL_SOCKET, unknown option %x", optname));
986 WSASetLastError(WSAENOPROTOOPT);
987 return SOCKET_ERROR;
988 }
989 }
990 else
991 if(level == IPPROTO_TCP)
992 {
993 if(optname == TCP_NODELAY) {
994 if(optlen < (int)sizeof(int)) {
995 dprintf(("IPPROTO_TCP, TCP_NODELAY, optlen too small"));
996 WSASetLastError(WSAEFAULT);
997 return SOCKET_ERROR;
998 }
999 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1000 }
1001 else {
1002 dprintf(("setsockopt: IPPROTO_TCP, unknown option %x", optname));
1003 WSASetLastError(WSAENOPROTOOPT);
1004 return SOCKET_ERROR;
1005 }
1006 }
1007 else
1008 if (level == IPPROTO_IP)
1009 {
1010 switch (optname)
1011 {
1012 case IP_MULTICAST_IF:
1013 {
1014 if (optlen < sizeof(in_addr))
1015 {
1016 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1017 WSASetLastError(WSAEFAULT);
1018 return SOCKET_ERROR;
1019 }
1020 //TODO convert common interface names!
1021 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1022 break;
1023 }
1024
1025 case IP_ADD_MEMBERSHIP:
1026 case IP_DROP_MEMBERSHIP:
1027 if (optlen < sizeof(struct ip_mreq))
1028 {
1029 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP, optlen too small"));
1030 WSASetLastError(WSAEFAULT);
1031 return SOCKET_ERROR;
1032 }
1033 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1034 break;
1035
1036 case IP_MULTICAST_LOOP:
1037 case IP_MULTICAST_TTL:
1038 if (optlen < sizeof(u_char))
1039 {
1040 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1041 WSASetLastError(WSAEFAULT);
1042 return SOCKET_ERROR;
1043 }
1044 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1045 break;
1046
1047 default:
1048 dprintf(("setsockopt: IPPROTO_IP, unknown option %x", optname));
1049 WSASetLastError(WSAENOPROTOOPT);
1050 return SOCKET_ERROR;
1051 }
1052 }
1053 else {
1054 dprintf(("unknown level code!"));
1055 WSASetLastError(WSAEINVAL);
1056 return SOCKET_ERROR;
1057 }
1058
1059 if(ret == SOCKET_ERROR) {
1060 WSASetLastError(wsaErrno());
1061 }
1062 else WSASetLastError(NO_ERROR);
1063 return ret;
1064}
1065//******************************************************************************
1066//******************************************************************************
1067ODINFUNCTION5(int,OS2getsockopt,
1068 SOCKET, s,
1069 int, level,
1070 int, optname,
1071 char *, optval,
1072 int *,optlen)
1073{
1074 struct ws_linger *yy;
1075 struct linger xx;
1076 int ret;
1077 int size, options;
1078
1079 if(!fWSAInitialized) {
1080 WSASetLastError(WSANOTINITIALISED);
1081 return SOCKET_ERROR;
1082 }
1083 else
1084 if(WSAIsBlocking()) {
1085 WSASetLastError(WSAEINPROGRESS);
1086 return SOCKET_ERROR;
1087 }
1088 if (level == SOL_SOCKET) {
1089 switch(optname) {
1090 case SO_DONTLINGER:
1091 case SO_LINGER:
1092 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
1093 WSASetLastError(WSAEFAULT);
1094 return SOCKET_ERROR;
1095 }
1096 size = sizeof(xx);
1097 ret = getsockopt(s,level,optname,(char *)&xx, &size);
1098 yy = (struct ws_linger *)optval;
1099 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
1100 yy->l_linger = xx.l_linger;
1101 *optlen = size;
1102 break;
1103
1104 case SO_SNDBUF:
1105 case SO_RCVBUF:
1106 case SO_BROADCAST:
1107 case SO_DEBUG:
1108 case SO_KEEPALIVE:
1109 case SO_DONTROUTE:
1110 case SO_OOBINLINE:
1111 case SO_REUSEADDR:
1112 case SO_TYPE:
1113 if(optlen == NULL || *optlen < sizeof(int)) {
1114 WSASetLastError(WSAEFAULT);
1115 return SOCKET_ERROR;
1116 }
1117 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1118 break;
1119 case SO_ACCEPTCONN:
1120 if(optlen == NULL || *optlen < sizeof(int)) {
1121 WSASetLastError(WSAEFAULT);
1122 return SOCKET_ERROR;
1123 }
1124 size = sizeof(options);
1125 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
1126 if(ret != SOCKET_ERROR) {
1127 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
1128 *optlen = sizeof(BOOL);
1129 }
1130 break;
1131 default:
1132 dprintf(("getsockopt: unknown option %x", optname));
1133 WSASetLastError(WSAENOPROTOOPT);
1134 return SOCKET_ERROR;
1135 }
1136 }
1137 else
1138 if(level == IPPROTO_TCP) {
1139 if(optname == TCP_NODELAY) {
1140 if(optlen == NULL || *optlen < sizeof(int)) {
1141 WSASetLastError(WSAEFAULT);
1142 return SOCKET_ERROR;
1143 }
1144 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1145 }
1146 else {
1147 dprintf(("getsockopt: unknown option %x", optname));
1148 WSASetLastError(WSAENOPROTOOPT);
1149 return SOCKET_ERROR;
1150 }
1151 }
1152 else {
1153 WSASetLastError(WSAEINVAL);
1154 return SOCKET_ERROR;
1155 }
1156
1157 if(ret == SOCKET_ERROR) {
1158 WSASetLastError(wsaErrno());
1159 }
1160 else WSASetLastError(NO_ERROR);
1161 return ret;
1162}
1163//******************************************************************************
1164//******************************************************************************
1165/* Database function prototypes */
1166//******************************************************************************
1167//******************************************************************************
1168ODINFUNCTION2(int,OS2gethostname,
1169 char *,name,
1170 int,namelen)
1171{
1172 int ret;
1173
1174 ret = gethostname(name, namelen);
1175 if(ret == NULL) {
1176 WSASetLastError(NO_ERROR);
1177 return 0;
1178 }
1179 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1180 return SOCKET_ERROR;
1181}
1182//******************************************************************************
1183//******************************************************************************
1184ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1185 const char *,addr,
1186 int,len,
1187 int,type)
1188{
1189 LPWSINFO pwsi = WINSOCK_GetIData();
1190
1191 if( pwsi )
1192 {
1193 struct hostent* host;
1194 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1195 if( WS_dup_he(pwsi, host) ) {
1196 WSASetLastError(NO_ERROR);
1197 return pwsi->he;
1198 }
1199 else WSASetLastError(WSAENOBUFS);
1200 }
1201 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1202 }
1203 else WSASetLastError(WSANOTINITIALISED);
1204 return NULL;
1205}
1206//******************************************************************************
1207//******************************************************************************
1208ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1209 const char *,name)
1210{
1211 LPWSINFO pwsi = WINSOCK_GetIData();
1212
1213 if( pwsi )
1214 {
1215 struct hostent* host;
1216 if( (host = gethostbyname((char *)name)) != NULL ) {
1217 if( WS_dup_he(pwsi, host) ) {
1218 WSASetLastError(NO_ERROR);
1219 return pwsi->he;
1220 }
1221 else WSASetLastError(WSAENOBUFS);
1222 }
1223 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1224 }
1225 else WSASetLastError(WSANOTINITIALISED);
1226 return NULL;
1227}
1228//******************************************************************************
1229//******************************************************************************
1230ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1231 int, port,
1232 const char *, proto)
1233{
1234 LPWSINFO pwsi = WINSOCK_GetIData();
1235
1236 if( pwsi )
1237 {
1238 struct servent* serv;
1239 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1240 if( WS_dup_se(pwsi, serv) ) {
1241 WSASetLastError(NO_ERROR);
1242 return pwsi->se;
1243 }
1244 else WSASetLastError(WSAENOBUFS);
1245 }
1246 else WSASetLastError(WSANO_DATA);
1247 }
1248 else WSASetLastError(WSANOTINITIALISED);
1249 return NULL;
1250}
1251//******************************************************************************
1252//******************************************************************************
1253ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1254 const char *, name,
1255 const char *, proto)
1256{
1257 LPWSINFO pwsi = WINSOCK_GetIData();
1258
1259 if( pwsi )
1260 {
1261 struct servent *serv;
1262 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1263 if( WS_dup_se(pwsi, serv) ) {
1264 WSASetLastError(NO_ERROR);
1265 return pwsi->se;
1266 }
1267 else WSASetLastError(WSAENOBUFS);
1268 }
1269 else WSASetLastError(WSANO_DATA);
1270 }
1271 else WSASetLastError(WSANOTINITIALISED);
1272 return NULL;
1273}
1274//******************************************************************************
1275//******************************************************************************
1276ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1277 int,number)
1278{
1279 LPWSINFO pwsi = WINSOCK_GetIData();
1280
1281 if( pwsi )
1282 {
1283 struct protoent* proto;
1284 if( (proto = getprotobynumber(number)) != NULL ) {
1285 if( WS_dup_pe(pwsi, proto) ) {
1286 WSASetLastError(NO_ERROR);
1287 return pwsi->pe;
1288 }
1289 else WSASetLastError(WSAENOBUFS);
1290 }
1291 else WSASetLastError(WSANO_DATA);
1292 }
1293 else WSASetLastError(WSANOTINITIALISED);
1294 return NULL;
1295}
1296//******************************************************************************
1297//******************************************************************************
1298ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1299 const char *,name)
1300{
1301 LPWSINFO pwsi = WINSOCK_GetIData();
1302
1303 if( pwsi )
1304 {
1305 struct protoent * proto;
1306 if( (proto = getprotobyname((char *)name)) != NULL ) {
1307 if(WS_dup_pe(pwsi, proto)) {
1308 WSASetLastError(NO_ERROR);
1309 return pwsi->pe;
1310 }
1311 else WSASetLastError(WSAENOBUFS);
1312 }
1313 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1314 }
1315 else WSASetLastError(WSANOTINITIALISED);
1316 return NULL;
1317}
1318//******************************************************************************
1319//******************************************************************************
Note: See TracBrowser for help on using the repository browser.