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

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

add support for ws2_32 IPPROTO_IP options

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