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

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

YD: fixes for opera

File size: 33.7 KB
Line 
1/* $Id: wsock32.cpp,v 1.35 2001-04-28 16:15:18 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 // according to the docs, WSASetLastError() is just a call-through
154 // to SetLastError()
155 if(iError) {
156 dprintf(("WSASetLastError %x", iError));
157 }
158 SetLastError(iError);
159}
160//******************************************************************************
161//******************************************************************************
162int WIN32API WSAGetLastError()
163{
164 return GetLastError();
165}
166//******************************************************************************
167//******************************************************************************
168ODINFUNCTION2(int,OS2shutdown,
169 SOCKET,s,
170 int,how)
171{
172 int ret;
173
174 if(!fWSAInitialized) {
175 WSASetLastError(WSANOTINITIALISED);
176 return SOCKET_ERROR;
177 }
178 else
179 if(WSAIsBlocking()) {
180 WSASetLastError(WSAEINPROGRESS);
181 return SOCKET_ERROR;
182 }
183 ret = shutdown(s, how);
184
185 if(ret == SOCKET_ERROR) {
186 WSASetLastError(wsaErrno());
187 }
188 else WSASetLastError(NO_ERROR);
189 return ret;
190}
191//******************************************************************************
192//******************************************************************************
193ODINFUNCTION3(SOCKET,OS2socket,
194 int,af,
195 int,type,
196 int,protocol)
197{
198 SOCKET s;
199
200 if(!fWSAInitialized) {
201 WSASetLastError(WSANOTINITIALISED);
202 return SOCKET_ERROR;
203 }
204 else
205 if(WSAIsBlocking()) {
206 WSASetLastError(WSAEINPROGRESS);
207 return SOCKET_ERROR;
208 }
209 s = socket(af, type, protocol);
210
211 if(s == SOCKET_ERROR && sock_errno() == SOCEPFNOSUPPORT) {
212 //map SOCEPFNOSUPPORT to SOCEPFNOSUPPORT
213 WSASetLastError(SOCEPFNOSUPPORT);
214 }
215 else
216 if(s == SOCKET_ERROR) {
217 WSASetLastError(wsaErrno());
218 }
219 else WSASetLastError(NO_ERROR);
220 return s;
221}
222//******************************************************************************
223//******************************************************************************
224ODINFUNCTION1(int,OS2closesocket,SOCKET, s)
225{
226 int ret;
227
228 if(!fWSAInitialized) {
229 WSASetLastError(WSANOTINITIALISED);
230 return SOCKET_ERROR;
231 }
232 else
233 if(WSAIsBlocking()) {
234 WSASetLastError(WSAEINPROGRESS);
235 return SOCKET_ERROR;
236 }
237 //Close WSAAsyncSelect thread if one was created for this socket
238 FindAndSetAsyncEvent(s, 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 WSASetLastError(WSANOTINITIALISED);
866 return SOCKET_ERROR;
867 }
868 else
869 if(WSAIsBlocking()) {
870 WSASetLastError(WSAEINPROGRESS);
871 return SOCKET_ERROR;
872 }
873 //SvL: The 16 bits TCP/IP stack doesn't like high addresses, so copy
874 // the option value(s) on the stack.
875 safeoptval = (char *)alloca(optlen);
876 if(safeoptval == NULL) {
877 DebugInt3();
878 WSASetLastError(WSAEFAULT);
879 return SOCKET_ERROR;
880 }
881 memcpy(safeoptval, optval, optlen);
882 optval = safeoptval;
883
884 if (level == SOL_SOCKET) {
885 switch(optname) {
886 case SO_DONTLINGER:
887 case SO_LINGER:
888 if(optlen < (int)sizeof(ws_linger)) {
889 WSASetLastError(WSAEFAULT);
890 return SOCKET_ERROR;
891 }
892 yy = (struct ws_linger *)optval;
893 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
894 xx.l_linger = yy->l_linger;
895
896 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
897 break;
898 case SO_SNDBUF:
899 case SO_RCVBUF:
900 if(optlen < (int)sizeof(int)) {
901 WSASetLastError(WSAEFAULT);
902 return SOCKET_ERROR;
903 }
904
905 size = *(ULONG *)optval;
906tryagain:
907 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
908 if(ret == SOCKET_ERROR && wsaErrno() == WSAENOBUFS && size > 4096) {
909 int newsize = (size > 65535) ? 63*1024 : (size-1024);
910 dprintf(("setsockopt: change size from %d to %d", size, newsize));
911 //SvL: Limit send & receive buffer length to 64k
912 // (only happens with 16 bits tcpip stack?)
913 size = newsize;
914 goto tryagain;
915 }
916 break;
917
918 case SO_BROADCAST:
919 case SO_DEBUG:
920 case SO_KEEPALIVE:
921 case SO_DONTROUTE:
922 case SO_OOBINLINE:
923 case SO_REUSEADDR:
924 if(optlen < (int)sizeof(int)) {
925 WSASetLastError(WSAEFAULT);
926 return SOCKET_ERROR;
927 }
928 ret = setsockopt(s, level, optname, (char *)optval, optlen);
929 break;
930 default:
931 dprintf(("setsockopt: unknown option %x", optname));
932 WSASetLastError(WSAENOPROTOOPT);
933 return SOCKET_ERROR;
934 }
935 }
936 else
937 if(level == IPPROTO_TCP) {
938 if(optname == TCP_NODELAY) {
939 if(optlen < (int)sizeof(int)) {
940 WSASetLastError(WSAEFAULT);
941 return SOCKET_ERROR;
942 }
943 ret = setsockopt(s, level, optname, (char *)optval, optlen);
944 }
945 else {
946 dprintf(("setsockopt: unknown option %x", optname));
947 WSASetLastError(WSAENOPROTOOPT);
948 return SOCKET_ERROR;
949 }
950 }
951 else {
952 WSASetLastError(WSAEINVAL);
953 return SOCKET_ERROR;
954 }
955
956 if(ret == SOCKET_ERROR) {
957 WSASetLastError(wsaErrno());
958 }
959 else WSASetLastError(NO_ERROR);
960 return ret;
961}
962//******************************************************************************
963//******************************************************************************
964ODINFUNCTION5(int,OS2getsockopt,
965 SOCKET, s,
966 int, level,
967 int, optname,
968 char *, optval,
969 int *,optlen)
970{
971 struct ws_linger *yy;
972 struct linger xx;
973 int ret;
974 int size, options;
975
976 if(!fWSAInitialized) {
977 WSASetLastError(WSANOTINITIALISED);
978 return SOCKET_ERROR;
979 }
980 else
981 if(WSAIsBlocking()) {
982 WSASetLastError(WSAEINPROGRESS);
983 return SOCKET_ERROR;
984 }
985 if (level == SOL_SOCKET) {
986 switch(optname) {
987 case SO_DONTLINGER:
988 case SO_LINGER:
989 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
990 WSASetLastError(WSAEFAULT);
991 return SOCKET_ERROR;
992 }
993 size = sizeof(xx);
994 ret = getsockopt(s,level,optname,(char *)&xx, &size);
995 yy = (struct ws_linger *)optval;
996 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
997 yy->l_linger = xx.l_linger;
998 *optlen = size;
999 break;
1000
1001 case SO_SNDBUF:
1002 case SO_RCVBUF:
1003 case SO_BROADCAST:
1004 case SO_DEBUG:
1005 case SO_KEEPALIVE:
1006 case SO_DONTROUTE:
1007 case SO_OOBINLINE:
1008 case SO_REUSEADDR:
1009 case SO_TYPE:
1010 if(optlen == NULL || *optlen < sizeof(int)) {
1011 WSASetLastError(WSAEFAULT);
1012 return SOCKET_ERROR;
1013 }
1014 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1015 break;
1016 case SO_ACCEPTCONN:
1017 if(optlen == NULL || *optlen < sizeof(int)) {
1018 WSASetLastError(WSAEFAULT);
1019 return SOCKET_ERROR;
1020 }
1021 size = sizeof(options);
1022 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
1023 if(ret != SOCKET_ERROR) {
1024 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
1025 *optlen = sizeof(BOOL);
1026 }
1027 break;
1028 default:
1029 dprintf(("getsockopt: unknown option %x", optname));
1030 WSASetLastError(WSAENOPROTOOPT);
1031 return SOCKET_ERROR;
1032 }
1033 }
1034 else
1035 if(level == IPPROTO_TCP) {
1036 if(optname == TCP_NODELAY) {
1037 if(optlen == NULL || *optlen < sizeof(int)) {
1038 WSASetLastError(WSAEFAULT);
1039 return SOCKET_ERROR;
1040 }
1041 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1042 }
1043 else {
1044 dprintf(("getsockopt: unknown option %x", optname));
1045 WSASetLastError(WSAENOPROTOOPT);
1046 return SOCKET_ERROR;
1047 }
1048 }
1049 else {
1050 WSASetLastError(WSAEINVAL);
1051 return SOCKET_ERROR;
1052 }
1053
1054 if(ret == SOCKET_ERROR) {
1055 WSASetLastError(wsaErrno());
1056 }
1057 else WSASetLastError(NO_ERROR);
1058 return ret;
1059}
1060//******************************************************************************
1061//******************************************************************************
1062/* Database function prototypes */
1063//******************************************************************************
1064//******************************************************************************
1065ODINFUNCTION2(int,OS2gethostname,
1066 char *,name,
1067 int,namelen)
1068{
1069 int ret;
1070
1071 ret = gethostname(name, namelen);
1072 if(ret == NULL) {
1073 WSASetLastError(NO_ERROR);
1074 return 0;
1075 }
1076 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1077 return SOCKET_ERROR;
1078}
1079//******************************************************************************
1080//******************************************************************************
1081ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1082 const char *,addr,
1083 int,len,
1084 int,type)
1085{
1086 LPWSINFO pwsi = WINSOCK_GetIData();
1087
1088 if( pwsi )
1089 {
1090 struct hostent* host;
1091 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1092 if( WS_dup_he(pwsi, host) ) {
1093 WSASetLastError(NO_ERROR);
1094 return pwsi->he;
1095 }
1096 else WSASetLastError(WSAENOBUFS);
1097 }
1098 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1099 }
1100 else WSASetLastError(WSANOTINITIALISED);
1101 return NULL;
1102}
1103//******************************************************************************
1104//******************************************************************************
1105ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1106 const char *,name)
1107{
1108 LPWSINFO pwsi = WINSOCK_GetIData();
1109
1110 if( pwsi )
1111 {
1112 struct hostent* host;
1113 if( (host = gethostbyname((char *)name)) != NULL ) {
1114 if( WS_dup_he(pwsi, host) ) {
1115 WSASetLastError(NO_ERROR);
1116 return pwsi->he;
1117 }
1118 else WSASetLastError(WSAENOBUFS);
1119 }
1120 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1121 }
1122 else WSASetLastError(WSANOTINITIALISED);
1123 return NULL;
1124}
1125//******************************************************************************
1126//******************************************************************************
1127ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1128 int, port,
1129 const char *, proto)
1130{
1131 LPWSINFO pwsi = WINSOCK_GetIData();
1132
1133 if( pwsi )
1134 {
1135 struct servent* serv;
1136 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1137 if( WS_dup_se(pwsi, serv) ) {
1138 WSASetLastError(NO_ERROR);
1139 return pwsi->se;
1140 }
1141 else WSASetLastError(WSAENOBUFS);
1142 }
1143 else WSASetLastError(WSANO_DATA);
1144 }
1145 else WSASetLastError(WSANOTINITIALISED);
1146 return NULL;
1147}
1148//******************************************************************************
1149//******************************************************************************
1150ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1151 const char *, name,
1152 const char *, proto)
1153{
1154 LPWSINFO pwsi = WINSOCK_GetIData();
1155
1156 if( pwsi )
1157 {
1158 struct servent *serv;
1159 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1160 if( WS_dup_se(pwsi, serv) ) {
1161 WSASetLastError(NO_ERROR);
1162 return pwsi->se;
1163 }
1164 else WSASetLastError(WSAENOBUFS);
1165 }
1166 else WSASetLastError(WSANO_DATA);
1167 }
1168 else WSASetLastError(WSANOTINITIALISED);
1169 return NULL;
1170}
1171//******************************************************************************
1172//******************************************************************************
1173ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1174 int,number)
1175{
1176 LPWSINFO pwsi = WINSOCK_GetIData();
1177
1178 if( pwsi )
1179 {
1180 struct protoent* proto;
1181 if( (proto = getprotobynumber(number)) != NULL ) {
1182 if( WS_dup_pe(pwsi, proto) ) {
1183 WSASetLastError(NO_ERROR);
1184 return pwsi->pe;
1185 }
1186 else WSASetLastError(WSAENOBUFS);
1187 }
1188 else WSASetLastError(WSANO_DATA);
1189 }
1190 else WSASetLastError(WSANOTINITIALISED);
1191 return NULL;
1192}
1193//******************************************************************************
1194//******************************************************************************
1195ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1196 const char *,name)
1197{
1198 LPWSINFO pwsi = WINSOCK_GetIData();
1199
1200 if( pwsi )
1201 {
1202 struct protoent * proto;
1203 if( (proto = getprotobyname((char *)name)) != NULL ) {
1204 if(WS_dup_pe(pwsi, proto)) {
1205 WSASetLastError(NO_ERROR);
1206 return pwsi->pe;
1207 }
1208 else WSASetLastError(WSAENOBUFS);
1209 }
1210 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1211 }
1212 else WSASetLastError(WSANOTINITIALISED);
1213 return NULL;
1214}
1215//******************************************************************************
1216//******************************************************************************
Note: See TracBrowser for help on using the repository browser.