Release 970112
[wine/multimedia.git] / misc / winsock.c
blob5acadcd97bfaa6e5b0494ce531d68d1812597f8b
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4 *
5 * (C) 1993,1994,1996 John Brezak, Erik Bos, Alex Korobka.
6 */
8 #include <stdio.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <sys/types.h>
12 #include <sys/ipc.h>
13 #include <sys/ioctl.h>
14 #if defined(__svr4__)
15 #include <sys/filio.h>
16 #include <sys/ioccom.h>
17 #include <sys/sockio.h>
18 #endif
19 #include <sys/msg.h>
20 #include <sys/wait.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <netdb.h>
27 #include <unistd.h>
29 #include "windows.h"
30 #include "winnt.h"
31 #include "heap.h"
32 #include "ldt.h"
33 #include "winsock.h"
34 #include "stddebug.h"
35 #include "debug.h"
37 #define dump_sockaddr(a) \
38 fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
39 ((struct sockaddr_in *)a)->sin_family, \
40 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
41 ntohs(((struct sockaddr_in *)a)->sin_port))
43 extern void SIGNAL_MaskAsyncEvents( BOOL32 );
45 #pragma pack(4)
47 /* ----------------------------------- internal data */
49 extern int h_errno;
50 extern void __sigio(int);
52 ws_async_ctl async_ctl;
53 int async_qid = -1;
55 static HANDLE32 _WSHeap = 0;
56 static unsigned char* _ws_stub = NULL;
57 static LPWSINFO _wsi_list = NULL;
59 #define WS_ALLOC(size) \
60 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
61 #define WS_FREE(ptr) \
62 HeapFree(_WSHeap, 0, (ptr) )
64 #define WS_PTR2HANDLE(ptr) \
65 ((short)((int)(ptr) - (int)_ws_stub))
66 #define WS_HANDLE2PTR(handle) \
67 ((unsigned)((int)_ws_stub + (int)handle))
69 #define WSI_CHECK_RANGE(pwsi, pws) \
70 ( ((unsigned)(pws) > (unsigned)(pwsi)) && \
71 ((unsigned)(pws) < ((unsigned)(pwsi) + sizeof(WSINFO))) )
73 static INT16 _ws_sock_ops[] =
74 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
75 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
76 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER, 0 };
77 static int _px_sock_ops[] =
78 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
79 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
80 SO_LINGER };
82 static INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent);
83 static int notify_client(ws_socket* pws, unsigned flag);
85 static int _check_ws(LPWSINFO pwsi, ws_socket* pws);
86 static int _check_buffer(LPWSINFO pwsi, int size);
88 static void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base);
89 static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base);
90 static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base);
92 static int cancel_async_select(ws_socket*);
94 static void convert_sockopt(INT16 *level, INT16 *optname)
96 int i;
97 switch (*level)
99 case WS_SOL_SOCKET:
100 *level = SOL_SOCKET;
101 for(i=0; _ws_sock_ops[i]; i++)
102 if( _ws_sock_ops[i] == *optname ) break;
103 if( _ws_sock_ops[i] ) *optname = (INT16)_px_sock_ops[i];
104 else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
105 break;
106 case WS_IPPROTO_TCP:
107 *optname = IPPROTO_TCP;
111 static void _ws_global_init()
113 if( !_ws_stub )
115 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
116 if( !(_ws_stub = WS_ALLOC(0x10)) )
117 fprintf(stderr,"Fatal: failed to create WinSock heap\n");
119 if( async_qid == -1 )
120 if( (async_qid = msgget(IPC_PRIVATE, IPC_CREAT | 0x1FF)) == -1 )
121 fprintf(stderr,"Fatal: failed to create WinSock resource\n");
124 /* ----------------------------------- Per-thread info */
126 static void wsi_link(LPWSINFO pwsi)
127 { if( _wsi_list ) _wsi_list->prev = pwsi;
128 pwsi->next = _wsi_list; _wsi_list = pwsi;
131 static void wsi_unlink(LPWSINFO pwsi)
133 if( pwsi == _wsi_list ) _wsi_list = pwsi->next;
134 else
135 { pwsi->prev->next = pwsi->next;
136 if( pwsi->next ) pwsi->next->prev = pwsi->prev; }
139 static LPWSINFO wsi_find(HTASK16 hTask)
140 { LPWSINFO pwsi = _wsi_list;
141 while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
142 return pwsi;
145 static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
147 if( pwsi->last_free >= 0 )
149 int i = pwsi->last_free;
151 pwsi->last_free = pwsi->sock[i].flags;
152 pwsi->sock[i].fd = fd;
153 pwsi->sock[i].flags = 0;
154 return &pwsi->sock[i];
156 return NULL;
159 static void fd_set_normalize(fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd)
161 FD_ZERO(fds);
162 if(ws)
164 int i;
165 ws_socket* pws;
166 for(i=0;i<(ws->fd_count);i++)
168 pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
169 if( _check_ws(pwsi, pws) )
171 if( pws->fd > *highfd ) *highfd = pws->fd;
172 FD_SET(pws->fd, fds);
179 * Note weirdness here: sockets with errors belong in exceptfds, but
180 * are given to us in readfds or writefds, so move them to exceptfds if
181 * there is an error. Note that this means that exceptfds may have mysterious
182 * sockets set in it that the program never asked for.
185 static int inline sock_error_p(int s)
187 unsigned int optval, optlen;
189 optlen = sizeof(optval);
190 getsockopt(s, SOL_SOCKET, SO_ERROR, &optval, &optlen);
191 if (optval) dprintf_winsock(stddeb, "error: %d\n", optval);
192 return optval != 0;
195 static void fd_set_update(LPWSINFO pwsi, fd_set* fds, ws_fd_set* ws,
196 fd_set *errorfds)
198 if( ws )
200 int i, j, count = ws->fd_count;
202 for( i = 0, j = 0; i < count; i++ )
204 ws_socket *pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
205 int fd = pws->fd;
207 if( _check_ws(pwsi, pws) && FD_ISSET(fd, fds) )
209 /* if error, move to errorfds */
210 if (errorfds && (FD_ISSET(fd, errorfds) || sock_error_p(fd)))
211 FD_SET(fd, errorfds);
212 else
213 ws->fd_array[j++] = ws->fd_array[i];
216 ws->fd_count = j;
217 dprintf_winsock(stddeb, "\n");
219 return;
222 static void fd_set_update_except(LPWSINFO pwsi, fd_set *fds, ws_fd_set *ws,
223 fd_set *errorfds)
225 if (ws)
227 int i, j, count = ws->fd_count;
229 for (i=j=0; i < count; i++)
231 ws_socket *pws = (ws_socket *)WS_HANDLE2PTR(ws->fd_array[i]);
233 if (_check_ws(pwsi, pws) && (FD_ISSET(pws->fd, fds)
234 || FD_ISSET(pws->fd, errorfds)))
235 ws->fd_array[j++] = ws->fd_array[i];
237 ws->fd_count = j;
239 return;
242 /* ----------------------------------- API -----
244 * Init / cleanup / error checking.
247 INT16 WSAStartup(UINT16 wVersionRequested, LPWSADATA lpWSAData)
249 WSADATA WINSOCK_data = { 0x0101, 0x0101,
250 "WINE Sockets 1.1",
251 #ifdef linux
252 "Linux/i386",
253 #elif defined(__NetBSD__)
254 "NetBSD/i386",
255 #elif defined(sunos)
256 "SunOS",
257 #elif defined(__FreeBSD__)
258 "FreeBSD",
259 #else
260 "Unknown",
261 #endif
262 WS_MAX_SOCKETS_PER_THREAD,
263 WS_MAX_UDP_DATAGRAM, NULL };
264 HTASK16 tid = GetCurrentTask();
265 LPWSINFO pwsi;
267 dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
269 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
270 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
272 if (!lpWSAData) return WSAEINVAL;
274 _ws_global_init();
275 if( _WSHeap == 0 ) return WSASYSNOTREADY;
277 pwsi = wsi_find(GetCurrentTask());
278 if( pwsi == NULL )
280 if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
282 int i = 0;
283 pwsi->tid = tid;
284 for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ )
286 pwsi->sock[i].fd = -1;
287 pwsi->sock[i].flags = i + 1;
289 pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1;
291 else return WSASYSNOTREADY;
292 wsi_link(pwsi);
293 } else pwsi->num_startup++;
295 /* return winsock information */
296 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
298 dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
299 return(0);
302 void WINSOCK_Shutdown()
304 if( async_qid != -1 )
305 if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
306 fprintf(stderr,"failed to delete WS message queue.\n");
307 else async_qid = -1;
310 INT16 WSACleanup(void)
312 LPWSINFO pwsi = wsi_find(GetCurrentTask());
314 /* FIXME: do global cleanup if no current task */
316 dprintf_winsock(stddeb, "WSACleanup(%08x)\n", (unsigned)pwsi);
317 if( pwsi )
319 int i, j, n;
321 if( pwsi->num_startup-- ) return 0;
323 SIGNAL_MaskAsyncEvents( TRUE );
324 WINSOCK_cancel_async_op(GetCurrentTask());
325 SIGNAL_MaskAsyncEvents( FALSE );
327 wsi_unlink(pwsi);
328 if( _wsi_list == NULL ) WINSOCK_Shutdown();
330 if( pwsi->flags & WSI_BLOCKINGCALL )
331 dprintf_winsock(stddeb,"\tinside blocking call!\n");
332 if( pwsi->num_async_rq )
333 dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
335 for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
336 if( pwsi->sock[i].fd != -1 )
338 n += cancel_async_select(&pwsi->sock[i]);
339 close(pwsi->sock[i].fd); j++;
341 if( j )
342 dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
344 if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
345 if( pwsi->dbuffer ) SEGPTR_FREE(pwsi->dbuffer);
346 WS_FREE(pwsi);
347 return 0;
349 return SOCKET_ERROR;
352 INT16 WSAGetLastError(void)
354 LPWSINFO pwsi = wsi_find(GetCurrentTask());
355 INT16 ret;
357 dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
359 ret = (pwsi) ? pwsi->errno : WSANOTINITIALISED;
361 dprintf_winsock(stddeb, " = %i\n", (int)ret);
362 return ret;
365 void WSASetLastError(INT16 iError)
367 LPWSINFO pwsi = wsi_find(GetCurrentTask());
369 dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
371 if( pwsi ) pwsi->errno = iError;
374 int _check_ws(LPWSINFO pwsi, ws_socket* pws)
376 if( pwsi )
377 if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->errno = WSAEINPROGRESS;
378 else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
379 else pwsi->errno = WSAENOTSOCK;
380 return 0;
383 int _check_buffer(LPWSINFO pwsi, int size)
385 if( pwsi->buffer && pwsi->buflen >= size ) return 1;
386 else SEGPTR_FREE(pwsi->buffer);
387 pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
388 return (pwsi->buffer != NULL);
391 /* ----- socket operations */
393 SOCKET16 WINSOCK_accept(SOCKET16 s, struct sockaddr *addr, INT16 *addrlen16)
395 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
396 LPWSINFO pwsi = wsi_find(GetCurrentTask());
398 dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n",
399 (unsigned)pwsi, (UINT16)s);
400 if( _check_ws(pwsi, pws) )
402 int sock, fd_flags, addrlen32 = *addrlen16;
404 /* this is how block info is supposed to be used -
405 * WSAIsBlocking() would then check WSI_BLOCKINGCALL bit.
408 fd_flags = fcntl(pws->fd, F_GETFL, 0);
409 if( !(fd_flags & O_NONBLOCK) ) pwsi->flags |= WSI_BLOCKINGCALL;
411 if( (sock = accept(pws->fd, addr, &addrlen32)) >= 0 )
413 ws_socket* pnew = wsi_alloc_socket(pwsi, sock);
414 notify_client(pws, WS_FD_ACCEPT);
415 if( pnew )
417 if( pws->p_aop )
418 init_async_select(pnew, pws->p_aop->hWnd,
419 pws->p_aop->uMsg,
420 pws->p_aop->flags & ~WS_FD_ACCEPT );
422 pwsi->flags &= ~WSI_BLOCKINGCALL;
423 return (SOCKET16)WS_PTR2HANDLE(pnew);
425 else pwsi->errno = WSAENOBUFS;
427 else pwsi->errno = wsaErrno();
429 pwsi->flags &= ~WSI_BLOCKINGCALL;
431 return INVALID_SOCKET;
434 INT16 WINSOCK_bind(SOCKET16 s, struct sockaddr *name, INT16 namelen)
436 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
437 LPWSINFO pwsi = wsi_find(GetCurrentTask());
439 dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n",
440 (unsigned)pwsi, s, (int) name, namelen);
441 #if 0
442 dump_sockaddr(name);
443 #endif
445 if ( _check_ws(pwsi, pws) )
446 if (namelen >= sizeof(*name))
447 if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
448 if ( bind(pws->fd, name, namelen) < 0 )
450 int loc_errno = errno;
451 dprintf_winsock(stddeb,"\tfailure - errno = %i\n", errno);
452 errno = loc_errno;
453 switch(errno)
455 case EBADF: pwsi->errno = WSAENOTSOCK; break;
456 case EADDRNOTAVAIL: pwsi->errno = WSAEINVAL; break;
457 default: pwsi->errno = wsaErrno();
460 else return 0;
461 else pwsi->errno = WSAEAFNOSUPPORT;
462 else pwsi->errno = WSAEFAULT;
463 return SOCKET_ERROR;
466 INT16 WINSOCK_closesocket(SOCKET16 s)
468 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
469 LPWSINFO pwsi = wsi_find(GetCurrentTask());
471 dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s);
473 if( _check_ws(pwsi, pws) )
475 int fd = pws->fd;
477 cancel_async_select(pws);
478 pws->fd = -1;
479 pws->flags = (unsigned)pwsi->last_free;
480 pwsi->last_free = pws - &pwsi->sock[0];
481 if (close(fd) == 0) return 0;
482 pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
484 return SOCKET_ERROR;
487 INT16 WINSOCK_connect(SOCKET16 s, struct sockaddr *name, INT16 namelen)
489 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
490 LPWSINFO pwsi = wsi_find(GetCurrentTask());
492 dprintf_winsock(stddeb, "WS_CONNECT(%08x): socket %04x, ptr %8x, length %d\n",
493 (unsigned)pwsi, s, (int) name, namelen);
494 #if 0
495 dump_sockaddr(name);
496 #endif
498 if( _check_ws(pwsi, pws) )
500 if (connect(pws->fd, name, namelen) == 0)
502 if( pws->p_aop )
503 /* we need to notify handler process if
504 * connect() succeeded NOT in response to winsock message
506 notify_client(pws, WS_FD_CONNECTED);
508 pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT);
509 return 0;
511 pwsi->errno = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno();
513 return SOCKET_ERROR;
516 INT16 WINSOCK_getpeername(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
518 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
519 LPWSINFO pwsi = wsi_find(GetCurrentTask());
521 dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n",
522 (unsigned)pwsi, s, (int) name, *namelen);
523 if( _check_ws(pwsi, pws) )
525 int namelen32 = *namelen;
526 if (getpeername(pws->fd, name, &namelen32) == 0)
528 #if 0
529 dump_sockaddr(name);
530 #endif
531 *namelen = (INT16)namelen32;
532 return 0;
534 pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
536 return SOCKET_ERROR;
539 INT16 WINSOCK_getsockname(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
541 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
542 LPWSINFO pwsi = wsi_find(GetCurrentTask());
544 dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n",
545 (unsigned)pwsi, s, (int) name, (int) *namelen);
546 if( _check_ws(pwsi, pws) )
548 int namelen32 = *namelen;
549 if (getsockname(pws->fd, name, &namelen32) == 0)
551 *namelen = (INT16)namelen32;
552 return 0;
554 pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
556 return SOCKET_ERROR;
559 INT16 WINSOCK_getsockopt(SOCKET16 s, INT16 level,
560 INT16 optname, char *optval, INT16 *optlen)
562 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
563 LPWSINFO pwsi = wsi_find(GetCurrentTask());
565 dprintf_winsock(stddeb, "WS_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n",
566 (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
568 if( _check_ws(pwsi, pws) )
570 int optlen32 = *optlen;
572 convert_sockopt(&level, &optname);
573 if (getsockopt(pws->fd, (int) level, optname, optval, &optlen32) == 0 )
574 { *optlen = (INT16)optlen32; return 0; }
575 pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
577 return SOCKET_ERROR;
580 u_long WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
581 u_short WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
582 u_long WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
583 u_long WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
584 u_short WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
586 SEGPTR WINSOCK_inet_ntoa(struct in_addr in)
588 /* use "buffer for dummies" here because some applications have
589 * propensity to decode addresses in ws_hostent structure without
590 * saving them first...
593 LPWSINFO pwsi = wsi_find(GetCurrentTask());
595 if( pwsi )
597 char* s = inet_ntoa(in);
598 if( s )
600 if( pwsi->dbuffer == NULL )
601 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
603 pwsi->errno = WSAENOBUFS;
604 return (SEGPTR)NULL;
606 strncpy(pwsi->dbuffer, s, 32 );
607 return SEGPTR_GET(pwsi->dbuffer);
609 pwsi->errno = wsaErrno();
611 return (SEGPTR)NULL;
614 INT16 WINSOCK_ioctlsocket(SOCKET16 s, UINT32 cmd, UINT32 *argp)
616 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
617 LPWSINFO pwsi = wsi_find(GetCurrentTask());
619 dprintf_winsock(stddeb, "WS_IOCTL(%08x): socket %04x, cmd %08x, ptr %8x\n",
620 (unsigned)pwsi, s, cmd, (unsigned) argp);
621 if( _check_ws(pwsi, pws) )
623 long newcmd = cmd;
625 switch( cmd )
627 case WS_FIONREAD: newcmd=FIONREAD; break;
628 case WS_FIONBIO: newcmd=FIONBIO;
629 if( pws->p_aop && *argp == 0 )
631 pwsi->errno = WSAEINVAL;
632 return SOCKET_ERROR;
634 break;
635 case WS_SIOCATMARK: newcmd=SIOCATMARK; break;
636 case WS_IOW('f',125,u_long):
637 fprintf(stderr,"Warning: WS1.1 shouldn't be using async I/O\n");
638 pwsi->errno = WSAEINVAL; return SOCKET_ERROR;
639 default: fprintf(stderr,"Warning: Unknown WS_IOCTL cmd (%08x)\n", cmd);
641 if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0;
642 pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
644 return SOCKET_ERROR;
647 INT16 WINSOCK_listen(SOCKET16 s, INT16 backlog)
649 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
650 LPWSINFO pwsi = wsi_find(GetCurrentTask());
652 dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n",
653 (unsigned)pwsi, s, backlog);
654 if( _check_ws(pwsi, pws) )
656 if( !pws->p_aop )
658 int fd_flags = fcntl(pws->fd, F_GETFL, 0);
659 if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
661 else notify_client(pws, WS_FD_ACCEPT);
663 if (listen(pws->fd, backlog) == 0) return 0;
664 pwsi->errno = wsaErrno();
666 return SOCKET_ERROR;
669 INT16 WINSOCK_recv(SOCKET16 s, char *buf, INT16 len, INT16 flags)
671 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
672 LPWSINFO pwsi = wsi_find(GetCurrentTask());
674 dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d",
675 (unsigned)pwsi, s, (unsigned)buf, len, flags);
676 if( _check_ws(pwsi, pws) )
678 int length;
679 if ((length = recv(pws->fd, buf, len, flags)) >= 0)
681 dprintf_winsock(stddeb, " -> %i bytes\n", length);
682 notify_client(pws, WS_FD_READ);
683 return (INT16)length;
685 pwsi->errno = wsaErrno();
687 dprintf_winsock(stddeb, " -> ERROR\n");
688 return SOCKET_ERROR;
691 INT16 WINSOCK_recvfrom(SOCKET16 s, char *buf, INT16 len, INT16 flags,
692 struct sockaddr *from, INT16 *fromlen16)
694 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
695 LPWSINFO pwsi = wsi_find(GetCurrentTask());
697 dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d\n",
698 (unsigned)pwsi, s, (unsigned)buf, len, flags);
699 if( _check_ws(pwsi, pws) )
701 int length, fromlen32 = *fromlen16;
703 if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0 );
705 *fromlen16 = fromlen32;
706 notify_client(pws, WS_FD_READ);
707 return (INT16)length;
709 pwsi->errno = wsaErrno();
711 return SOCKET_ERROR;
714 INT16 WINSOCK_select(INT16 nfds, ws_fd_set *ws_readfds,
715 ws_fd_set *ws_writefds,
716 ws_fd_set *ws_exceptfds, struct timeval *timeout)
718 LPWSINFO pwsi = wsi_find(GetCurrentTask());
720 dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n",
721 (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
723 if( pwsi )
725 int highfd = 0;
726 fd_set readfds, writefds, exceptfds, errorfds;
728 fd_set_normalize(&readfds, pwsi, ws_readfds, &highfd);
729 fd_set_normalize(&writefds, pwsi, ws_writefds, &highfd);
730 fd_set_normalize(&exceptfds, pwsi, ws_exceptfds, &highfd);
731 FD_ZERO(&errorfds);
733 if( (highfd = select(highfd + 1, &readfds, &writefds, &exceptfds, timeout)) >= 0 )
735 if( highfd )
737 fd_set_update(pwsi, &readfds, ws_readfds, &errorfds);
738 fd_set_update(pwsi, &writefds, ws_writefds, &errorfds);
739 fd_set_update_except(pwsi, &exceptfds, ws_exceptfds, &errorfds);
741 return highfd;
743 pwsi->errno = wsaErrno();
745 return SOCKET_ERROR;
748 INT16 WINSOCK_send(SOCKET16 s, char *buf, INT16 len, INT16 flags)
750 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
751 LPWSINFO pwsi = wsi_find(GetCurrentTask());
753 dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
754 (unsigned)pwsi, s, (unsigned) buf, len, flags);
755 if( _check_ws(pwsi, pws) )
757 int length;
758 if ((length = send(pws->fd, buf, len, flags)) < 0 )
760 length = SOCKET_ERROR;
761 pwsi->errno = wsaErrno();
763 notify_client(pws, WS_FD_WRITE);
764 return (INT16)length;
766 return SOCKET_ERROR;
769 INT16 WINSOCK_sendto(SOCKET16 s, char *buf, INT16 len, INT16 flags,
770 struct sockaddr *to, INT16 tolen)
772 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
773 LPWSINFO pwsi = wsi_find(GetCurrentTask());
775 dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
776 (unsigned)pwsi, s, (unsigned) buf, len, flags);
777 if( _check_ws(pwsi, pws) )
779 int length;
781 if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
783 length = SOCKET_ERROR;
784 pwsi->errno = wsaErrno();
786 notify_client(pws, WS_FD_WRITE);
787 return (INT16)length;
789 return SOCKET_ERROR;
792 INT16 WINSOCK_setsockopt(SOCKET16 s, INT16 level, INT16 optname,
793 char *optval, INT16 optlen)
795 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
796 LPWSINFO pwsi = wsi_find(GetCurrentTask());
798 dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, level %d, opt %d, ptr %08x, len %d\n",
799 (unsigned)pwsi, s, level, optname, (int) optval, optlen);
800 if( _check_ws(pwsi, pws) )
802 int linger32[2];
803 convert_sockopt(&level, &optname);
804 if( optname == SO_LINGER )
806 INT16* ptr = (INT16*)optval;
807 linger32[0] = ptr[0];
808 linger32[1] = ptr[1];
809 optval = (char*)&linger32;
810 optlen = sizeof(linger32);
812 if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
813 pwsi->errno = wsaErrno();
815 return SOCKET_ERROR;
818 INT16 WINSOCK_shutdown(SOCKET16 s, INT16 how)
820 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
821 LPWSINFO pwsi = wsi_find(GetCurrentTask());
823 dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n",
824 (unsigned)pwsi, s, how );
825 if( _check_ws(pwsi, pws) )
827 pws->flags |= WS_FD_INACTIVE;
828 cancel_async_select(pws);
830 if (shutdown(pws->fd, how) == 0) return 0;
831 pwsi->errno = wsaErrno();
833 return SOCKET_ERROR;
836 SOCKET16 WINSOCK_socket(INT16 af, INT16 type, INT16 protocol)
838 LPWSINFO pwsi = wsi_find(GetCurrentTask());
840 dprintf_winsock(stddeb, "WS_SOCKET(%08x): af=%d type=%d protocol=%d\n",
841 (unsigned)pwsi, af, type, protocol);
843 if( pwsi )
845 int sock;
847 /* check the socket family */
848 switch(af)
850 case AF_INET:
851 case AF_UNSPEC: break;
852 default: pwsi->errno = WSAEAFNOSUPPORT; return INVALID_SOCKET;
855 /* check the socket type */
856 switch(type)
858 case SOCK_STREAM:
859 case SOCK_DGRAM:
860 case SOCK_RAW: break;
861 default: pwsi->errno = WSAESOCKTNOSUPPORT; return INVALID_SOCKET;
864 /* check the protocol type */
865 if ( protocol < 0 ) /* don't support negative values */
866 { pwsi->errno = WSAEPROTONOSUPPORT; return INVALID_SOCKET; }
868 if ( af == AF_UNSPEC) /* did they not specify the address family? */
869 switch(protocol)
871 case IPPROTO_TCP:
872 if (type == SOCK_STREAM) { af = AF_INET; break; }
873 case IPPROTO_UDP:
874 if (type == SOCK_DGRAM) { af = AF_INET; break; }
875 default: pwsi->errno = WSAEPROTOTYPE; return INVALID_SOCKET;
878 if ((sock = socket(af, type, protocol)) >= 0)
880 ws_socket* pnew = wsi_alloc_socket(pwsi, sock);
882 dprintf_winsock(stddeb,"\tcreated %04x (handle %i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
884 if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
886 close(sock);
887 pwsi->errno = WSAENOBUFS;
888 return INVALID_SOCKET;
892 if (errno == EPERM) /* raw socket denied */
894 fprintf(stderr, "WS_SOCKET: not enough privileges\n");
895 pwsi->errno = WSAESOCKTNOSUPPORT;
896 } else pwsi->errno = wsaErrno();
899 dprintf_winsock(stddeb, "\t\tfailed!\n");
900 return INVALID_SOCKET;
904 /* ----- database functions
906 * Note that ws_...ent structures we return have SEGPTR pointers inside them.
909 static char* NULL_STRING = "NULL";
912 struct WIN_hostent *
914 SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT16 len, INT16 type)
916 LPWSINFO pwsi = wsi_find(GetCurrentTask());
918 dprintf_winsock(stddeb, "WS_GetHostByAddr(%08x): ptr %8x, len %d, type %d\n",
919 (unsigned)pwsi, (unsigned) addr, len, type);
920 if( pwsi )
922 struct hostent* host;
923 if( (host = gethostbyaddr(addr, len, type)) != NULL )
924 if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
925 return SEGPTR_GET(pwsi->buffer);
926 else pwsi->errno = WSAENOBUFS;
927 else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
929 return NULL;
933 struct WIN_hostent *
935 SEGPTR WINSOCK_gethostbyname(const char *name)
937 LPWSINFO pwsi = wsi_find(GetCurrentTask());
939 dprintf_winsock(stddeb, "WS_GetHostByName(%08x): %s\n",
940 (unsigned)pwsi, (name)?name:"NULL");
941 if( pwsi )
943 struct hostent* host;
944 if( (host = gethostbyname(name)) != NULL )
945 if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
946 return SEGPTR_GET(pwsi->buffer);
947 else pwsi->errno = WSAENOBUFS;
948 else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
950 return NULL;
953 INT16 WINSOCK_gethostname(char *name, INT16 namelen)
955 LPWSINFO pwsi = wsi_find(GetCurrentTask());
957 dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n",
958 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
959 if( pwsi )
961 if (gethostname(name, namelen) == 0) return 0;
962 pwsi->errno = (errno == EINVAL) ? WSAEFAULT : wsaErrno();
964 return SOCKET_ERROR;
968 struct WIN_protoent *
970 SEGPTR WINSOCK_getprotobyname(char *name)
972 LPWSINFO pwsi = wsi_find(GetCurrentTask());
974 dprintf_winsock(stddeb, "WS_GetProtoByName(%08x): %s\n",
975 (unsigned)pwsi, (name)?name:NULL_STRING);
976 if( pwsi )
978 struct protoent* proto;
979 if( (proto = getprotobyname(name)) != NULL )
980 if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
981 return SEGPTR_GET(pwsi->buffer);
982 else pwsi->errno = WSAENOBUFS;
983 else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
985 return NULL;
989 struct WIN_protoent *
991 SEGPTR WINSOCK_getprotobynumber(INT16 number)
993 LPWSINFO pwsi = wsi_find(GetCurrentTask());
995 dprintf_winsock(stddeb, "WS_GetProtoByNumber(%08x): %i\n", (unsigned)pwsi, number);
997 if( pwsi )
999 struct protoent* proto;
1000 if( (proto = getprotobynumber(number)) != NULL )
1001 if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
1002 return SEGPTR_GET(pwsi->buffer);
1003 else pwsi->errno = WSAENOBUFS;
1004 else pwsi->errno = WSANO_DATA;
1006 return NULL;
1010 struct WIN_servent *
1012 SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
1014 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1016 dprintf_winsock(stddeb, "WS_GetServByName(%08x): '%s', '%s'\n",
1017 (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1019 if( pwsi )
1021 struct servent* serv;
1022 if( (serv = getservbyname(name, proto)) != NULL )
1023 if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
1024 return SEGPTR_GET(pwsi->buffer);
1025 else pwsi->errno = WSAENOBUFS;
1026 else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1028 return NULL;
1032 struct WIN_servent *
1034 SEGPTR WINSOCK_getservbyport(INT16 port, const char *proto)
1036 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1038 dprintf_winsock(stddeb, "WS_GetServByPort(%08x): %i, '%s'\n",
1039 (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
1040 if( pwsi )
1042 struct servent* serv;
1043 if( (serv = getservbyport(port, proto)) != NULL )
1044 if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
1045 return SEGPTR_GET(pwsi->buffer);
1046 else pwsi->errno = WSAENOBUFS;
1047 else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1049 return NULL;
1053 /* ----------------------------------- Windows sockets extensions -- *
1055 * ----------------------------------------------------------------- */
1057 static int aop_control(ws_async_op* p_aop, int flag )
1059 unsigned lLength;
1061 read(p_aop->fd[0], &lLength, sizeof(unsigned));
1062 if( LOWORD(lLength) )
1063 if( (int)LOWORD(lLength) <= p_aop->buflen )
1065 char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base);
1066 read(p_aop->fd[0], buffer, LOWORD(lLength));
1067 switch( p_aop->flags )
1069 case WSMSG_ASYNC_HOSTBYNAME:
1070 case WSMSG_ASYNC_HOSTBYADDR:
1071 fixup_wshe((struct ws_hostent*)buffer, p_aop->buffer_base); break;
1072 case WSMSG_ASYNC_PROTOBYNAME:
1073 case WSMSG_ASYNC_PROTOBYNUM:
1074 fixup_wspe((struct ws_protoent*)buffer, p_aop->buffer_base); break;
1075 case WSMSG_ASYNC_SERVBYNAME:
1076 case WSMSG_ASYNC_SERVBYPORT:
1077 fixup_wsse((struct ws_servent*)buffer, p_aop->buffer_base); break;
1078 default:
1079 if( p_aop->flags ) fprintf(stderr,"Received unknown async request!\n");
1080 return AOP_CONTROL_REMOVE;
1083 else lLength = ((UINT32)LOWORD(lLength)) | ((unsigned)WSAENOBUFS << 16);
1085 #if 0
1086 printf("async op completed: hWnd [%04x], uMsg [%04x], aop [%04x], event [%08x]\n",
1087 p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
1088 #endif
1090 PostMessage(p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
1091 return AOP_CONTROL_REMOVE;
1095 static HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, LPCSTR init,
1096 INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen, UINT32 flag)
1098 /* queue 'flag' request and fork off its handler */
1100 async_ctl.ws_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op));
1102 if( async_ctl.ws_aop )
1104 HANDLE16 handle = (HANDLE16)WS_PTR2HANDLE(async_ctl.ws_aop);
1106 if( pipe(async_ctl.ws_aop->fd) == 0 )
1108 async_ctl.init = (char*)init;
1109 async_ctl.lLength = len;
1110 async_ctl.lEvent = type;
1112 async_ctl.ws_aop->hWnd = hWnd;
1113 async_ctl.ws_aop->uMsg = uMsg;
1115 async_ctl.ws_aop->buffer_base = sbuf; async_ctl.ws_aop->buflen = buflen;
1116 async_ctl.ws_aop->flags = flag;
1117 async_ctl.ws_aop->aop_control = &aop_control;
1118 WINSOCK_link_async_op( async_ctl.ws_aop );
1120 async_ctl.ws_aop->pid = fork();
1121 if( async_ctl.ws_aop->pid )
1123 close(async_ctl.ws_aop->fd[1]); /* write endpoint */
1125 /* Damn, BSD'ish SIGIO doesn't work on pipes/streams
1127 * async_io(async_ctl.ws_aop->fd[0], 1);
1130 dprintf_winsock(stddeb, "\tasync_op = %04x (child %i)\n",
1131 handle, async_ctl.ws_aop->pid);
1132 return handle;
1133 } else
1134 /* child process */
1136 close(async_ctl.ws_aop->fd[0]); /* read endpoint */
1137 switch(flag)
1139 case WSMSG_ASYNC_HOSTBYADDR:
1140 case WSMSG_ASYNC_HOSTBYNAME:
1141 WS_do_async_gethost(pwsi,flag);
1142 case WSMSG_ASYNC_PROTOBYNUM:
1143 case WSMSG_ASYNC_PROTOBYNAME:
1144 WS_do_async_getproto(pwsi,flag);
1145 case WSMSG_ASYNC_SERVBYPORT:
1146 case WSMSG_ASYNC_SERVBYNAME:
1147 WS_do_async_getserv(pwsi,flag);
1149 _exit(0); /* skip atexit()'ed cleanup */
1152 WS_FREE(async_ctl.ws_aop);
1153 pwsi->errno = wsaErrno();
1154 } else pwsi->errno = WSAEWOULDBLOCK;
1155 return 0;
1158 HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
1159 INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
1161 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1163 dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
1164 (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
1166 if( pwsi )
1167 return __WSAsyncDBQuery(pwsi, hWnd, uMsg, addr, len,
1168 type, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
1169 return 0;
1173 HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
1174 SEGPTR sbuf, INT16 buflen)
1176 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1178 dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
1179 (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
1181 if( pwsi )
1182 return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1183 0, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
1184 return 0;
1188 HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
1189 SEGPTR sbuf, INT16 buflen)
1191 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1193 dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n",
1194 (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
1196 if( pwsi )
1197 return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1198 0, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
1199 return 0;
1203 HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number,
1204 SEGPTR sbuf, INT16 buflen)
1206 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1208 dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n",
1209 (unsigned)pwsi, hWnd, uMsg, number );
1211 if( pwsi )
1212 return __WSAsyncDBQuery(pwsi, hWnd, uMsg, NULL, 0,
1213 number, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
1214 return 0;
1218 HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
1219 LPCSTR proto, SEGPTR sbuf, INT16 buflen)
1221 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1223 dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
1224 (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
1226 if( pwsi )
1228 async_ctl.buffer = (char*)proto;
1229 return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1230 0, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
1232 return 0;
1236 HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port,
1237 LPCSTR proto, SEGPTR sbuf, INT16 buflen)
1239 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1241 dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
1242 (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING );
1244 if( pwsi )
1245 return __WSAsyncDBQuery(pwsi, hWnd, uMsg, proto, 0,
1246 port, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
1247 return 0;
1250 INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
1252 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1253 ws_async_op* p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
1255 dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n",
1256 (unsigned)pwsi, hAsyncTaskHandle);
1257 if( pwsi )
1258 if( WINSOCK_check_async_op(p_aop) )
1260 kill(p_aop->pid, SIGKILL);
1261 waitpid(p_aop->pid, NULL, 0); /* just in case */
1262 close(p_aop->fd[0]);
1263 WINSOCK_unlink_async_op(p_aop);
1264 WS_FREE(p_aop);
1265 return 0;
1267 else pwsi->errno = WSAEINVAL;
1268 return SOCKET_ERROR;
1271 /* ----- asynchronous select() */
1273 int cancel_async_select(ws_socket* pws)
1275 if( pws->p_aop )
1277 kill(pws->p_aop->pid, SIGKILL);
1278 waitpid(pws->p_aop->pid, NULL, 0);
1279 WS_FREE(pws->p_aop);
1280 pws->p_aop = NULL;
1281 return 1;
1283 return 0;
1286 void _sigusr1_handler_parent(int sig)
1288 /* child process puts MTYPE_CLIENT data packet into the
1289 * 'async_qid' message queue and signals us with SIGUSR1.
1290 * This handler reads the queue and posts 'uMsg' notification
1291 * message.
1294 ipc_packet ipack;
1296 signal( SIGUSR1, _sigusr1_handler_parent);
1297 while( msgrcv(async_qid, (struct msgbuf*)&ipack,
1298 MTYPE_CLIENT_SIZE, MTYPE_CLIENT, IPC_NOWAIT) != -1 )
1300 if( ipack.wParam && abs((short)ipack.wParam) < 32768 )
1302 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(ipack.wParam);
1303 if( pws->p_aop && abs((char*)_ws_stub - (char*)pws->p_aop) < 32768 )
1305 pws->flags &= ~(ipack.lParam);
1306 #if 0
1307 printf("async event - hWnd %04x, uMsg %04x [%08x]\n",
1308 pws->p_aop->hWnd, pws->p_aop->uMsg, ipack.lParam );
1309 #endif
1310 PostMessage(pws->p_aop->hWnd, pws->p_aop->uMsg,
1311 (WPARAM16)ipack.wParam, (LPARAM)ipack.lParam );
1313 else fprintf(stderr,"AsyncSelect:stray async_op in socket %04x!\n", ipack.wParam);
1315 else fprintf(stderr,"AsyncSelect:stray socket at %04x!\n", ipack.wParam);
1319 int notify_client( ws_socket* pws, unsigned flag )
1321 if( pws->p_aop && ((pws->p_aop->flags & flag) ||
1322 (flag == WS_FD_CONNECTED && pws->flags & WS_FD_CONNECT)) )
1324 async_ctl.ip.mtype = MTYPE_PARENT;
1325 async_ctl.ip.lParam = flag;
1326 while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
1327 MTYPE_PARENT_SIZE, 0) == -1 )
1329 if( errno == EINTR ) continue;
1330 else
1332 perror("AsyncSelect(parent)");
1333 cancel_async_select(pws);
1334 pws->flags &= WS_FD_INTERNAL;
1335 return 0;
1338 kill(pws->p_aop->pid, SIGUSR1);
1339 return 1;
1341 return 0;
1344 INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
1346 ws_async_op* p_aop;
1348 if( cancel_async_select(pws) ) /* delete old async handler if any */
1349 pws->flags &= WS_FD_INTERNAL;
1351 if( lEvent == 0 ) return 0;
1353 /* setup async handler - some data may be redundant */
1355 WINSOCK_unblock_io(pws->fd, 1);
1356 if( (p_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op))) )
1358 p_aop->hWnd = hWnd;
1359 p_aop->uMsg = uMsg;
1360 pws->p_aop = p_aop;
1362 async_ctl.lEvent = p_aop->flags = lEvent;
1363 async_ctl.ws_sock = pws;
1364 async_ctl.ip.wParam = (UINT16)WS_PTR2HANDLE(pws);
1365 async_ctl.ip.lParam = 0;
1367 p_aop->pid = fork();
1368 if( p_aop->pid != -1 )
1369 if( p_aop->pid == 0 ) WINSOCK_do_async_select(); /* child process */
1370 else pws->flags |= lEvent;
1372 signal( SIGUSR1, _sigusr1_handler_parent );
1373 return 0; /* Wine process */
1375 return SOCKET_ERROR;
1378 INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
1380 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1381 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1383 dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
1384 (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent );
1385 if( _check_ws(pwsi, pws) )
1386 if( init_async_select(pws, hWnd, uMsg, lEvent) == 0 ) return 0;
1387 else pwsi->errno = WSAENOBUFS;
1388 return SOCKET_ERROR;
1391 /* ----- miscellaneous */
1393 INT16 __WSAFDIsSet(SOCKET16 fd, ws_fd_set *set)
1395 int i = set->fd_count;
1397 dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
1399 while (i--)
1400 if (set->fd_array[i] == fd) return 1;
1401 return 0;
1404 BOOL16 WSAIsBlocking(void)
1406 /* By default WinSock should set all its sockets to non-blocking mode
1407 * and poll in PeekMessage loop when processing "blocking" ones. This
1408 * function * is supposed to tell if program is in this loop. Our
1409 * blocking calls are truly blocking so we always return FALSE.
1411 * Note: It is allowed to call this function without prior WSAStartup().
1414 dprintf_winsock(stddeb, "WS_IsBlocking()\n");
1415 return FALSE;
1418 INT16 WSACancelBlockingCall(void)
1420 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1422 dprintf_winsock(stddeb, "WS_CancelBlockingCall(%08x)\n", (unsigned)pwsi);
1424 if( pwsi ) return 0;
1425 return SOCKET_ERROR;
1428 FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc)
1430 FARPROC16 prev;
1431 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1433 dprintf_winsock(stddeb, "WS_SetBlockingHook(%08x): hook %08x\n",
1434 (unsigned)pwsi, (unsigned) lpBlockFunc);
1436 if( pwsi ) {
1437 prev = pwsi->blocking_hook;
1438 pwsi->blocking_hook = lpBlockFunc;
1439 return prev;
1441 return 0;
1444 INT16 WSAUnhookBlockingHook(void)
1446 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1448 dprintf_winsock(stddeb, "WS_UnhookBlockingHook(%08x)\n", (unsigned)pwsi);
1449 if( pwsi ) return (INT16)(INT32)(pwsi->blocking_hook = (FARPROC16)NULL);
1450 return SOCKET_ERROR;
1453 VOID
1454 WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6)
1456 fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
1457 x1,x2,x3,x4,x5,x6
1459 fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
1460 x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
1462 return;
1464 /* ----------------------------------- end of API stuff */
1468 /* ----------------------------------- helper functions */
1470 static int list_size(char** l, int item_size)
1472 int i,j = 0;
1473 if(l)
1474 { for(i=0;l[i];i++)
1475 j += (item_size) ? item_size : strlen(l[i]) + 1;
1476 j += (i + 1) * sizeof(char*); }
1477 return j;
1480 static int list_dup(char** l_src, char* ref, char* base, int item_size)
1482 /* base is either either equal to ref or 0 or SEGPTR */
1484 char* p = ref;
1485 char** l_to = (char**)ref;
1486 int i,j,k;
1488 for(j=0;l_src[j];j++) ;
1489 p += (j + 1) * sizeof(char*);
1490 for(i=0;i<j;i++)
1491 { l_to[i] = base + (p - ref);
1492 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
1493 memcpy(p, l_src[i], k); p += k; }
1494 l_to[i] = NULL;
1495 return (p - ref);
1498 /* ----- hostent */
1500 static int hostent_size(struct hostent* p_he)
1502 int size = 0;
1503 if( p_he )
1504 { size = sizeof(struct hostent);
1505 size += strlen(p_he->h_name) + 1;
1506 size += list_size(p_he->h_aliases, 0);
1507 size += list_size(p_he->h_addr_list, p_he->h_length ); }
1508 return size;
1511 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
1513 /* Duplicate hostent structure and flatten data (with its pointers)
1514 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
1515 * relative to 0 depending on "flag" value. Return data size (also
1516 * in the pwsi->buflen).
1519 int size = hostent_size(p_he);
1520 if( size )
1522 char* p_name,*p_aliases,*p_addr,*p_base,*p;
1524 _check_buffer(pwsi, size);
1525 p = pwsi->buffer;
1526 p_base = (flag & WS_DUP_OFFSET) ? NULL
1527 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1528 p += (flag & WS_DUP_SEGPTR) ? sizeof(struct ws_hostent) : sizeof(struct hostent);
1529 p_name = p;
1530 strcpy(p, p_he->h_name); p += strlen(p) + 1;
1531 p_aliases = p;
1532 p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0);
1533 p_addr = p;
1534 list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length);
1535 if( !(flag & WS_DUP_SEGPTR) )
1536 { struct hostent* p_to = (struct hostent*)pwsi->buffer;
1537 p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
1538 p_to->h_name = p_base + (p_name - pwsi->buffer);
1539 p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer));
1540 p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); }
1541 else
1542 { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer;
1543 p_to->h_addrtype = (INT16)p_he->h_addrtype;
1544 p_to->h_length = (INT16)p_he->h_length;
1545 p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
1546 p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
1547 p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
1549 return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
1551 return size;
1554 void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base)
1556 /* add 'base' to ws_hostent pointers to convert them from offsets */
1558 int i;
1559 unsigned* p_aliases,*p_addr;
1561 p_aliases = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_aliases);
1562 p_addr = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_addr_list);
1563 ((unsigned)(p_wshe->h_name)) += (unsigned)base;
1564 ((unsigned)(p_wshe->h_aliases)) += (unsigned)base;
1565 ((unsigned)(p_wshe->h_addr_list)) += (unsigned)base;
1566 for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1567 for(i=0;p_addr[i];i++) p_addr[i] += (unsigned)base;
1570 /* ----- protoent */
1572 static int protoent_size(struct protoent* p_pe)
1574 int size = 0;
1575 if( p_pe )
1576 { size = sizeof(struct protoent);
1577 size += strlen(p_pe->p_name) + 1;
1578 size += list_size(p_pe->p_aliases, 0); }
1579 return size;
1582 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
1584 int size = protoent_size(p_pe);
1585 if( size )
1587 char* p_name,*p_aliases,*p_base,*p;
1589 _check_buffer(pwsi, size);
1590 p = pwsi->buffer;
1591 p_base = (flag & WS_DUP_OFFSET) ? NULL
1592 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1593 p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_protoent) : sizeof(struct protoent);
1594 p_name = p;
1595 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
1596 p_aliases = p;
1597 list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0);
1598 if( !(flag & WS_DUP_NATIVE) )
1599 { struct protoent* p_to = (struct protoent*)pwsi->buffer;
1600 p_to->p_proto = p_pe->p_proto;
1601 p_to->p_name = p_base + (p_name - pwsi->buffer);
1602 p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
1603 else
1604 { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer;
1605 p_to->p_proto = (INT16)p_pe->p_proto;
1606 p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
1607 p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer));
1608 return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); }
1610 return size;
1613 void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base)
1615 int i;
1616 unsigned* p_aliases = (unsigned*)((char*)p_wspe + (unsigned)p_wspe->p_aliases);
1617 ((unsigned)(p_wspe->p_name)) += (unsigned)base;
1618 ((unsigned)(p_wspe->p_aliases)) += (unsigned)base;
1619 for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1622 /* ----- servent */
1624 static int servent_size(struct servent* p_se)
1626 int size = 0;
1627 if( p_se )
1628 { size += sizeof(struct servent);
1629 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
1630 size += list_size(p_se->s_aliases, 0); }
1631 return size;
1634 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
1636 int size = servent_size(p_se);
1637 if( size )
1639 char* p_name,*p_aliases,*p_proto,*p_base,*p;
1641 _check_buffer(pwsi, size);
1642 p = pwsi->buffer;
1643 p_base = (flag & WS_DUP_OFFSET) ? NULL
1644 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1645 p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_servent) : sizeof(struct servent);
1646 p_name = p;
1647 strcpy(p, p_se->s_name); p += strlen(p) + 1;
1648 p_proto = p;
1649 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
1650 p_aliases = p;
1651 list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
1653 if( !(flag & WS_DUP_SEGPTR) )
1654 { struct servent* p_to = (struct servent*)pwsi->buffer;
1655 p_to->s_port = p_se->s_port;
1656 p_to->s_name = p_base + (p_name - pwsi->buffer);
1657 p_to->s_proto = p_base + (p_proto - pwsi->buffer);
1658 p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
1659 else
1660 { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer;
1661 p_to->s_port = (INT16)p_se->s_port;
1662 p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
1663 p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
1664 p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
1665 return (size + sizeof(struct ws_servent) - sizeof(struct servent)); }
1667 return size;
1670 void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base)
1672 int i;
1673 unsigned* p_aliases = (unsigned*)((char*)p_wsse + (unsigned)p_wsse->s_aliases);
1674 ((unsigned)(p_wsse->s_name)) += (unsigned)base;
1675 ((p_wsse->s_proto)) += (unsigned)base;
1676 ((p_wsse->s_aliases)) += (unsigned)base;
1677 for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1680 /* ----------------------------------- error handling */
1682 UINT16 wsaErrno(void)
1684 int loc_errno = errno;
1685 #if defined(__FreeBSD__)
1686 dprintf_winsock(stderr, "winsock: errno %d, (%s).\n",
1687 errno, sys_errlist[errno]);
1688 #else
1689 dprintf_winsock(stderr, "winsock: errno %d\n", errno);
1690 #endif
1692 switch(loc_errno)
1694 case EINTR: return WSAEINTR;
1695 case EBADF: return WSAEBADF;
1696 case EACCES: return WSAEACCES;
1697 case EFAULT: return WSAEFAULT;
1698 case EINVAL: return WSAEINVAL;
1699 case EMFILE: return WSAEMFILE;
1700 case EWOULDBLOCK: return WSAEWOULDBLOCK;
1701 case EINPROGRESS: return WSAEINPROGRESS;
1702 case EALREADY: return WSAEALREADY;
1703 case ENOTSOCK: return WSAENOTSOCK;
1704 case EDESTADDRREQ: return WSAEDESTADDRREQ;
1705 case EMSGSIZE: return WSAEMSGSIZE;
1706 case EPROTOTYPE: return WSAEPROTOTYPE;
1707 case ENOPROTOOPT: return WSAENOPROTOOPT;
1708 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
1709 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
1710 case EOPNOTSUPP: return WSAEOPNOTSUPP;
1711 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
1712 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
1713 case EADDRINUSE: return WSAEADDRINUSE;
1714 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
1715 case ENETDOWN: return WSAENETDOWN;
1716 case ENETUNREACH: return WSAENETUNREACH;
1717 case ENETRESET: return WSAENETRESET;
1718 case ECONNABORTED: return WSAECONNABORTED;
1719 case ECONNRESET: return WSAECONNRESET;
1720 case ENOBUFS: return WSAENOBUFS;
1721 case EISCONN: return WSAEISCONN;
1722 case ENOTCONN: return WSAENOTCONN;
1723 case ESHUTDOWN: return WSAESHUTDOWN;
1724 case ETOOMANYREFS: return WSAETOOMANYREFS;
1725 case ETIMEDOUT: return WSAETIMEDOUT;
1726 case ECONNREFUSED: return WSAECONNREFUSED;
1727 case ELOOP: return WSAELOOP;
1728 case ENAMETOOLONG: return WSAENAMETOOLONG;
1729 case EHOSTDOWN: return WSAEHOSTDOWN;
1730 case EHOSTUNREACH: return WSAEHOSTUNREACH;
1731 case ENOTEMPTY: return WSAENOTEMPTY;
1732 #ifdef EPROCLIM
1733 case EPROCLIM: return WSAEPROCLIM;
1734 #endif
1735 #ifdef EUSERS
1736 case EUSERS: return WSAEUSERS;
1737 #endif
1738 #ifdef EDQUOT
1739 case EDQUOT: return WSAEDQUOT;
1740 #endif
1741 case ESTALE: return WSAESTALE;
1742 case EREMOTE: return WSAEREMOTE;
1744 /* just in case we ever get here and there are no problems */
1745 case 0: return 0;
1746 default:
1747 fprintf(stderr, "winsock: unknown errno %d!\n", errno);
1748 return WSAEOPNOTSUPP;
1752 UINT16 wsaHerrno(void)
1754 int loc_errno = h_errno;
1756 #if defined(__FreeBSD__)
1757 dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n",
1758 h_errno, sys_errlist[h_errno]);
1759 #else
1760 dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno);
1761 #ifndef sun
1762 if( debugging_winsock ) herror("wine: winsock: wsaherrno");
1763 #endif
1764 #endif
1766 switch(loc_errno)
1768 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
1769 case TRY_AGAIN: return WSATRY_AGAIN;
1770 case NO_RECOVERY: return WSANO_RECOVERY;
1771 case NO_DATA: return WSANO_DATA;
1773 case 0: return 0;
1774 default:
1775 fprintf(stderr, "winsock: unknown h_errno %d!\n", h_errno);
1776 return WSAEOPNOTSUPP;