|
|
1.1.1.2 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * bsdsocket.library emulation - Win32 OS-dependent part
5: *
6: * Copyright 1997,98 Mathias Ortmann
7: * Copyright 1999,2000 Brian King
8: *
9: * GNU Public License
10: *
11: */
1.1 root 12: #include "sysconfig.h"
13: #include "sysdeps.h"
14:
1.1.1.2 root 15: #include <winsock.h>
1.1 root 16: #include <stddef.h>
1.1.1.2 root 17: #include <process.h>
1.1 root 18:
19: #include "options.h"
1.1.1.2 root 20: #include "memory.h"
1.1 root 21: #include "custom.h"
22: #include "newcpu.h"
23: #include "autoconf.h"
24: #include "bsdsocket.h"
25:
1.1.1.2 root 26: #include "osdep/exectasks.h"
27: #include "threaddep/thread.h"
28: #include "native2amiga.h"
29: #include "osdep/resource.h"
30: #include "osdep/win32gui.h"
31:
32: static HWND hSockWnd;
33: extern HWND hAmigaWnd;
34: int hWndSelector = 0; /* Set this to zero to get hSockWnd */
1.1 root 35: CRITICAL_SECTION csSigQueueLock;
36:
37: DWORD threadid;
1.1.1.2 root 38: #ifdef __GNUC__
1.1 root 39: #define THREAD(func,arg) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)func,(LPVOID)arg,0,&threadid)
1.1.1.2 root 40: #else
41: #define THREAD(func,arg) _beginthreadex( NULL, 0, func, (void *)arg, 0, (unsigned *)&threadid )
42: #endif
1.1 root 43:
44: #define SETERRNO seterrno(sb,WSAGetLastError()-WSABASEERR)
45: #define SETHERRNO setherrno(sb,WSAGetLastError()-WSABASEERR)
46: #define WAITSIGNAL waitsig(sb)
47:
48: #define SETSIGNAL addtosigqueue(sb,0)
49: #define CANCELSIGNAL cancelsig(sb)
50:
51: #define BEGINBLOCKING if (sb->ftable[sd-1] & SF_BLOCKING) sb->ftable[sd-1] |= SF_BLOCKINGINPROGRESS
52: #define ENDBLOCKING sb->ftable[sd-1] &= ~SF_BLOCKINGINPROGRESS
53:
54: static WSADATA wsbData;
55:
56: int PASCAL WSAEventSelect(SOCKET,HANDLE,long);
57:
58: #define MAX_SELECT_THREADS 64
59: static HANDLE hThreads[MAX_SELECT_THREADS];
60: uae_u32 *threadargs[MAX_SELECT_THREADS];
61: static HANDLE hEvents[MAX_SELECT_THREADS];
62:
1.1.1.2 root 63: static HANDLE hSockThread;
64: static HANDLE hSockReq, hSockReqHandled;
65: static unsigned int __stdcall sock_thread(void *);
66:
67: CRITICAL_SECTION SockThreadCS;
68: #define PREPARE_THREAD EnterCriticalSection( &SockThreadCS )
69: #define TRIGGER_THREAD { SetEvent( hSockReq ); WaitForSingleObject( hSockReqHandled, INFINITE ); LeaveCriticalSection( &SockThreadCS ); }
70:
71: #define SOCKVER_MAJOR 2
72: #define SOCKVER_MINOR 2
73: int mySockStartup( void )
74: {
75: int result = 0;
76: SOCKET dummy;
77: DWORD lasterror;
78:
79: if (WSAStartup(MAKEWORD( SOCKVER_MAJOR, SOCKVER_MINOR ), &wsbData))
80: {
81: lasterror = WSAGetLastError();
82:
83: if( lasterror == WSAVERNOTSUPPORTED )
84: {
85: char szMessage[ MAX_PATH ];
86: WIN32GUI_LoadUIString( IDS_WSOCK2NEEDED, szMessage, MAX_PATH );
1.1.1.3 ! root 87: gui_message( szMessage );
1.1.1.2 root 88: }
89: else
1.1.1.3 ! root 90: write_log( "BSDSOCK: ERROR - Unable to initialize Windows socket layer! Error code: %d\n", lasterror );
1.1.1.2 root 91: return 0;
92: }
93:
94: if (LOBYTE (wsbData.wVersion) != SOCKVER_MAJOR || HIBYTE (wsbData.wVersion) != SOCKVER_MINOR )
95: {
96: char szMessage[ MAX_PATH ];
97: WIN32GUI_LoadUIString( IDS_WSOCK2NEEDED, szMessage, MAX_PATH );
1.1.1.3 ! root 98: gui_message( szMessage );
1.1.1.2 root 99:
1.1.1.3 ! root 100: return 0;
1.1.1.2 root 101: }
102: else
103: {
1.1.1.3 ! root 104: write_log( "BSDSOCK: using %s\n", wsbData.szDescription );
1.1.1.2 root 105: // make sure WSP/NSPStartup gets called from within the regular stack
106: // (Windows 95/98 need this)
107: if( ( dummy = socket( AF_INET,SOCK_STREAM,IPPROTO_TCP ) ) != INVALID_SOCKET )
108: {
109: closesocket( dummy );
110: result = 1;
111: }
112: else
113: {
114: write_log( "BSDSOCK: ERROR - WSPStartup/NSPStartup failed! Error code: %d\n",WSAGetLastError() );
115: result = 0;
116: }
117: }
118:
119: return result;
120: }
121:
122: static int socket_layer_initialized = 0;
1.1 root 123:
124: int init_socket_layer(void)
125: {
1.1.1.2 root 126: int result = 0;
1.1 root 127:
1.1.1.2 root 128: #ifndef CAN_DO_STACK_MAGIC
129: currprefs.socket_emu = 0;
130: #endif
131: if( currprefs.socket_emu )
132: {
133: if( ( result = mySockStartup() ) )
1.1 root 134: {
1.1.1.2 root 135: InitializeCriticalSection(&csSigQueueLock);
136:
137: if( hSockThread == NULL )
138: {
139: InitializeCriticalSection( &SockThreadCS );
140: hSockReq = CreateEvent( NULL, FALSE, FALSE, NULL );
141: hSockReqHandled = CreateEvent( NULL, FALSE, FALSE, NULL );
142: hSockThread = (void *)THREAD(sock_thread,NULL);
143: }
1.1 root 144: }
1.1.1.2 root 145: }
1.1 root 146:
1.1.1.2 root 147: socket_layer_initialized = result;
1.1 root 148:
1.1.1.2 root 149: return result;
1.1 root 150: }
151:
152: void deinit_socket_layer(void)
153: {
1.1.1.2 root 154: int i;
155: if( currprefs.socket_emu )
156: {
1.1 root 157: WSACleanup();
1.1.1.2 root 158: if( socket_layer_initialized )
159: {
160: DeleteCriticalSection( &csSigQueueLock );
161: if( hSockThread )
162: {
163: DeleteCriticalSection( &SockThreadCS );
164: CloseHandle( hSockReq );
165: hSockReq = NULL;
166: CloseHandle( hSockReqHandled );
167: WaitForSingleObject( hSockThread, INFINITE );
168: CloseHandle( hSockThread );
169: }
170: for (i = 0; i < MAX_SELECT_THREADS; i++)
171: {
172: if (hThreads[i])
173: {
174: CloseHandle( hThreads[i] );
175: }
176: }
177: }
178: }
1.1 root 179: }
180:
1.1.1.2 root 181: #ifdef BSDSOCKET_SUPPORTED
182:
1.1 root 183: void locksigqueue(void)
184: {
1.1.1.2 root 185: EnterCriticalSection(&csSigQueueLock);
1.1 root 186: }
187:
188: void unlocksigqueue(void)
189: {
1.1.1.2 root 190: LeaveCriticalSection(&csSigQueueLock);
1.1 root 191: }
192:
193: // Asynchronous completion notification
194:
195: // We use window messages posted to hAmigaWnd in the range from 0xb000 to 0xb000+MAXPENDINGASYNC*2
196: // Socket events cause even-numbered messages, task events odd-numbered messages
197: // Message IDs are allocated on a round-robin basis and deallocated by the main thread.
198:
199: // WinSock tends to choke on WSAAsyncCancelMessage(s,w,m,0,0) called too often with an event pending
200:
201: // @@@ Enabling all socket event messages for every socket by default and basing things on that would
202: // be cleaner (and allow us to write a select() emulation that doesn't need to be kludge-aborted).
203: // However, the latency of the message queue is too high for that at the moment (setting up a dummy
204: // window from a separate thread would fix that).
205:
206: // Blocking sockets with asynchronous event notification are currently not safe to use.
207:
208: struct socketbase *asyncsb[MAXPENDINGASYNC];
209: SOCKET asyncsock[MAXPENDINGASYNC];
210: uae_u32 asyncsd[MAXPENDINGASYNC];
211: int asyncindex;
212:
213: int host_sbinit(SB)
214: {
215: sb->sockAbort = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
216:
217: if (sb->sockAbort == INVALID_SOCKET) return 0;
218: if ((sb->hEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL) return 0;
219:
220: sb->mtable = calloc(sb->dtablesize,sizeof(*sb->mtable));
221:
222: return 1;
223: }
224:
225: void host_closesocketquick(int s)
226: {
227: BOOL true = 1;
228:
1.1.1.2 root 229: if( s )
230: {
231: setsockopt((SOCKET)s,SOL_SOCKET,SO_DONTLINGER,(char *)&true,sizeof(true));
232: //shutdown(s,1);
233: closesocket((SOCKET)s);
234: }
1.1 root 235: }
236:
237: void host_sbcleanup(SB)
238: {
239: int i;
240:
241: for (i = 0; i < MAXPENDINGASYNC; i++) if (asyncsb[i] == sb) asyncsb[i] = NULL;
242:
243: if (sb->hEvent != NULL) CloseHandle(sb->hEvent);
244: if (sb->hAsyncTask) WSACancelAsyncRequest(sb->hAsyncTask);
245:
246: for (i = sb->dtablesize; i--; )
247: {
248: if (sb->dtable[i] != (int)INVALID_SOCKET) host_closesocketquick(sb->dtable[i]);
249:
250: if (sb->mtable[i]) asyncsb[(sb->mtable[i]-0xb000)/2] = NULL;
251: }
252:
1.1.1.3 ! root 253: //shutdown(sb->sockAbort,1);
1.1 root 254: closesocket(sb->sockAbort);
255:
256: free(sb->mtable);
257: }
258:
259: void host_sbreset(void)
260: {
261: memset(asyncsb,0,sizeof asyncsb);
262: memset(asyncsock,0,sizeof asyncsock);
263: memset(asyncsd,0,sizeof asyncsd);
264: memset(threadargs,0,sizeof threadargs);
265: }
266:
267: void sockmsg(unsigned int msg, unsigned long wParam, unsigned long lParam)
268: {
269: SB;
270: unsigned int index;
271: int sdi;
272:
273: index = (msg-0xb000)/2;
274: sb = asyncsb[index];
275:
276: if (!(msg & 1))
277: {
278: // is this one really for us?
279: if ((SOCKET)wParam != asyncsock[index])
280: {
281: // cancel socket event
1.1.1.2 root 282: WSAAsyncSelect((SOCKET)wParam,hWndSelector ? hAmigaWnd : hSockWnd,0,0);
1.1 root 283: return;
284: }
285:
286: sdi = asyncsd[index]-1;
287:
288: // asynchronous socket event?
289: if (sb && !(sb->ftable[sdi] & SF_BLOCKINGINPROGRESS) && sb->mtable[sdi])
290: {
291: long wsbevents = WSAGETSELECTEVENT(lParam);
292: int fmask = 0;
293:
294: // regular socket event?
295: if (wsbevents & FD_READ) fmask = REP_READ;
296: else if (wsbevents & FD_WRITE) fmask = REP_WRITE;
297: else if (wsbevents & FD_OOB) fmask = REP_OOB;
298: else if (wsbevents & FD_ACCEPT) fmask = REP_ACCEPT;
299: else if (wsbevents & FD_CONNECT) fmask = REP_CONNECT;
300: else if (wsbevents & FD_CLOSE) fmask = REP_CLOSE;
301:
302: // error?
303: if (WSAGETSELECTERROR(lParam)) fmask |= REP_ERROR;
304:
305: // notify
306: if (sb->ftable[sdi] & fmask) sb->ftable[sdi] |= fmask<<8;
307:
308: addtosigqueue(sb,1);
309: return;
310: }
311: }
312:
313: locksigqueue();
314:
315: if (sb != NULL)
316: {
317: if (msg & 1)
318: {
319: // is this one really for us?
320: if (sb->hAsyncTask != (void *)~0L && (void *)wParam != sb->hAsyncTask)
321: {
322: unlocksigqueue();
323: return;
324: }
325: }
326:
327: asyncsb[index] = NULL;
328:
329: if (WSAGETASYNCERROR(lParam))
330: {
331: seterrno(sb,WSAGETASYNCERROR(lParam)-WSABASEERR);
332: if (sb->sb_errno >= 1001 && sb->sb_errno <= 1005) setherrno(sb,sb->sb_errno-1000);
333: else if (sb->sb_errno == 55) // ENOBUFS
1.1.1.2 root 334: write_log("BSDSOCK: ERROR - Buffer overflow - %d bytes requested\n",WSAGETASYNCBUFLEN(lParam));
1.1 root 335: }
336: else seterrno(sb,0);
337:
338: if (msg & 1) sb->hAsyncTask = 0;
339:
340: SETSIGNAL;
341: }
342:
343: unlocksigqueue();
344: }
345:
346: static unsigned int allocasyncmsg(SB,uae_u32 sd,SOCKET s)
347: {
348: int i;
349:
350: locksigqueue();
351:
352: for (i = asyncindex+1; i != asyncindex; i++)
353: {
354: if (i == MAXPENDINGASYNC) i = 0;
355:
356: if (!asyncsb[i])
357: {
358: asyncsb[i] = sb;
359: if (++asyncindex == MAXPENDINGASYNC) asyncindex = 0;
360: unlocksigqueue();
361:
362: if (s == INVALID_SOCKET)
363: {
364: sb->hAsyncTask = (void *)~0L; // set wildcard value to prevent race condition
365: return i*2+0xb001;
366: }
367: else
368: {
369: asyncsd[i] = sd;
370: asyncsock[i] = s;
371: return i*2+0xb000;
372: }
373: }
374: }
375:
376: unlocksigqueue();
377:
378: seterrno(sb,12); // ENOMEM
1.1.1.2 root 379: write_log("BSDSOCK: ERROR - Async operation completion table overflow\n");
1.1 root 380:
381: return 0;
382: }
383:
384: static void cancelasyncmsg(unsigned int wMsg)
385: {
386: SB;
387:
388: wMsg = (wMsg-0xb000)/2;
389:
390: sb = asyncsb[wMsg];
391:
392: if (sb != NULL)
393: {
394: asyncsb[wMsg] = NULL;
395: CANCELSIGNAL;
396: }
397: }
398:
399: void sockabort(SB)
400: {
1.1.1.2 root 401: locksigqueue();
1.1 root 402:
1.1.1.2 root 403: if (sb->hAsyncTask)
404: {
405: if (WSACancelAsyncRequest(sb->hAsyncTask))
1.1.1.3 ! root 406: write_log("BSDSOCK: ERROR - WSACancelAsyncRequest() failed with error code %d\n",WSAGetLastError());
1.1.1.2 root 407: sb->hAsyncTask = 0;
408: }
1.1 root 409:
1.1.1.2 root 410: unlocksigqueue();
1.1 root 411: }
412:
413: // address cleaning
414: static void prephostaddr(SOCKADDR_IN *addr)
415: {
1.1.1.2 root 416: addr->sin_family = AF_INET;
1.1 root 417: }
418:
419: static void prepamigaaddr(struct sockaddr *realpt, int len)
420: {
1.1.1.2 root 421: // little endian address family value to the byte sin_family member
422: ((char *)realpt)[1] = *((char *)realpt);
423:
424: // set size of address
425: *((char *)realpt) = len;
1.1 root 426: }
427:
428: int host_socket(SB, int af, int type, int protocol)
429: {
1.1.1.2 root 430: int sd;
431: SOCKET s;
432: unsigned long nonblocking = 1;
433:
434: TRACE(("socket(%s,%s,%d) -> ",af == AF_INET ? "AF_INET" : "AF_other",type == SOCK_STREAM ? "SOCK_STREAM" : type == SOCK_DGRAM ? "SOCK_DGRAM " : "SOCK_RAW",protocol));
435:
436: if ((s = socket(af,type,protocol)) == INVALID_SOCKET)
437: {
438: SETERRNO;
439: TRACE(("failed (%d)\n",sb->sb_errno));
440: return -1;
441: }
442: else
1.1.1.3 ! root 443: sd = getsd(sb,(int)s);
1.1.1.2 root 444:
445: sb->ftable[sd-1] = SF_BLOCKING;
446: ioctlsocket(s,FIONBIO,&nonblocking);
447: TRACE(("%d\n",sd));
1.1 root 448:
1.1.1.2 root 449: return sd;
1.1 root 450: }
451:
452: uae_u32 host_bind(SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
453: {
1.1.1.2 root 454: char buf[MAXADDRLEN];
455: uae_u32 success = 0;
456: SOCKET s;
457:
458: TRACE(("bind(%d,0x%lx,%d) -> ",sd,name,namelen));
459: s = getsock(sb, sd);
460:
461: if (s != INVALID_SOCKET)
462: {
463: if (namelen <= sizeof buf)
464: {
465: memcpy(buf,get_real_address(name),namelen);
466:
467: // some Amiga programs set this field to bogus values
468: prephostaddr((SOCKADDR_IN *)buf);
1.1 root 469:
1.1.1.2 root 470: if ((success = bind(s,(struct sockaddr *)buf,namelen)) != 0)
471: {
472: SETERRNO;
473: TRACE(("failed (%d)\n",sb->sb_errno));
474: }
475: else
1.1.1.3 ! root 476: TRACE(("OK\n"));
1.1 root 477: }
1.1.1.2 root 478: else
1.1.1.3 ! root 479: write_log("BSDSOCK: ERROR - Excessive namelen (%d) in bind()!\n",namelen);
1.1.1.2 root 480: }
1.1 root 481:
1.1.1.2 root 482: return success;
1.1 root 483: }
484:
485: uae_u32 host_listen(SB, uae_u32 sd, uae_u32 backlog)
486: {
1.1.1.2 root 487: SOCKET s;
488: uae_u32 success = -1;
1.1 root 489:
1.1.1.2 root 490: TRACE(("listen(%d,%d) -> ",sd,backlog));
491: s = getsock(sb, sd);
1.1 root 492:
1.1.1.2 root 493: if (s != INVALID_SOCKET)
494: {
495: if ((success = listen(s,backlog)) != 0)
496: {
497: SETERRNO;
498: TRACE(("failed (%d)\n",sb->sb_errno));
499: }
500: else
1.1.1.3 ! root 501: TRACE(("OK\n"));
1.1.1.2 root 502: }
503:
504: return success;
1.1 root 505: }
506:
507: void host_accept(SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
508: {
1.1.1.2 root 509: struct sockaddr *rp_name;
510: int hlen;
511: SOCKET s, s2;
512: int success = 0;
513: unsigned int wMsg;
514:
515: rp_name = (struct sockaddr *)get_real_address(name);
516: hlen = get_long(namelen);
517: TRACE(("accept(%d,%d,%d) -> ",sd,name,hlen));
518:
519: s = (SOCKET)getsock(sb,(int)sd);
520:
521: if (s != INVALID_SOCKET)
522: {
523: BEGINBLOCKING;
524:
525: s2 = accept(s,rp_name,&hlen);
526:
527: if (s2 == INVALID_SOCKET)
528: {
529: SETERRNO;
530:
531: if (sb->ftable[sd-1] & SF_BLOCKING && sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR)
532: {
533: if ((wMsg = allocasyncmsg(sb,sd,s)) != 0)
534: {
535: WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_ACCEPT);
536:
537: WAITSIGNAL;
538:
539: cancelasyncmsg(wMsg);
540:
541: if (sb->eintr)
542: {
543: TRACE(("[interrupted]\n"));
544: ENDBLOCKING;
545: return;
546: }
1.1 root 547:
1.1.1.2 root 548: s2 = accept(s,rp_name,&hlen);
1.1 root 549:
1.1.1.2 root 550: if (s2 == INVALID_SOCKET)
551: {
1.1 root 552: SETERRNO;
553:
1.1.1.2 root 554: if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR) write_log("BSDSOCK: ERRRO - accept() would block despite FD_ACCEPT message\n");
555: }
1.1 root 556: }
1.1.1.2 root 557: }
558: }
1.1 root 559:
1.1.1.2 root 560: if (s2 == INVALID_SOCKET)
561: {
562: sb->resultval = -1;
563: TRACE(("failed (%d)\n",sb->sb_errno));
564: }
565: else
566: {
567: sb->resultval = getsd(sb, s2);
568: sb->ftable[sb->resultval-1] = sb->ftable[sd-1]; // new socket inherits the old socket's properties
1.1 root 569:
1.1.1.2 root 570: prepamigaaddr(rp_name,hlen);
571: put_long(namelen,hlen);
572: TRACE(("%d/%d\n",sb->resultval,hlen));
573: }
574:
575: ENDBLOCKING;
576: }
577: }
578:
579: typedef enum
580: {
581: connect_req,
582: recvfrom_req,
583: sendto_req,
584: abort_req,
585: last_req
586: } threadsock_e;
587:
588: struct threadsock_packet
589: {
590: threadsock_e packet_type;
591: union
592: {
1.1.1.3 ! root 593: struct sendto_params
! 594: {
! 595: char *buf;
! 596: char *realpt;
! 597: uae_u32 sd;
! 598: uae_u32 msg;
! 599: uae_u32 len;
! 600: uae_u32 flags;
! 601: uae_u32 to;
! 602: uae_u32 tolen;
! 603: } sendto_s;
! 604: struct recvfrom_params
! 605: {
! 606: char *realpt;
! 607: uae_u32 addr;
! 608: uae_u32 len;
! 609: uae_u32 flags;
! 610: struct sockaddr *rp_addr;
! 611: int *hlen;
! 612: } recvfrom_s;
! 613: struct connect_params
! 614: {
! 615: char *buf;
! 616: uae_u32 namelen;
! 617: } connect_s;
! 618: struct abort_params
! 619: {
! 620: SOCKET *newsock;
! 621: } abort_s;
1.1.1.2 root 622: } params;
623: SOCKET s;
624: SB;
625: } sockreq;
626:
627: BOOL HandleStuff( void )
628: {
629: BOOL quit = FALSE;
630: SB = NULL;
631: BOOL handled = TRUE;
632:
633: if( hSockReq )
634: {
635: // 100ms sleepiness might need some tuning...
636: if( WaitForSingleObject( hSockReq, 100 ) == WAIT_OBJECT_0 )
637: {
638: switch( sockreq.packet_type )
639: {
640: case connect_req:
1.1.1.3 ! root 641: sockreq.sb->resultval = connect(sockreq.s,(struct sockaddr *)(sockreq.params.connect_s.buf),sockreq.params.connect_s.namelen);
1.1.1.2 root 642: break;
643: case sendto_req:
644: if( sockreq.params.sendto_s.to )
645: {
646: sockreq.sb->resultval = sendto(sockreq.s,sockreq.params.sendto_s.realpt,sockreq.params.sendto_s.len,sockreq.params.sendto_s.flags,(struct sockaddr *)(sockreq.params.sendto_s.buf),sockreq.params.sendto_s.tolen);
647: }
648: else
649: {
650: sockreq.sb->resultval = send(sockreq.s,sockreq.params.sendto_s.realpt,sockreq.params.sendto_s.len,sockreq.params.sendto_s.flags);
651: }
652: break;
653: case recvfrom_req:
654: if( sockreq.params.recvfrom_s.addr )
655: {
656: sockreq.sb->resultval = recvfrom( sockreq.s, sockreq.params.recvfrom_s.realpt, sockreq.params.recvfrom_s.len,
657: sockreq.params.recvfrom_s.flags, sockreq.params.recvfrom_s.rp_addr,
658: sockreq.params.recvfrom_s.hlen );
659: }
660: else
661: {
662: sockreq.sb->resultval = recv( sockreq.s, sockreq.params.recvfrom_s.realpt, sockreq.params.recvfrom_s.len,
663: sockreq.params.recvfrom_s.flags );
664: }
665: break;
666: case abort_req:
667: *(sockreq.params.abort_s.newsock) = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
668: //shutdown( sb->sockAbort, 1 );
669: closesocket(sb->sockAbort);
670: handled = FALSE; /* Don't bother the SETERRNO section after the switch() */
671: break;
672: case last_req:
673: default:
674: write_log( "BSDSOCK: Invalid sock-thread request!\n" );
675: handled = FALSE;
676: break;
677: }
678: if( handled )
679: {
680: if( sockreq.sb->resultval == SOCKET_ERROR )
681: {
682: sb = sockreq.sb;
683: SETERRNO;
684: }
685: }
686: SetEvent( hSockReqHandled );
687: }
688: }
689: else
690: {
691: quit = TRUE;
692: }
693: return quit;
694: }
695:
696: long FAR PASCAL SocketWindowProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
697: {
698: #ifdef BSDSOCKET_SUPPORTED
699: if( message >= 0xB000 && message < 0xB000+MAXPENDINGASYNC*2 )
700: {
701: #if DEBUG_SOCKETS
1.1.1.3 ! root 702: write_log( "sockmsg(0x%x, 0x%x, 0x%x)\n", message, wParam, lParam );
1.1.1.2 root 703: #endif
1.1.1.3 ! root 704: sockmsg( message, wParam, lParam );
! 705: return 0;
1.1.1.2 root 706: }
707: #endif
1.1 root 708:
1.1.1.2 root 709: return DefWindowProc( hwnd, message, wParam, lParam );
1.1 root 710: }
711:
1.1.1.2 root 712: static unsigned int __stdcall sock_thread(void *blah)
1.1 root 713: {
1.1.1.2 root 714: unsigned int result = 0;
715: MSG msg;
716: WNDCLASS wc; // Set up an invisible window and dummy wndproc
717:
718: wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW;
719: wc.lpfnWndProc = SocketWindowProc;
720: wc.cbClsExtra = 0;
721: wc.cbWndExtra = 0;
722: wc.hInstance = 0;
723: wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE( IDI_APPICON ) );
724: wc.hCursor = LoadCursor (NULL, IDC_ARROW);
725: wc.hbrBackground = GetStockObject (BLACK_BRUSH);
726: wc.lpszMenuName = 0;
727: wc.lpszClassName = "SocketFun";
728: if( RegisterClass (&wc) )
729: {
730: hSockWnd = CreateWindowEx ( 0,
731: "SocketFun", "WinUAE Socket Window",
732: WS_POPUP,
733: 0, 0,
734: 1, 1,
735: NULL, NULL, 0, NULL);
736: if( hSockWnd )
737: {
738: // Make sure we're outrunning the wolves
739: SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL );
740:
741: while( TRUE )
742: {
743: if( PeekMessage( &msg, NULL, WM_USER, 0xB000+MAXPENDINGASYNC*2, PM_REMOVE ) > 0 )
744: {
745: TranslateMessage( &msg );
746: DispatchMessage( &msg );
747: }
748: if( HandleStuff() ) // See if its time to quit...
749: break;
750: }
751: }
752: }
753: write_log( "BSDSOCK: We have exited our sock_thread()\n" );
754: #ifndef __GNUC__
755: _endthreadex( result );
756: #endif
757: return result;
1.1 root 758: }
759:
760: void host_connect(SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
761: {
1.1.1.2 root 762: SOCKET s;
763: int success = 0;
764: unsigned int wMsg;
765: char buf[MAXADDRLEN];
766: TRACE(("connect(%d,0x%lx,%d) -> ",sd,name,namelen));
767:
768: s = (SOCKET)getsock(sb,(int)sd);
769:
770: if (s != INVALID_SOCKET)
771: {
772: if (namelen <= MAXADDRLEN)
773: {
774: if ((wMsg = allocasyncmsg(sb,sd,s)) != 0)
775: {
776: WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_CONNECT);
1.1 root 777:
1.1.1.2 root 778: BEGINBLOCKING;
1.1.1.3 ! root 779: PREPARE_THREAD;
1.1 root 780:
1.1.1.2 root 781: memcpy(buf,get_real_address(name),namelen);
782: prephostaddr((SOCKADDR_IN *)buf);
1.1 root 783:
1.1.1.3 ! root 784: sockreq.packet_type = connect_req;
! 785: sockreq.s = s;
! 786: sockreq.sb = sb;
! 787: sockreq.params.connect_s.buf = buf;
! 788: sockreq.params.connect_s.namelen = namelen;
1.1.1.2 root 789:
1.1.1.3 ! root 790: TRIGGER_THREAD;
1.1.1.2 root 791: if (sb->resultval)
792: {
793: if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR)
794: {
795: if (sb->ftable[sd-1] & SF_BLOCKING)
796: {
797: seterrno(sb,0);
798:
799: WAITSIGNAL;
800:
801: if (sb->eintr)
802: {
803: // Destroy socket to cancel abort, replace it with fake socket to enable proper closing.
804: // This is in accordance with BSD behaviour.
1.1.1.3 ! root 805: //shutdown(s,1);
1.1.1.2 root 806: closesocket(s);
807: sb->dtable[sd-1] = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
808: }
809: }
1.1.1.3 ! root 810: else
! 811: seterrno(sb,36); // EINPROGRESS
1.1.1.2 root 812: }
1.1.1.3 ! root 813: }
1.1.1.2 root 814:
1.1.1.3 ! root 815: ENDBLOCKING;
1.1.1.2 root 816:
1.1.1.3 ! root 817: cancelasyncmsg(wMsg);
1.1.1.2 root 818: }
1.1.1.3 ! root 819: }
! 820: else
! 821: write_log("BSDSOCK: WARNING - Excessive namelen (%d) in connect()!\n",namelen);
1.1.1.2 root 822: }
1.1 root 823:
1.1.1.2 root 824: TRACE(("%d\n",sb->sb_errno));
1.1 root 825: }
826:
827: void host_sendto(SB, uae_u32 sd, uae_u32 msg, uae_u32 len, uae_u32 flags, uae_u32 to, uae_u32 tolen)
828: {
1.1.1.2 root 829: SOCKET s;
830: char *realpt;
831: unsigned int wMsg;
832: char buf[MAXADDRLEN];
1.1 root 833:
834: #ifdef TRACING_ENABLED
1.1.1.2 root 835: if (to) TRACE(("sendto(%d,0x%lx,%d,0x%lx,0x%lx,%d) -> ",sd,msg,len,flags,to,tolen))
836: else TRACE(("send(%d,0x%lx,%d,%d) -> ",sd,msg,len,flags));
1.1 root 837: #endif
838:
1.1.1.2 root 839: s = getsock(sb,sd);
1.1 root 840:
1.1.1.2 root 841: if (s != INVALID_SOCKET)
842: {
1.1.1.3 ! root 843: realpt = get_real_address(msg);
1.1 root 844:
1.1.1.2 root 845: if (to)
846: {
847: if (tolen > sizeof buf) write_log("BSDSOCK: WARNING - Target address in sendto() too large (%d)!\n",tolen);
848: else
849: {
850: memcpy(buf,get_real_address(to),tolen);
851: // some Amiga software sets this field to bogus values
852: prephostaddr((SOCKADDR_IN *)buf);
853: }
854: }
1.1 root 855:
1.1.1.2 root 856: BEGINBLOCKING;
1.1 root 857:
1.1.1.2 root 858: for (;;)
859: {
1.1.1.3 ! root 860: PREPARE_THREAD;
1.1 root 861:
1.1.1.3 ! root 862: sockreq.packet_type = sendto_req;
! 863: sockreq.s = s;
! 864: sockreq.sb = sb;
! 865: sockreq.params.sendto_s.realpt = realpt;
! 866: sockreq.params.sendto_s.buf = buf;
! 867: sockreq.params.sendto_s.sd = sd;
! 868: sockreq.params.sendto_s.msg = msg;
! 869: sockreq.params.sendto_s.len = len;
! 870: sockreq.params.sendto_s.flags = flags;
! 871: sockreq.params.sendto_s.to = to;
! 872: sockreq.params.sendto_s.tolen = tolen;
1.1.1.2 root 873:
1.1.1.3 ! root 874: TRIGGER_THREAD;
1.1.1.2 root 875: if (sb->resultval == -1)
876: {
877: if (sb->sb_errno != WSAEWOULDBLOCK-WSABASEERR || !(sb->ftable[sd-1] & SF_BLOCKING)) break;
878: }
879: else
880: {
881: realpt += sb->resultval;
882: len -= sb->resultval;
883:
884: if (len <= 0) break;
885: else continue;
886: }
887:
888: if ((wMsg = allocasyncmsg(sb,sd,s)) != 0)
889: {
890: WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_WRITE);
1.1 root 891:
1.1.1.2 root 892: WAITSIGNAL;
893:
894: cancelasyncmsg(wMsg);
895:
896: if (sb->eintr)
897: {
898: TRACE(("[interrupted]\n"));
899: return;
1.1 root 900: }
1.1.1.2 root 901: }
902: else break;
1.1 root 903: }
1.1.1.2 root 904:
905: ENDBLOCKING;
906: }
907: else sb->resultval = -1;
1.1 root 908:
909: #ifdef TRACING_ENABLED
1.1.1.2 root 910: if (sb->resultval == -1) TRACE(("failed (%d)\n",sb->sb_errno))
911: else TRACE(("%d\n",sb->resultval));
1.1 root 912: #endif
913: }
914:
915: void host_recvfrom(SB, uae_u32 sd, uae_u32 msg, uae_u32 len, uae_u32 flags, uae_u32 addr, uae_u32 addrlen)
916: {
1.1.1.2 root 917: SOCKET s;
918: char *realpt;
919: struct sockaddr *rp_addr = NULL;
920: int hlen;
921: unsigned int wMsg;
1.1 root 922:
923: #ifdef TRACING_ENABLED
1.1.1.2 root 924: if (addr) TRACE(("recvfrom(%d,0x%lx,%d,0x%lx,0x%lx,%d) -> ",sd,msg,len,flags,addr,get_long(addrlen)))
925: else TRACE(("recv(%d,0x%lx,%d,0x%lx) -> ",sd,msg,len,flags));
1.1 root 926: #endif
927:
1.1.1.2 root 928: s = getsock(sb,sd);
1.1 root 929:
1.1.1.2 root 930: if (s != INVALID_SOCKET)
931: {
932: realpt = get_real_address(msg);
933:
934: if (addr)
1.1 root 935: {
1.1.1.2 root 936: hlen = get_long(addrlen);
937: rp_addr = (struct sockaddr *)get_real_address(addr);
938: }
1.1 root 939:
1.1.1.2 root 940: BEGINBLOCKING;
1.1 root 941:
1.1.1.2 root 942: for (;;)
943: {
1.1.1.3 ! root 944: PREPARE_THREAD;
1.1 root 945:
1.1.1.3 ! root 946: sockreq.packet_type = recvfrom_req;
! 947: sockreq.s = s;
! 948: sockreq.sb = sb;
! 949: sockreq.params.recvfrom_s.addr = addr;
! 950: sockreq.params.recvfrom_s.flags = flags;
! 951: sockreq.params.recvfrom_s.hlen = &hlen;
! 952: sockreq.params.recvfrom_s.len = len;
! 953: sockreq.params.recvfrom_s.realpt = realpt;
! 954: sockreq.params.recvfrom_s.rp_addr = rp_addr;
1.1.1.2 root 955:
1.1.1.3 ! root 956: TRIGGER_THREAD;
1.1.1.2 root 957: if (sb->resultval == -1)
958: {
959: if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR && sb->ftable[sd-1] & SF_BLOCKING)
1.1 root 960: {
1.1.1.2 root 961: if ((wMsg = allocasyncmsg(sb,sd,s)) != 0)
962: {
963: WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_READ);
1.1 root 964:
1.1.1.2 root 965: WAITSIGNAL;
966:
967: cancelasyncmsg(wMsg);
968:
969: if (sb->eintr)
1.1 root 970: {
1.1.1.2 root 971: TRACE(("[interrupted]\n"));
972: return;
1.1 root 973: }
1.1.1.2 root 974: }
975: else break;
1.1 root 976: }
1.1.1.2 root 977: else break;
978: }
979: else break;
980: }
981:
982: ENDBLOCKING;
1.1 root 983:
1.1.1.2 root 984: if (addr)
985: {
986: prepamigaaddr(rp_addr,hlen);
987: put_long(addrlen,hlen);
1.1 root 988: }
1.1.1.2 root 989: }
990: else sb->resultval = -1;
1.1 root 991:
992: #ifdef TRACING_ENABLED
1.1.1.2 root 993: if (sb->resultval == -1) TRACE(("failed (%d)\n",sb->sb_errno))
994: else TRACE(("%d\n",sb->resultval));
1.1 root 995: #endif
996: }
997:
998: uae_u32 host_shutdown(SB, uae_u32 sd, uae_u32 how)
999: {
1.1.1.2 root 1000: SOCKET s;
1001:
1002: TRACE(("shutdown(%d,%d) -> ",sd,how));
1003:
1004: s = getsock(sb,sd);
1005:
1006: if (s != INVALID_SOCKET)
1007: {
1008: if (shutdown(s,how))
1.1 root 1009: {
1.1.1.2 root 1010: SETERRNO;
1011: TRACE(("failed (%d)\n",sb->sb_errno));
1.1 root 1012: }
1.1.1.2 root 1013: else
1014: {
1015: TRACE(("OK\n"));
1016: return 0;
1017: }
1018: }
1.1 root 1019:
1.1.1.2 root 1020: return -1;
1.1 root 1021: }
1022:
1023: void host_setsockopt(SB, uae_u32 sd, uae_u32 level, uae_u32 optname, uae_u32 optval, uae_u32 len)
1024: {
1.1.1.2 root 1025: SOCKET s;
1026: char buf[MAXADDRLEN];
1.1 root 1027:
1.1.1.2 root 1028: TRACE(("setsockopt(%d,%d,0x%lx,0x%lx,%d) -> ",sd,(short)level,optname,optval,len));
1.1 root 1029:
1.1.1.2 root 1030: s = getsock(sb,sd);
1.1 root 1031:
1.1.1.2 root 1032: if (s != INVALID_SOCKET)
1033: {
1034: if (len > sizeof buf)
1.1 root 1035: {
1.1.1.2 root 1036: write_log("BSDSOCK: WARNING - Excessive optlen in setsockopt() (%d)\n",len);
1037: len = sizeof buf;
1038: }
1.1 root 1039:
1.1.1.2 root 1040: if (level == SOL_SOCKET && optname == SO_LINGER)
1041: {
1042: ((LINGER *)buf)->l_onoff = get_long(optval);
1043: ((LINGER *)buf)->l_linger = get_long(optval+4);
1044: }
1045: else
1046: {
1047: if (len == 4) *(long *)buf = get_long(optval);
1048: else if (len == 2) *(short *)buf = get_word(optval);
1049: else write_log("BSDSOCK: ERROR - Unknown optlen (%d) in setsockopt(%d,%d)\n",level,optname);
1050: }
1051:
1052: // handle SO_EVENTMASK
1053: if (level == 0xffff && optname == 0x2001)
1054: {
1055: long wsbevents = 0;
1056: uae_u32 eventflags = get_long(optval);
1057:
1058: sb->ftable[sd-1] = (sb->ftable[sd-1] & ~REP_ALL) | (eventflags & REP_ALL);
1059:
1060: if (eventflags & REP_ACCEPT) wsbevents |= FD_ACCEPT;
1061: if (eventflags & REP_CONNECT) wsbevents |= FD_CONNECT;
1062: if (eventflags & REP_OOB) wsbevents |= FD_OOB;
1063: if (eventflags & REP_READ) wsbevents |= FD_READ;
1064: if (eventflags & REP_WRITE) wsbevents |= FD_WRITE;
1065: if (eventflags & REP_CLOSE) wsbevents |= FD_CLOSE;
1066:
1067: if (sb->mtable[sd-1] || (sb->mtable[sd-1] = allocasyncmsg(sb,sd,s)))
1068: {
1069: WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,sb->mtable[sd-1],wsbevents);
1070: sb->resultval = 0;
1071: }
1072: else sb->resultval = -1;
1073: }
1074: else sb->resultval = setsockopt(s,level,optname,buf,len);
1.1 root 1075:
1.1.1.2 root 1076: if (!sb->resultval)
1077: {
1078: TRACE(("OK\n"));
1079: return;
1.1 root 1080: }
1.1.1.2 root 1081: else SETERRNO;
1082:
1083: TRACE(("failed (%d)\n",sb->sb_errno));
1084: }
1.1 root 1085: }
1086:
1087: uae_u32 host_getsockopt(SB, uae_u32 sd, uae_u32 level, uae_u32 optname, uae_u32 optval, uae_u32 optlen)
1088: {
1089: SOCKET s;
1090: char buf[MAXADDRLEN];
1091: int len = sizeof(buf);
1092:
1093: TRACE(("getsockopt(%d,%d,0x%lx,0x%lx,0x%lx) -> ",sd,(short)level,optname,optval,optlen));
1094:
1095: s = getsock(sb,sd);
1096:
1097: if (s != INVALID_SOCKET)
1098: {
1099: if (!getsockopt(s,level,optname,buf,&len))
1100: {
1101: if (level == SOL_SOCKET && optname == SO_LINGER)
1102: {
1103: put_long(optval,((LINGER *)buf)->l_onoff);
1104: put_long(optval+4,((LINGER *)buf)->l_linger);
1105: }
1106: else
1107: {
1108: if (len == 4) put_long(optval,*(long *)buf);
1109: else if (len == 2) put_word(optval,*(short *)buf);
1.1.1.2 root 1110: else write_log("BSDSOCK: ERROR - Unknown optlen (%d) in setsockopt(%d,%d)\n",level,optname);
1.1 root 1111: }
1112:
1113: // put_long(optlen,len); // some programs pass the actual ength instead of a pointer to the length, so...
1114: TRACE(("OK (%d,%d)\n",len,*(long *)buf));
1115: return 0;
1116: }
1117: else
1118: {
1119: SETERRNO;
1120: TRACE(("failed (%d)\n",sb->sb_errno));
1121: }
1122: }
1123:
1124: return -1;
1125: }
1126:
1127: uae_u32 host_getsockname(SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
1128: {
1129: SOCKET s;
1130: int len;
1131: struct sockaddr *rp_name;
1132:
1133: len = get_long(namelen);
1134:
1135: TRACE(("getsockname(%d,0x%lx,%d) -> ",sd,name,len));
1136:
1137: s = getsock(sb,sd);
1138:
1139: if (s != INVALID_SOCKET)
1140: {
1141: rp_name = (struct sockaddr *)get_real_address(name);
1142:
1143: if (getsockname(s,rp_name,&len))
1144: {
1145: SETERRNO;
1146: TRACE(("failed (%d)\n",sb->sb_errno));
1147: }
1148: else
1149: {
1150: TRACE(("%d\n",len));
1151: prepamigaaddr(rp_name,len);
1152: put_long(namelen,len);
1153: return 0;
1154: }
1155: }
1156:
1157: return -1;
1158: }
1159:
1160: uae_u32 host_getpeername(SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
1161: {
1162: SOCKET s;
1163: int len;
1164: struct sockaddr *rp_name;
1165:
1166: len = get_long(namelen);
1167:
1168: TRACE(("getpeername(%d,0x%lx,%d) -> ",sd,name,len));
1169:
1170: s = getsock(sb,sd);
1171:
1172: if (s != INVALID_SOCKET)
1173: {
1174: rp_name = (struct sockaddr *)get_real_address(name);
1175:
1176: if (getpeername(s,rp_name,&len))
1177: {
1178: SETERRNO;
1179: TRACE(("failed (%d)\n",sb->sb_errno));
1180: }
1181: else
1182: {
1183: TRACE(("%d\n",len));
1184: prepamigaaddr(rp_name,len);
1185: put_long(namelen,len);
1186: return 0;
1187: }
1188: }
1189:
1190: return -1;
1191: }
1192:
1193: uae_u32 host_IoctlSocket(SB, uae_u32 sd, uae_u32 request, uae_u32 arg)
1194: {
1195: SOCKET s;
1196: uae_u32 data;
1197: int success = SOCKET_ERROR;
1198:
1199: TRACE(("IoctlSocket(%d,0x%lx,0x%lx) ",sd,request,arg));
1200:
1201: s = getsock(sb,sd);
1202:
1203: if (s != INVALID_SOCKET)
1204: {
1205: switch (request)
1206: {
1207: case FIONBIO:
1208: TRACE(("[FIONBIO] -> "));
1209: if (get_long(arg))
1210: {
1211: TRACE(("nonblocking\n"));
1212: sb->ftable[sd-1] &= ~SF_BLOCKING;
1213: }
1214: else
1215: {
1216: TRACE(("blocking\n"));
1217: sb->ftable[sd-1] |= SF_BLOCKING;
1218: }
1219: success = 0;
1220: break;
1221: case FIONREAD:
1222: ioctlsocket(s,request,(u_long *)&data);
1223: TRACE(("[FIONREAD] -> %d\n",data));
1224: put_long(arg,data);
1225: success = 0;
1226: break;
1227: case FIOASYNC:
1228: if (get_long(arg))
1229: {
1230: sb->ftable[sd-1] |= REP_ALL;
1231:
1232: TRACE(("[FIOASYNC] -> enabled\n"));
1233: if (sb->mtable[sd-1] || (sb->mtable[sd-1] = allocasyncmsg(sb,sd,s)))
1234: {
1.1.1.2 root 1235: WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,sb->mtable[sd-1],FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE | FD_CLOSE);
1.1 root 1236: success = 0;
1237: break;
1238: }
1239: }
1.1.1.2 root 1240: else write_log(("BSDSOCK: WARNING - FIOASYNC disabling unsupported.\n"));
1.1 root 1241:
1242: success = -1;
1243: break;
1244: default:
1.1.1.2 root 1245: write_log("BSDSOCK: WARNING - Unknown IoctlSocket request: 0x%08lx\n",request);
1.1 root 1246: seterrno(sb,22); // EINVAL
1247: }
1248: }
1249:
1250: return success;
1251: }
1252:
1253: int host_CloseSocket(SB, int sd)
1254: {
1.1.1.2 root 1255: unsigned int wMsg;
1256: SOCKET s;
1.1 root 1257:
1.1.1.2 root 1258: TRACE(("CloseSocket(%d) -> ",sd));
1.1 root 1259:
1.1.1.2 root 1260: s = getsock(sb,sd);
1.1 root 1261:
1.1.1.2 root 1262: if (s != INVALID_SOCKET)
1263: {
1264: if (sb->mtable[sd-1])
1.1 root 1265: {
1.1.1.2 root 1266: asyncsb[(sb->mtable[sd-1]-0xb000)/2] = NULL;
1267: sb->mtable[sd-1] = 0;
1268: }
1.1 root 1269:
1.1.1.2 root 1270: BEGINBLOCKING;
1.1 root 1271:
1.1.1.2 root 1272: for (;;)
1273: {
1.1.1.3 ! root 1274: //shutdown(s,1);
1.1.1.2 root 1275: if (!closesocket(s))
1276: {
1277: releasesock(sb,sd);
1278: TRACE(("OK\n"));
1279: return 0;
1280: }
1.1 root 1281:
1.1.1.2 root 1282: SETERRNO;
1283:
1284: if (sb->sb_errno != WSAEWOULDBLOCK-WSABASEERR || !(sb->ftable[sd-1] & SF_BLOCKING)) break;
1285:
1286: if ((wMsg = allocasyncmsg(sb,sd,s)) != 0)
1287: {
1288: WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_CLOSE);
1.1 root 1289:
1.1.1.2 root 1290: WAITSIGNAL;
1291:
1292: cancelasyncmsg(wMsg);
1293:
1294: if (sb->eintr)
1295: {
1296: TRACE(("[interrupted]\n"));
1297: break;
1.1 root 1298: }
1.1.1.2 root 1299: }
1300: else break;
1.1 root 1301: }
1.1.1.2 root 1302:
1.1.1.3 ! root 1303: ENDBLOCKING;
1.1.1.2 root 1304: }
1.1 root 1305:
1.1.1.2 root 1306: TRACE(("failed (%d)\n",sb->sb_errno));
1307:
1308: return -1;
1.1 root 1309: }
1310:
1311: // For the sake of efficiency, we do not malloc() the fd_sets here.
1312: // 64 sockets should be enough for everyone.
1313: static void makesocktable(SB, uae_u32 fd_set_amiga, struct fd_set *fd_set_win, int nfds, SOCKET addthis)
1314: {
1.1.1.2 root 1315: int i, j;
1.1 root 1316: uae_u32 currlong, mask;
1317: SOCKET s;
1318:
1319: if (addthis != INVALID_SOCKET)
1320: {
1321: *fd_set_win->fd_array = addthis;
1322: fd_set_win->fd_count = 1;
1323: }
1324: else fd_set_win->fd_count = 0;
1325:
1326: if (!fd_set_amiga)
1327: {
1328: fd_set_win->fd_array[fd_set_win->fd_count] = INVALID_SOCKET;
1329: return;
1330: }
1331:
1332: if (nfds > sb->dtablesize)
1333: {
1.1.1.2 root 1334: write_log("BSDSOCK: ERROR - select()ing more sockets (%d) than socket descriptors available (%d)!\n",nfds,sb->dtablesize);
1.1 root 1335: nfds = sb->dtablesize;
1336: }
1337:
1338: for (j = 0; ; j += 32, fd_set_amiga += 4)
1339: {
1340: currlong = get_long(fd_set_amiga);
1341:
1342: mask = 1;
1343:
1344: for (i = 0; i < 32; i++, mask <<= 1)
1345: {
1346: if (i+j > nfds)
1347: {
1348: fd_set_win->fd_array[fd_set_win->fd_count] = INVALID_SOCKET;
1349: return;
1350: }
1351:
1352: if (currlong & mask)
1353: {
1354: s = getsock(sb,j+i);
1355:
1356: if (s != INVALID_SOCKET)
1357: {
1358: fd_set_win->fd_array[fd_set_win->fd_count++] = s;
1359:
1360: if (fd_set_win->fd_count >= FD_SETSIZE)
1361: {
1.1.1.2 root 1362: write_log("BSDSOCK: ERROR - select()ing more sockets (%d) than the hard-coded fd_set limit (%d) - please report\n",nfds,FD_SETSIZE);
1.1 root 1363: return;
1364: }
1365: }
1366: }
1367: }
1368: }
1369:
1370: fd_set_win->fd_array[fd_set_win->fd_count] = INVALID_SOCKET;
1371: }
1372:
1373: static void makesockbitfield(SB, uae_u32 fd_set_amiga, struct fd_set *fd_set_win, int nfds)
1374: {
1375: int n, i, j, val, mask;
1376: SOCKET currsock;
1377:
1378: for (n = 0; n < nfds; n += 32)
1379: {
1380: val = 0;
1381: mask = 1;
1382:
1383: for (i = 0; i < 32; i++, mask <<= 1)
1384: {
1385: if ((n || i) && (currsock = sb->dtable[n+i-1]) != INVALID_SOCKET)
1386: {
1387: for (j = fd_set_win->fd_count; j--; )
1388: {
1389: if (fd_set_win->fd_array[j] == currsock)
1390: {
1391: val |= mask;
1392: break;
1393: }
1394: }
1395: }
1396: }
1397:
1398: put_long(fd_set_amiga,val);
1399: }
1400: }
1401:
1402: static void fd_zero(uae_u32 fdset, uae_u32 nfds)
1403: {
1404: unsigned int i;
1405:
1406: for (i = 0; i < nfds; i += 32, fdset += 4) put_long(fdset,0);
1407: }
1408:
1409: // This seems to be the only way of implementing a cancelable WinSock2 select() call... sigh.
1.1.1.2 root 1410: static unsigned int __stdcall thread_WaitSelect(void *index2)
1.1 root 1411: {
1.1.1.2 root 1412: uae_u32 index = (uae_u32)index2;
1413: unsigned int result = 0;
1414: long nfds;
1415: uae_u32 readfds, writefds, exceptfds;
1416: uae_u32 timeout;
1417: struct fd_set readsocks, writesocks, exceptsocks;
1418: struct timeval tv;
1419: uae_u32 *args;
1420:
1421: SB;
1422:
1423: for (;;)
1424: {
1425: WaitForSingleObject(hEvents[index],INFINITE);
1426:
1427: if ((args = threadargs[index]) != NULL)
1428: {
1429: sb = (struct socketbase *)*args;
1430: nfds = args[1];
1431: readfds = args[2];
1432: writefds = args[3];
1433: exceptfds = args[4];
1434: timeout = args[5];
1435:
1436: // construct descriptor tables
1437: makesocktable(sb,readfds,&readsocks,nfds,sb->sockAbort);
1438: if (writefds) makesocktable(sb,writefds,&writesocks,nfds,INVALID_SOCKET);
1439: if (exceptfds) makesocktable(sb,exceptfds,&exceptsocks,nfds,INVALID_SOCKET);
1440:
1441: if (timeout)
1442: {
1443: tv.tv_sec = get_long(timeout);
1444: tv.tv_usec = get_long(timeout+4);
1445: TRACE(("(timeout: %d.%06d) ",tv.tv_sec,tv.tv_usec))
1446: }
1447:
1448: TRACE(("-> "));
1449:
1450: sb->resultval = select(nfds+1,&readsocks,writefds ? &writesocks : NULL,exceptfds ? &exceptsocks : NULL,timeout ? &tv : 0);
1451: sb->needAbort = 0;
1452:
1453: if (sb->resultval == SOCKET_ERROR)
1454: {
1455: SETERRNO;
1456: TRACE(("failed (%d) - ",sb->sb_errno));
1457: if (readfds) fd_zero(readfds,nfds);
1458: if (writefds) fd_zero(writefds,nfds);
1459: if (exceptfds) fd_zero(exceptfds,nfds);
1460: }
1461: else
1462: {
1463: if (readfds) makesockbitfield(sb,readfds,&readsocks,nfds);
1464: if (writefds) makesockbitfield(sb,writefds,&writesocks,nfds);
1465: if (exceptfds) makesockbitfield(sb,exceptfds,&exceptsocks,nfds);
1466: }
1467:
1468: SETSIGNAL;
1469:
1470: threadargs[index] = NULL;
1471: SetEvent(sb->hEvent);
1472: }
1473: }
1474: #ifndef __GNUC__
1475: _endthreadex( result );
1476: #endif
1477: return result;
1.1 root 1478: }
1479:
1.1.1.2 root 1480: void host_WaitSelect(SB, uae_u32 nfds, uae_u32 readfds, uae_u32 writefds, uae_u32 exceptfds, uae_u32 timeout, uae_u32 sigmp)
1.1 root 1481: {
1482: uae_u32 sigs, wssigs;
1483: int i;
1484:
1485: wssigs = sigmp ? get_long(sigmp) : 0;
1486:
1487: TRACE(("WaitSelect(%d,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx) ",nfds,readfds,writefds,exceptfds,timeout,wssigs));
1488:
1489: if (!readfds && !writefds && !exceptfds && !timeout && !wssigs)
1490: {
1491: sb->resultval = 0;
1492: TRACE(("-> [ignored]\n"))
1493: return;
1494: }
1495:
1496: if (wssigs)
1497: {
1498: m68k_dreg(regs,0) = 0;
1499: m68k_dreg(regs,1) = wssigs;
1500: sigs = CallLib(get_long(4),-0x132) & wssigs; // SetSignal()
1501:
1502: if (sigs)
1503: {
1504: TRACE(("-> [preempted by signals 0x%08lx]\n",sigs & wssigs));
1505: put_long(sigmp,sigs & wssigs);
1506: fd_zero(readfds,nfds);
1507: fd_zero(writefds,nfds);
1508: fd_zero(exceptfds,nfds);
1509: sb->resultval = 0;
1510: seterrno(sb,0);
1511: return;
1512: }
1513: }
1514:
1515: ResetEvent(sb->hEvent);
1516:
1517: sb->needAbort = 1;
1518:
1519: for (i = 0; i < MAX_SELECT_THREADS; i++) if (hThreads[i] && !threadargs[i]) break;
1520:
1521: if (i >= MAX_SELECT_THREADS)
1522: {
1.1.1.2 root 1523: for (i = 0; i < MAX_SELECT_THREADS; i++)
1524: {
1525: if (!hThreads[i])
1526: {
1527: if ((hEvents[i] = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL || (hThreads[i] = (void *)THREAD(thread_WaitSelect,i)) == NULL)
1528: {
1529: hThreads[i] = 0;
1530: write_log("BSDSOCK: ERROR - Thread/Event creation failed - error code: %d\n",GetLastError());
1531: seterrno(sb,12); // ENOMEM
1532: sb->resultval = -1;
1533: return;
1534: }
1535:
1536: // this should improve responsiveness
1537: SetThreadPriority(hThreads[i],THREAD_PRIORITY_TIME_CRITICAL);
1538: break;
1.1 root 1539: }
1.1.1.2 root 1540: }
1.1 root 1541: }
1542:
1.1.1.2 root 1543: if (i >= MAX_SELECT_THREADS) write_log("BSDSOCK: ERROR - Too many select()s\n");
1.1 root 1544: else
1545: {
1546: SOCKET newsock = INVALID_SOCKET;
1547:
1548: threadargs[i] = (uae_u32 *)&sb;
1549:
1550: SetEvent(hEvents[i]);
1551:
1552: m68k_dreg(regs,0) = (((uae_u32)1)<<sb->signal)|sb->eintrsigs|wssigs;
1553: sigs = CallLib(get_long(4),-0x13e); // Wait()
1554:
1555: if (sb->needAbort)
1556: {
1557: if ((newsock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET)
1.1.1.2 root 1558: write_log("BSDSOCK: ERROR - Cannot create socket: %d\n",WSAGetLastError());
1.1.1.3 ! root 1559: //shutdown(sb->sockAbort,1);
1.1 root 1560: closesocket(sb->sockAbort);
1561: }
1562:
1563: WaitForSingleObject(sb->hEvent,INFINITE);
1564:
1565: CANCELSIGNAL;
1566:
1567: if (newsock != INVALID_SOCKET) sb->sockAbort = newsock;
1568:
1.1.1.3 ! root 1569: if( sigmp )
! 1570: {
1.1.1.2 root 1571: put_long(sigmp,sigs & wssigs);
1572:
1573: if (sigs & sb->eintrsigs)
1574: {
1575: TRACE(("[interrupted]\n"));
1576: sb->resultval = -1;
1577: seterrno(sb,4); // EINTR
1578: }
1579: else if (sigs & wssigs)
1580: {
1581: TRACE(("[interrupted by signals 0x%08lx]\n",sigs & wssigs));
1582: sb->resultval = 0;
1583: seterrno(sb,0);
1584: }
1.1.1.3 ! root 1585: }
1.1 root 1586: else TRACE(("%d\n",sb->resultval));
1587: }
1588: }
1589:
1590: uae_u32 host_Inet_NtoA(SB, uae_u32 in)
1591: {
1592: char *addr;
1593: struct in_addr ina;
1594: uae_u32 scratchbuf;
1595:
1596: *(uae_u32 *)&ina = htonl(in);
1597:
1598: TRACE(("Inet_NtoA(%lx) -> ",in));
1599:
1600: if ((addr = inet_ntoa(ina)) != NULL)
1601: {
1602: scratchbuf = m68k_areg(regs,6)+offsetof(struct UAEBSDBase,scratchbuf);
1603: strncpyha(scratchbuf,addr,SCRATCHBUFSIZE);
1604: TRACE(("%s\n",addr));
1605: return scratchbuf;
1606: }
1607: else SETERRNO;
1608:
1609: TRACE(("failed (%d)\n",sb->sb_errno));
1610:
1611: return 0;
1612: }
1613:
1614: uae_u32 host_inet_addr(uae_u32 cp)
1615: {
1616: uae_u32 addr;
1617: char *cp_rp;
1618:
1619: cp_rp = get_real_address(cp);
1620:
1621: addr = htonl(inet_addr(cp_rp));
1622:
1623: TRACE(("inet_addr(%s) -> 0x%08lx\n",cp_rp,addr));
1624:
1625: return addr;
1626: }
1627:
1628: void host_gethostbynameaddr(SB, uae_u32 name, uae_u32 namelen, long addrtype)
1629: {
1630: HOSTENT *h;
1631: int size, numaliases = 0, numaddr = 0;
1.1.1.2 root 1632: uae_u32 aptr;
1.1 root 1633: char *name_rp;
1634: int i;
1635: uae_u32 addr;
1636: uae_u32 *addr_list[2];
1637:
1638: char buf[MAXGETHOSTSTRUCT];
1639: unsigned int wMsg = 0;
1640:
1641: name_rp = get_real_address(name);
1642:
1643: if (addrtype == -1)
1644: {
1645: TRACE(("gethostbyname(%s) -> ",name_rp));
1646:
1647: // workaround for numeric host "names"
1648: if ((addr = inet_addr(name_rp)) != INADDR_NONE)
1649: {
1650: seterrno(sb,0);
1651: ((HOSTENT *)buf)->h_name = name_rp;
1652: ((HOSTENT *)buf)->h_aliases = NULL;
1653: ((HOSTENT *)buf)->h_addrtype = AF_INET;
1654: ((HOSTENT *)buf)->h_length = 4;
1655: ((HOSTENT *)buf)->h_addr_list = (char **)&addr_list;
1656: addr_list[0] = &addr;
1657: addr_list[1] = NULL;
1658:
1659: goto kludge;
1660: }
1661: }
1662: else
1663: {
1664: TRACE(("gethostbyaddr(0x%lx,0x%lx,%ld) -> ",name,namelen,addrtype));
1665: }
1666:
1667: if ((wMsg = allocasyncmsg(sb,0,INVALID_SOCKET)) != 0)
1668: {
1.1.1.2 root 1669: if ((sb->hAsyncTask = addrtype == -1 ? WSAAsyncGetHostByName(hWndSelector ? hAmigaWnd : hSockWnd,wMsg,name_rp,buf,sizeof buf) : WSAAsyncGetHostByAddr(hWndSelector ? hAmigaWnd : hSockWnd,wMsg,name_rp,namelen,addrtype,buf,sizeof buf)) != NULL)
1.1 root 1670: {
1671: while (sb->hAsyncTask) WAITSIGNAL;
1672:
1673: sockabort(sb);
1674:
1675: if (!sb->sb_errno)
1676: {
1677: kludge:
1678: h = (HOSTENT *)buf;
1679:
1680: // compute total size of hostent
1681: size = 28;
1682: if (h->h_name != NULL) size += strlen(h->h_name)+1;
1683:
1684: if (h->h_aliases != NULL)
1685: while (h->h_aliases[numaliases]) size += strlen(h->h_aliases[numaliases++])+5;
1686:
1687: if (h->h_addr_list != NULL)
1688: {
1689: while (h->h_addr_list[numaddr]) numaddr++;
1690: size += numaddr*(h->h_length+4);
1691: }
1692:
1693: if (sb->hostent)
1694: {
1.1.1.3 ! root 1695: uae_FreeMem( sb->hostent, sb->hostentsize );
1.1 root 1696: }
1.1.1.2 root 1697:
1.1.1.3 ! root 1698: sb->hostent = uae_AllocMem( size, 0 );
1.1 root 1699:
1700: if (!sb->hostent)
1701: {
1.1.1.2 root 1702: write_log("BSDSOCK: WARNING - gethostby%s() ran out of Amiga memory (couldn't allocate %ld bytes) while returning result of lookup for '%s'\n",addrtype == -1 ? "name" : "addr",size,(char *)name);
1.1 root 1703: seterrno(sb,12); // ENOMEM
1704: return;
1705: }
1706:
1707: sb->hostentsize = size;
1708:
1709: aptr = sb->hostent+28+numaliases*4+numaddr*4;
1710:
1711: // transfer hostent to Amiga memory
1712: put_long(sb->hostent+4,sb->hostent+20);
1713: put_long(sb->hostent+8,h->h_addrtype);
1714: put_long(sb->hostent+12,h->h_length);
1715: put_long(sb->hostent+16,sb->hostent+24+numaliases*4);
1716:
1717: for (i = 0; i < numaliases; i++) put_long(sb->hostent+20+i*4,addstr(&aptr,h->h_aliases[i]));
1718: put_long(sb->hostent+20+numaliases*4,0);
1719: for (i = 0; i < numaddr; i++) put_long(sb->hostent+24+(numaliases+i)*4,addmem(&aptr,h->h_addr_list[i],h->h_length));
1720: put_long(sb->hostent+24+numaliases*4+numaddr*4,0);
1721: put_long(sb->hostent,aptr);
1722: addstr(&aptr,h->h_name);
1723:
1724: TRACE(("OK (%s)\n",h->h_name));
1725: seterrno(sb,0);
1726: }
1727: else
1728: {
1729: TRACE(("failed (%d/%d)\n",sb->sb_errno,sb->sb_herrno))
1730: }
1731: }
1732: else
1733: {
1734: seterrno(sb,12); // ENOMEM - well...
1.1.1.2 root 1735: write_log("BSDSOCK: ERROR - WSAAsyncGetHostBy%s() failed - error code: %d\n",addrtype == -1 ? "Name" : "Addr",WSAGetLastError());
1.1 root 1736: }
1737:
1738: if (wMsg) cancelasyncmsg(wMsg);
1739: }
1740: }
1741:
1742: void host_getservbynameport(SB, uae_u32 nameport, uae_u32 proto, uae_u32 type)
1743: {
1744: SERVENT *s;
1745: int size, numaliases = 0;
1.1.1.2 root 1746: uae_u32 aptr;
1.1 root 1747: char *name_rp = NULL, *proto_rp = NULL;
1748: int i;
1749:
1750: char buf[MAXGETHOSTSTRUCT];
1751: unsigned int wMsg;
1752:
1753: if (proto) proto_rp = get_real_address(proto);
1754:
1755: if (type)
1756: {
1757: TRACE(("getservbyport(%d,%s) -> ",nameport,proto_rp ? proto_rp : "NULL"));
1758: }
1759: else
1760: {
1761: name_rp = get_real_address(nameport);
1762: TRACE(("getservbyname(%s,%s) -> ",name_rp,proto_rp ? proto_rp : "NULL"));
1763: }
1764:
1765: if ((wMsg = allocasyncmsg(sb,0,INVALID_SOCKET)) != 0)
1766: {
1.1.1.2 root 1767: if ((sb->hAsyncTask = type ? WSAAsyncGetServByPort(hWndSelector ? hAmigaWnd : hSockWnd,wMsg,nameport,proto_rp,buf,sizeof buf) : WSAAsyncGetServByName(hWndSelector ? hAmigaWnd : hSockWnd,wMsg,name_rp,proto_rp,buf,sizeof buf)) != NULL)
1.1 root 1768: {
1769: while (sb->hAsyncTask) WAITSIGNAL;
1770:
1771: sockabort(sb);
1772:
1773: if (!sb->sb_errno)
1774: {
1775: s = (SERVENT *)buf;
1776:
1777: // compute total size of servent
1778: size = 20;
1779: if (s->s_name != NULL) size += strlen(s->s_name)+1;
1780: if (s->s_proto != NULL) size += strlen(s->s_proto)+1;
1781:
1782: if (s->s_aliases != NULL)
1783: while (s->s_aliases[numaliases]) size += strlen(s->s_aliases[numaliases++])+5;
1784:
1785: if (sb->servent)
1786: {
1.1.1.3 ! root 1787: uae_FreeMem( sb->servent, sb->serventsize );
1.1 root 1788: }
1789:
1.1.1.3 ! root 1790: sb->servent = uae_AllocMem( size, 0 );
1.1 root 1791:
1792: if (!sb->servent)
1793: {
1.1.1.2 root 1794: write_log("BSDSOCK: WARNING - getservby%s() ran out of Amiga memory (couldn't allocate %ld bytes)\n",type ? "port" : "name",size);
1.1 root 1795: seterrno(sb,12); // ENOMEM
1796: return;
1797: }
1798:
1799: sb->serventsize = size;
1800:
1801: aptr = sb->servent+20+numaliases*4;
1802:
1803: // transfer servent to Amiga memory
1804: put_long(sb->servent+4,sb->servent+16);
1805: put_long(sb->servent+8,(unsigned short)htons(s->s_port));
1806:
1807: for (i = 0; i < numaliases; i++) put_long(sb->servent+16+i*4,addstr(&aptr,s->s_aliases[i]));
1808: put_long(sb->servent+16+numaliases*4,0);
1809: put_long(sb->servent,aptr);
1810: addstr(&aptr,s->s_name);
1811: put_long(sb->servent+12,aptr);
1812: addstr(&aptr,s->s_proto);
1813:
1814: TRACE(("OK (%s, %d)\n",s->s_name,(unsigned short)htons(s->s_port)));
1815: seterrno(sb,0);
1816: }
1817: else
1818: {
1819: TRACE(("failed (%d)\n",sb->sb_errno))
1820: }
1821: }
1822: else
1823: {
1824: seterrno(sb,12); // ENOMEM - well...
1.1.1.2 root 1825: write_log("BSDSOCK: ERROR - WSAAsyncGetServBy%s() failed - error code: %d\n",type ? "Port" : "Name",WSAGetLastError());
1.1 root 1826: }
1827:
1828: cancelasyncmsg(wMsg);
1829: }
1830: }
1831:
1832: void host_getprotobyname(SB, uae_u32 name)
1833: {
1834: PROTOENT *p;
1835: int size, numaliases = 0;
1.1.1.2 root 1836: uae_u32 aptr;
1.1 root 1837: char *name_rp;
1838: int i;
1839:
1840: char buf[MAXGETHOSTSTRUCT];
1841: unsigned int wMsg;
1842:
1843: name_rp = get_real_address(name);
1844:
1845: TRACE(("getprotobyname(%s) -> ",name_rp));
1846:
1847: if ((wMsg = allocasyncmsg(sb,0,INVALID_SOCKET)) != 0)
1848: {
1.1.1.2 root 1849: if ((sb->hAsyncTask = WSAAsyncGetProtoByName(hWndSelector ? hAmigaWnd : hSockWnd,wMsg,name_rp,buf,sizeof buf)) != NULL)
1.1 root 1850: {
1851: while (sb->hAsyncTask) WAITSIGNAL;
1852:
1853: sockabort(sb);
1854:
1855: if (!sb->sb_errno)
1856: {
1857: p = (PROTOENT *)buf;
1858:
1859: // compute total size of protoent
1860: size = 16;
1861: if (p->p_name != NULL) size += strlen(p->p_name)+1;
1862:
1863: if (p->p_aliases != NULL)
1864: while (p->p_aliases[numaliases]) size += strlen(p->p_aliases[numaliases++])+5;
1865:
1866: if (sb->protoent)
1867: {
1.1.1.3 ! root 1868: uae_FreeMem( sb->protoent, sb->protoentsize );
1.1 root 1869: }
1870:
1.1.1.2 root 1871: sb->protoent = uae_AllocMem( size, 0 );
1.1 root 1872:
1873: if (!sb->protoent)
1874: {
1.1.1.2 root 1875: write_log("BSDSOCK: WARNING - getprotobyname() ran out of Amiga memory (couldn't allocate %ld bytes) while returning result of lookup for '%s'\n",size,(char *)name);
1.1 root 1876: seterrno(sb,12); // ENOMEM
1877: return;
1878: }
1879:
1880: sb->protoentsize = size;
1881:
1882: aptr = sb->protoent+16+numaliases*4;
1883:
1884: // transfer protoent to Amiga memory
1885: put_long(sb->protoent+4,sb->protoent+12);
1886: put_long(sb->protoent+8,p->p_proto);
1887:
1888: for (i = 0; i < numaliases; i++) put_long(sb->protoent+12+i*4,addstr(&aptr,p->p_aliases[i]));
1889: put_long(sb->protoent+12+numaliases*4,0);
1890: put_long(sb->protoent,aptr);
1891: addstr(&aptr,p->p_name);
1892: TRACE(("OK (%s, %d)\n",p->p_name,p->p_proto));
1893: seterrno(sb,0);
1894: }
1895: else
1896: {
1897: TRACE(("failed (%d)\n",sb->sb_errno))
1898: }
1899: }
1900: else
1901: {
1902: seterrno(sb,12); // ENOMEM - well...
1.1.1.2 root 1903: write_log("BSDSOCK: ERROR - WSAAsyncGetProtoByName() failed - error code: %d\n",WSAGetLastError());
1.1 root 1904: }
1905:
1906: cancelasyncmsg(wMsg);
1907: }
1908: }
1909:
1910: uae_u32 host_gethostname(uae_u32 name, uae_u32 namelen)
1911: {
1912: return gethostname(get_real_address(name),namelen);
1913: }
1.1.1.2 root 1914:
1915: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.