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

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

implemented WSAEventSelect

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