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