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

Last change on this file since 3548 was 3548, checked in by sandervl, 25 years ago

async select clear fix

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