--- uae/src/od-win32/bsdsock.c 2018/04/24 16:45:40 1.1.1.1 +++ uae/src/od-win32/bsdsock.c 2018/04/24 17:19:22 1.1.1.4 @@ -1,34 +1,45 @@ - /* - * UAE - The Un*x Amiga Emulator - * - * bsdsocket.library emulation - Win32 OS-dependent part - * - * Copyright 1997,98 Mathias Ortmann - * - */ - -#include -#include - +/* + * UAE - The Un*x Amiga Emulator + * + * bsdsocket.library emulation - Win32 OS-dependent part + * + * Copyright 1997,98 Mathias Ortmann + * Copyright 1999,2000 Brian King + * + * GNU Public License + * + */ #include "sysconfig.h" #include "sysdeps.h" +#include #include +#include -#include "config.h" #include "options.h" -#include "include/memory.h" +#include "memory.h" #include "custom.h" -#include "readcpu.h" #include "newcpu.h" #include "autoconf.h" #include "bsdsocket.h" +#include "osdep/exectasks.h" +#include "threaddep/thread.h" +#include "native2amiga.h" +#include "osdep/resource.h" +#include "osdep/win32gui.h" + +static HWND hSockWnd; +extern HWND hAmigaWnd; +int hWndSelector = 0; /* Set this to zero to get hSockWnd */ CRITICAL_SECTION csSigQueueLock; DWORD threadid; - +#ifdef __GNUC__ #define THREAD(func,arg) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)func,(LPVOID)arg,0,&threadid) +#else +#define THREAD(func,arg) _beginthreadex( NULL, 0, func, (void *)arg, 0, (unsigned *)&threadid ) +#endif #define SETERRNO seterrno(sb,WSAGetLastError()-WSABASEERR) #define SETHERRNO setherrno(sb,WSAGetLastError()-WSABASEERR) @@ -49,54 +60,134 @@ static HANDLE hThreads[MAX_SELECT_THREAD uae_u32 *threadargs[MAX_SELECT_THREADS]; static HANDLE hEvents[MAX_SELECT_THREADS]; -static HANDLE hConnectThread; -static HANDLE hConnectEvent, hConnectEventReply; -static void thread_connect(void); +static HANDLE hSockThread; +static HANDLE hSockReq, hSockReqHandled; +static unsigned int __stdcall sock_thread(void *); + +CRITICAL_SECTION SockThreadCS; +#define PREPARE_THREAD EnterCriticalSection( &SockThreadCS ) +#define TRIGGER_THREAD { SetEvent( hSockReq ); WaitForSingleObject( hSockReqHandled, INFINITE ); LeaveCriticalSection( &SockThreadCS ); } + +#define SOCKVER_MAJOR 2 +#define SOCKVER_MINOR 2 +int mySockStartup( void ) +{ + int result = 0; + SOCKET dummy; + DWORD lasterror; + + if (WSAStartup(MAKEWORD( SOCKVER_MAJOR, SOCKVER_MINOR ), &wsbData)) + { + lasterror = WSAGetLastError(); + + if( lasterror == WSAVERNOTSUPPORTED ) + { + char szMessage[ MAX_PATH ]; + WIN32GUI_LoadUIString( IDS_WSOCK2NEEDED, szMessage, MAX_PATH ); + gui_message( szMessage ); + } + else + write_log ( "BSDSOCK: ERROR - Unable to initialize Windows socket layer! Error code: %d\n", lasterror ); + return 0; + } + + if (LOBYTE (wsbData.wVersion) != SOCKVER_MAJOR || HIBYTE (wsbData.wVersion) != SOCKVER_MINOR ) + { + char szMessage[ MAX_PATH ]; + WIN32GUI_LoadUIString( IDS_WSOCK2NEEDED, szMessage, MAX_PATH ); + gui_message( szMessage ); -int init_socket_layer(void) -{ - SOCKET dummy; - DWORD lasterror; - - if (WSAStartup(2, &wsbData)) + return 0; + } + else + { + write_log ( "BSDSOCK: using %s\n", wsbData.szDescription ); + // make sure WSP/NSPStartup gets called from within the regular stack + // (Windows 95/98 need this) + if( ( dummy = socket( AF_INET,SOCK_STREAM,IPPROTO_TCP ) ) != INVALID_SOCKET ) { - lasterror = WSAGetLastError(); - - if (lasterror == WSAVERNOTSUPPORTED) write_log("Please upgrade to WinSock2.\n"); - else write_log("bsdsocket: ERROR: Unable to initialize Windows socket layer! Error code: %d\n",lasterror); - return 0; + closesocket( dummy ); + result = 1; + } + else + { + write_log ( "BSDSOCK: ERROR - WSPStartup/NSPStartup failed! Error code: %d\n",WSAGetLastError() ); + result = 0; } + } - InitializeCriticalSection(&csSigQueueLock); + return result; +} - // make sure WSP/NSPStartup gets called from within the regular stack - // (Windows 95/98 need this) - if ((dummy = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) != INVALID_SOCKET) closesocket(dummy); - else write_log("bsdsocket: ERROR: WSPStartup/NSPStartup failed! Error code: %d\n",WSAGetLastError()); +static int socket_layer_initialized = 0; + +int init_socket_layer(void) +{ + int result = 0; - if (hConnectThread == NULL) +#ifndef CAN_DO_STACK_MAGIC + currprefs.socket_emu = 0; +#endif + if( currprefs.socket_emu ) + { + if( ( result = mySockStartup() ) ) { - hConnectThread = THREAD(thread_connect,NULL); - hConnectEvent = CreateEvent(NULL,FALSE,FALSE,NULL); - hConnectEventReply = CreateEvent(NULL,FALSE,FALSE,NULL); + InitializeCriticalSection(&csSigQueueLock); + + if( hSockThread == NULL ) + { + InitializeCriticalSection( &SockThreadCS ); + hSockReq = CreateEvent( NULL, FALSE, FALSE, NULL ); + hSockReqHandled = CreateEvent( NULL, FALSE, FALSE, NULL ); + hSockThread = (void *)THREAD(sock_thread,NULL); + } } - - return 1; + } + + socket_layer_initialized = result; + + return result; } void deinit_socket_layer(void) { + int i; + if( currprefs.socket_emu ) + { WSACleanup(); + if( socket_layer_initialized ) + { + DeleteCriticalSection( &csSigQueueLock ); + if( hSockThread ) + { + DeleteCriticalSection( &SockThreadCS ); + CloseHandle( hSockReq ); + hSockReq = NULL; + CloseHandle( hSockReqHandled ); + WaitForSingleObject( hSockThread, INFINITE ); + CloseHandle( hSockThread ); + } + for (i = 0; i < MAX_SELECT_THREADS; i++) + { + if (hThreads[i]) + { + CloseHandle( hThreads[i] ); + } + } + } + } } +#ifdef BSDSOCKET_SUPPORTED + void locksigqueue(void) { - EnterCriticalSection(&csSigQueueLock); + EnterCriticalSection(&csSigQueueLock); } void unlocksigqueue(void) { - LeaveCriticalSection(&csSigQueueLock); + LeaveCriticalSection(&csSigQueueLock); } // Asynchronous completion notification @@ -135,8 +226,12 @@ void host_closesocketquick(int s) { BOOL true = 1; - setsockopt((SOCKET)s,SOL_SOCKET,SO_DONTLINGER,(char *)&true,sizeof(true)); - closesocket((SOCKET)s); + if( s ) + { + setsockopt((SOCKET)s,SOL_SOCKET,SO_DONTLINGER,(char *)&true,sizeof(true)); + //shutdown(s,1); + closesocket((SOCKET)s); + } } void host_sbcleanup(SB) @@ -155,6 +250,7 @@ void host_sbcleanup(SB) if (sb->mtable[i]) asyncsb[(sb->mtable[i]-0xb000)/2] = NULL; } + //shutdown(sb->sockAbort,1); closesocket(sb->sockAbort); free(sb->mtable); @@ -183,7 +279,7 @@ void sockmsg(unsigned int msg, unsigned if ((SOCKET)wParam != asyncsock[index]) { // cancel socket event - WSAAsyncSelect((SOCKET)wParam,hAmigaWnd,0,0); + WSAAsyncSelect((SOCKET)wParam,hWndSelector ? hAmigaWnd : hSockWnd,0,0); return; } @@ -235,7 +331,7 @@ void sockmsg(unsigned int msg, unsigned seterrno(sb,WSAGETASYNCERROR(lParam)-WSABASEERR); if (sb->sb_errno >= 1001 && sb->sb_errno <= 1005) setherrno(sb,sb->sb_errno-1000); else if (sb->sb_errno == 55) // ENOBUFS - write_log("bsdsocket: ERROR: Buffer overflow - %d bytes requested\n",WSAGETASYNCBUFLEN(lParam)); + write_log ("BSDSOCK: ERROR - Buffer overflow - %d bytes requested\n",WSAGETASYNCBUFLEN(lParam)); } else seterrno(sb,0); @@ -280,7 +376,7 @@ static unsigned int allocasyncmsg(SB,uae unlocksigqueue(); seterrno(sb,12); // ENOMEM - write_log("bsdsocket: ERROR: Async operation completion table overflow\n"); + write_log ("BSDSOCK: ERROR - Async operation completion table overflow\n"); return 0; } @@ -302,505 +398,690 @@ static void cancelasyncmsg(unsigned int void sockabort(SB) { - locksigqueue(); + locksigqueue(); - if (sb->hAsyncTask) - { - if (WSACancelAsyncRequest(sb->hAsyncTask)) write_log("bsdsocket: ERROR: WSACancelAsyncRequest() failed with error code %d\n",WSAGetLastError()); - sb->hAsyncTask = 0; - } + if (sb->hAsyncTask) + { + if (WSACancelAsyncRequest(sb->hAsyncTask)) + write_log ("BSDSOCK: ERROR - WSACancelAsyncRequest() failed with error code %d\n",WSAGetLastError()); + sb->hAsyncTask = 0; + } - unlocksigqueue(); + unlocksigqueue(); } // address cleaning static void prephostaddr(SOCKADDR_IN *addr) { - addr->sin_family = AF_INET; + addr->sin_family = AF_INET; } static void prepamigaaddr(struct sockaddr *realpt, int len) { - // little endian address family value to the byte sin_family member - ((char *)realpt)[1] = *((char *)realpt); - - // set size of address - *((char *)realpt) = len; + // little endian address family value to the byte sin_family member + ((char *)realpt)[1] = *((char *)realpt); + + // set size of address + *((char *)realpt) = len; } int host_socket(SB, int af, int type, int protocol) { - int sd; - SOCKET s; - unsigned long nonblocking = 1; - - TRACE(("socket(%d,%d,%d) -> ",af,type,protocol)); - - if ((s = socket(af,type,protocol)) == INVALID_SOCKET) - { - SETERRNO; - TRACE(("failed (%d)\n",sb->sb_errno)); - return -1; - } - else sd = getsd(sb,(int)s); - - sb->ftable[sd-1] = SF_BLOCKING; - ioctlsocket(s,FIONBIO,&nonblocking); - TRACE(("%d\n",sd)); + int sd; + SOCKET s; + unsigned long nonblocking = 1; + + 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)); + + if ((s = socket(af,type,protocol)) == INVALID_SOCKET) + { + SETERRNO; + TRACE(("failed (%d)\n",sb->sb_errno)); + return -1; + } + else + sd = getsd(sb,(int)s); + + sb->ftable[sd-1] = SF_BLOCKING; + ioctlsocket(s,FIONBIO,&nonblocking); + TRACE(("%d\n",sd)); - return sd; + return sd; } uae_u32 host_bind(SB, uae_u32 sd, uae_u32 name, uae_u32 namelen) { - char buf[MAXADDRLEN]; - uae_u32 success = 0; - SOCKET s; - - TRACE(("bind(%d,0x%lx,%d) -> ",sd,name,namelen)); - s = getsock(sb, sd); - - if (s != INVALID_SOCKET) - { - if (namelen <= sizeof buf) - { - memcpy(buf,get_real_address(name),namelen); - - // some Amiga programs set this field to bogus values - prephostaddr((SOCKADDR_IN *)buf); + char buf[MAXADDRLEN]; + uae_u32 success = 0; + SOCKET s; + + TRACE(("bind(%d,0x%lx,%d) -> ",sd,name,namelen)); + s = getsock(sb, sd); + + if (s != INVALID_SOCKET) + { + if (namelen <= sizeof buf) + { + memcpy(buf,get_real_address (name),namelen); + + // some Amiga programs set this field to bogus values + prephostaddr((SOCKADDR_IN *)buf); - if ((success = bind(s,(struct sockaddr *)buf,namelen)) != 0) - { - SETERRNO; - TRACE(("failed (%d)\n",sb->sb_errno)); - } - else TRACE(("OK\n")); - } - else write_log("bsdsocket: ERROR: Excessive namelen (%d) in bind()!\n",namelen); + if ((success = bind(s,(struct sockaddr *)buf,namelen)) != 0) + { + SETERRNO; + TRACE(("failed (%d)\n",sb->sb_errno)); + } + else + TRACE(("OK\n")); } + else + write_log ("BSDSOCK: ERROR - Excessive namelen (%d) in bind()!\n",namelen); + } - return success; + return success; } uae_u32 host_listen(SB, uae_u32 sd, uae_u32 backlog) { - SOCKET s; - uae_u32 success = -1; + SOCKET s; + uae_u32 success = -1; - TRACE(("listen(%d,%d) -> ",sd,backlog)); - s = getsock(sb, sd); + TRACE(("listen(%d,%d) -> ",sd,backlog)); + s = getsock(sb, sd); - if (s != INVALID_SOCKET) - { - if ((success = listen(s,backlog)) != 0) - { - SETERRNO; - TRACE(("failed (%d)\n",sb->sb_errno)); - } - else TRACE(("OK\n")); - } - - return success; + if (s != INVALID_SOCKET) + { + if ((success = listen(s,backlog)) != 0) + { + SETERRNO; + TRACE(("failed (%d)\n",sb->sb_errno)); + } + else + TRACE(("OK\n")); + } + + return success; } void host_accept(SB, uae_u32 sd, uae_u32 name, uae_u32 namelen) { - struct sockaddr *rp_name; - int hlen; - SOCKET s, s2; - int success = 0; - unsigned int wMsg; - - rp_name = (struct sockaddr *)get_real_address(name); - hlen = get_long(namelen); - TRACE(("accept(%d,%d,%d) -> ",sd,name,hlen)); + struct sockaddr *rp_name; + int hlen; + SOCKET s, s2; + int success = 0; + unsigned int wMsg; + + rp_name = (struct sockaddr *)get_real_address (name); + hlen = get_long (namelen); + TRACE(("accept(%d,%d,%d) -> ",sd,name,hlen)); + + s = (SOCKET)getsock(sb,(int)sd); + + if (s != INVALID_SOCKET) + { + BEGINBLOCKING; + + s2 = accept(s,rp_name,&hlen); + + if (s2 == INVALID_SOCKET) + { + SETERRNO; + + if (sb->ftable[sd-1] & SF_BLOCKING && sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR) + { + if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) + { + WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_ACCEPT); + + WAITSIGNAL; + + cancelasyncmsg(wMsg); + + if (sb->eintr) + { + TRACE(("[interrupted]\n")); + ENDBLOCKING; + return; + } - s = (SOCKET)getsock(sb,(int)sd); - - if (s != INVALID_SOCKET) - { - BEGINBLOCKING; - - s2 = accept(s,rp_name,&hlen); + s2 = accept(s,rp_name,&hlen); - if (s2 == INVALID_SOCKET) - { + if (s2 == INVALID_SOCKET) + { SETERRNO; - if (sb->ftable[sd-1] & SF_BLOCKING && sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR) - { - if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) - { - WSAAsyncSelect(s,hAmigaWnd,wMsg,FD_ACCEPT); - - WAITSIGNAL; - - cancelasyncmsg(wMsg); - - if (sb->eintr) - { - TRACE(("[interrupted]\n")); - ENDBLOCKING; - return; - } - - s2 = accept(s,rp_name,&hlen); - - if (s2 == INVALID_SOCKET) - { - SETERRNO; - - if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR) write_log("bsdsocket: ERRRO: accept() would block despite FD_ACCEPT message\n"); - } - } - } + if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR) write_log ("BSDSOCK: ERRRO - accept() would block despite FD_ACCEPT message\n"); + } } + } + } - if (s2 == INVALID_SOCKET) - { - sb->resultval = -1; - TRACE(("failed (%d)\n",sb->sb_errno)); - } - else - { - sb->resultval = getsd(sb, s2); - sb->ftable[sb->resultval-1] = sb->ftable[sd-1]; // new socket inherits the old socket's properties + if (s2 == INVALID_SOCKET) + { + sb->resultval = -1; + TRACE(("failed (%d)\n",sb->sb_errno)); + } + else + { + sb->resultval = getsd(sb, s2); + sb->ftable[sb->resultval-1] = sb->ftable[sd-1]; // new socket inherits the old socket's properties - prepamigaaddr(rp_name,hlen); - put_long(namelen,hlen); - TRACE(("%d/%d\n",sb->resultval,hlen)); - } + prepamigaaddr(rp_name,hlen); + put_long (namelen,hlen); + TRACE(("%d/%d\n",sb->resultval,hlen)); + } + + ENDBLOCKING; + } +} + +typedef enum +{ + connect_req, + recvfrom_req, + sendto_req, + abort_req, + last_req +} threadsock_e; + +struct threadsock_packet +{ + threadsock_e packet_type; + union + { + struct sendto_params + { + char *buf; + char *realpt; + uae_u32 sd; + uae_u32 msg; + uae_u32 len; + uae_u32 flags; + uae_u32 to; + uae_u32 tolen; + } sendto_s; + struct recvfrom_params + { + char *realpt; + uae_u32 addr; + uae_u32 len; + uae_u32 flags; + struct sockaddr *rp_addr; + int *hlen; + } recvfrom_s; + struct connect_params + { + char *buf; + uae_u32 namelen; + } connect_s; + struct abort_params + { + SOCKET *newsock; + } abort_s; + } params; + SOCKET s; + SB; +} sockreq; + +BOOL HandleStuff( void ) +{ + BOOL quit = FALSE; + SB = NULL; + BOOL handled = TRUE; + + if( hSockReq ) + { + // 100ms sleepiness might need some tuning... + if( WaitForSingleObject( hSockReq, 100 ) == WAIT_OBJECT_0 ) + { + switch( sockreq.packet_type ) + { + case connect_req: + sockreq.sb->resultval = connect(sockreq.s,(struct sockaddr *)(sockreq.params.connect_s.buf),sockreq.params.connect_s.namelen); + break; + case sendto_req: + if( sockreq.params.sendto_s.to ) + { + 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); + } + else + { + sockreq.sb->resultval = send(sockreq.s,sockreq.params.sendto_s.realpt,sockreq.params.sendto_s.len,sockreq.params.sendto_s.flags); + } + break; + case recvfrom_req: + if( sockreq.params.recvfrom_s.addr ) + { + sockreq.sb->resultval = recvfrom( sockreq.s, sockreq.params.recvfrom_s.realpt, sockreq.params.recvfrom_s.len, + sockreq.params.recvfrom_s.flags, sockreq.params.recvfrom_s.rp_addr, + sockreq.params.recvfrom_s.hlen ); + } + else + { + sockreq.sb->resultval = recv( sockreq.s, sockreq.params.recvfrom_s.realpt, sockreq.params.recvfrom_s.len, + sockreq.params.recvfrom_s.flags ); + } + break; + case abort_req: + *(sockreq.params.abort_s.newsock) = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + //shutdown( sb->sockAbort, 1 ); + closesocket(sb->sockAbort); + handled = FALSE; /* Don't bother the SETERRNO section after the switch() */ + break; + case last_req: + default: + write_log ( "BSDSOCK: Invalid sock-thread request!\n" ); + handled = FALSE; + break; + } + if( handled ) + { + if( sockreq.sb->resultval == SOCKET_ERROR ) + { + sb = sockreq.sb; + SETERRNO; + } + } + SetEvent( hSockReqHandled ); + } + } + else + { + quit = TRUE; + } + return quit; +} + +long FAR PASCAL SocketWindowProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) +{ +#ifdef BSDSOCKET_SUPPORTED + if( message >= 0xB000 && message < 0xB000+MAXPENDINGASYNC*2 ) + { +#if DEBUG_SOCKETS + write_log ( "sockmsg(0x%x, 0x%x, 0x%x)\n", message, wParam, lParam ); +#endif + sockmsg( message, wParam, lParam ); + return 0; + } +#endif - ENDBLOCKING; - } + return DefWindowProc( hwnd, message, wParam, lParam ); } -// Windows 9x workaround... Microsoft blows chunks. -volatile SOCKET connect_s; -volatile uae_u32 connect_name, connect_namelen; -struct socketbase *connect_sb; - -static void thread_connect(void) +static unsigned int __stdcall sock_thread(void *blah) { - char buf[MAXADDRLEN]; - SB; - - for (;;) - { - WaitForSingleObject(hConnectEvent,INFINITE); - - if ((sb = connect_sb) != NULL) - { - memcpy(buf,get_real_address(connect_name),connect_namelen); - prephostaddr((SOCKADDR_IN *)buf); - - if ((sb->resultval = connect(connect_s,(struct sockaddr *)buf,connect_namelen)) != 0) SETERRNO; - - connect_sb = NULL; - SetEvent(hConnectEventReply); - } - } + unsigned int result = 0; + MSG msg; + WNDCLASS wc; // Set up an invisible window and dummy wndproc + + wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW; + wc.lpfnWndProc = SocketWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = 0; + wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE( IDI_APPICON ) ); + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject (BLACK_BRUSH); + wc.lpszMenuName = 0; + wc.lpszClassName = "SocketFun"; + if( RegisterClass (&wc) ) + { + hSockWnd = CreateWindowEx ( 0, + "SocketFun", "WinUAE Socket Window", + WS_POPUP, + 0, 0, + 1, 1, + NULL, NULL, 0, NULL); + if( hSockWnd ) + { + // Make sure we're outrunning the wolves + SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL ); + + while( TRUE ) + { + if( PeekMessage( &msg, NULL, WM_USER, 0xB000+MAXPENDINGASYNC*2, PM_REMOVE ) > 0 ) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + if( HandleStuff() ) // See if its time to quit... + break; + } + } + } + write_log ( "BSDSOCK: We have exited our sock_thread()\n" ); +#ifndef __GNUC__ + _endthreadex( result ); +#endif + return result; } void host_connect(SB, uae_u32 sd, uae_u32 name, uae_u32 namelen) { - SOCKET s; - int success = 0; - unsigned int wMsg; - - TRACE(("connect(%d,0x%lx,%d) -> ",sd,name,namelen)); + SOCKET s; + int success = 0; + unsigned int wMsg; + char buf[MAXADDRLEN]; + TRACE(("connect(%d,0x%lx,%d) -> ",sd,name,namelen)); + + s = (SOCKET)getsock(sb,(int)sd); + + if (s != INVALID_SOCKET) + { + if (namelen <= MAXADDRLEN) + { + if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) + { + WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_CONNECT); - s = (SOCKET)getsock(sb,(int)sd); - - if (s != INVALID_SOCKET) - { - if (namelen <= MAXADDRLEN) - { - if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) - { - WSAAsyncSelect(s,hAmigaWnd,wMsg,FD_CONNECT); - - BEGINBLOCKING; - - connect_s = s; - connect_name = name; - connect_namelen = namelen; - connect_sb = sb; - SetEvent(hConnectEvent); - WaitForSingleObject(hConnectEventReply,INFINITE); + BEGINBLOCKING; + PREPARE_THREAD; - if (sb->resultval) - { - if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR) - { - if (sb->ftable[sd-1] & SF_BLOCKING) - { - seterrno(sb,0); - - WAITSIGNAL; - - if (sb->eintr) - { - // Destroy socket to cancel abort, replace it with fake socket to enable proper closing. - // This is in accordance with BSD behaviour. - closesocket(s); - sb->dtable[sd-1] = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); - } - } - else seterrno(sb,36); // EINPROGRESS - } - } - - ENDBLOCKING; + memcpy(buf,get_real_address (name),namelen); + prephostaddr((SOCKADDR_IN *)buf); - cancelasyncmsg(wMsg); + sockreq.packet_type = connect_req; + sockreq.s = s; + sockreq.sb = sb; + sockreq.params.connect_s.buf = buf; + sockreq.params.connect_s.namelen = namelen; + + TRIGGER_THREAD; + if (sb->resultval) + { + if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR) + { + if (sb->ftable[sd-1] & SF_BLOCKING) + { + seterrno(sb,0); + + WAITSIGNAL; + + if (sb->eintr) + { + // Destroy socket to cancel abort, replace it with fake socket to enable proper closing. + // This is in accordance with BSD behaviour. + //shutdown(s,1); + closesocket(s); + sb->dtable[sd-1] = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + } } + else + seterrno(sb,36); // EINPROGRESS + } } - else write_log("bsdsock: WARNING: Excessive namelen (%d) in connect()!\n",namelen); + + ENDBLOCKING; + + cancelasyncmsg(wMsg); + } } + else + write_log ("BSDSOCK: WARNING - Excessive namelen (%d) in connect()!\n",namelen); + } - TRACE(("%d\n",sb->sb_errno)); + TRACE(("%d\n",sb->sb_errno)); } -// @@@ move sendto() to an extra thread to make UDP-based apps work under Windows 9x void host_sendto(SB, uae_u32 sd, uae_u32 msg, uae_u32 len, uae_u32 flags, uae_u32 to, uae_u32 tolen) { - SOCKET s; - char *realpt; - unsigned int wMsg; - char buf[MAXADDRLEN]; + SOCKET s; + char *realpt; + unsigned int wMsg; + char buf[MAXADDRLEN]; #ifdef TRACING_ENABLED - if (to) TRACE(("sendto(%d,0x%lx,%d,0x%lx,0x%lx,%d) -> ",sd,msg,len,flags,to,tolen)) - else TRACE(("send(%d,0x%lx,%d,%d) -> ",sd,msg,len,flags)); + if (to) TRACE(("sendto(%d,0x%lx,%d,0x%lx,0x%lx,%d) -> ",sd,msg,len,flags,to,tolen)) + else TRACE(("send(%d,0x%lx,%d,%d) -> ",sd,msg,len,flags)); #endif - s = getsock(sb,sd); + s = getsock(sb,sd); - if (s != INVALID_SOCKET) - { - realpt = get_real_address(msg); + if (s != INVALID_SOCKET) + { + realpt = get_real_address (msg); - if (to) - { - if (tolen > sizeof buf) write_log("bsdsocket: WARNING: Target address in sendto() too large (%d)!\n",tolen); - else - { - memcpy(buf,get_real_address(to),tolen); - // some Amiga software sets this field to bogus values - prephostaddr((SOCKADDR_IN *)buf); - } - } + if (to) + { + if (tolen > sizeof buf) write_log ("BSDSOCK: WARNING - Target address in sendto() too large (%d)!\n",tolen); + else + { + memcpy(buf,get_real_address (to),tolen); + // some Amiga software sets this field to bogus values + prephostaddr((SOCKADDR_IN *)buf); + } + } - BEGINBLOCKING; + BEGINBLOCKING; - for (;;) - { - sb->resultval = to ? sendto(s,realpt,len,flags,(struct sockaddr *)buf,tolen) : send(s,realpt,len,flags); - - if (sb->resultval == -1) - { - SETERRNO; - if (sb->sb_errno != WSAEWOULDBLOCK-WSABASEERR || !(sb->ftable[sd-1] & SF_BLOCKING)) break; - } - else - { - realpt += sb->resultval; - len -= sb->resultval; - - if (len <= 0) break; - else continue; - } + for (;;) + { + PREPARE_THREAD; - if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) - { - WSAAsyncSelect(s,hAmigaWnd,wMsg,FD_WRITE); + sockreq.packet_type = sendto_req; + sockreq.s = s; + sockreq.sb = sb; + sockreq.params.sendto_s.realpt = realpt; + sockreq.params.sendto_s.buf = buf; + sockreq.params.sendto_s.sd = sd; + sockreq.params.sendto_s.msg = msg; + sockreq.params.sendto_s.len = len; + sockreq.params.sendto_s.flags = flags; + sockreq.params.sendto_s.to = to; + sockreq.params.sendto_s.tolen = tolen; + + TRIGGER_THREAD; + if (sb->resultval == -1) + { + if (sb->sb_errno != WSAEWOULDBLOCK-WSABASEERR || !(sb->ftable[sd-1] & SF_BLOCKING)) break; + } + else + { + realpt += sb->resultval; + len -= sb->resultval; + + if (len <= 0) break; + else continue; + } + + if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) + { + WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_WRITE); - WAITSIGNAL; - - cancelasyncmsg(wMsg); - - if (sb->eintr) - { - TRACE(("[interrupted]\n")); - return; - } - } - else break; + WAITSIGNAL; + + cancelasyncmsg(wMsg); + + if (sb->eintr) + { + TRACE(("[interrupted]\n")); + return; } - - ENDBLOCKING; + } + else break; } - else sb->resultval = -1; + + ENDBLOCKING; + } + else sb->resultval = -1; #ifdef TRACING_ENABLED - if (sb->resultval == -1) TRACE(("failed (%d)\n",sb->sb_errno)) - else TRACE(("%d\n",sb->resultval)); + if (sb->resultval == -1) TRACE(("failed (%d)\n",sb->sb_errno)) + else TRACE(("%d\n",sb->resultval)); #endif } void host_recvfrom(SB, uae_u32 sd, uae_u32 msg, uae_u32 len, uae_u32 flags, uae_u32 addr, uae_u32 addrlen) { - SOCKET s; - char *realpt; - struct sockaddr *rp_addr = NULL; - int hlen; - char buf[MAXADDRLEN]; - unsigned int wMsg; + SOCKET s; + char *realpt; + struct sockaddr *rp_addr = NULL; + int hlen; + unsigned int wMsg; #ifdef TRACING_ENABLED - if (addr) TRACE(("recvfrom(%d,0x%lx,%d,0x%lx,0x%lx,0x%lx) -> ",sd,msg,len,flags,addr,addrlen)) - else TRACE(("recv(%d,0x%lx,%d,0x%lx) -> ",sd,msg,len,flags)); + if (addr) TRACE(("recvfrom(%d,0x%lx,%d,0x%lx,0x%lx,%d) -> ",sd,msg,len,flags,addr,get_long (addrlen))) + else TRACE(("recv(%d,0x%lx,%d,0x%lx) -> ",sd,msg,len,flags)); #endif - s = getsock(sb,sd); + s = getsock(sb,sd); - if (s != INVALID_SOCKET) + if (s != INVALID_SOCKET) + { + realpt = get_real_address (msg); + + if (addr) { - realpt = get_real_address(msg); + hlen = get_long (addrlen); + rp_addr = (struct sockaddr *)get_real_address (addr); + } - if (addr) - { - hlen = get_long(addrlen); - rp_addr = (struct sockaddr *)get_real_address(addr); - } + BEGINBLOCKING; - BEGINBLOCKING; + for (;;) + { + PREPARE_THREAD; + + sockreq.packet_type = recvfrom_req; + sockreq.s = s; + sockreq.sb = sb; + sockreq.params.recvfrom_s.addr = addr; + sockreq.params.recvfrom_s.flags = flags; + sockreq.params.recvfrom_s.hlen = &hlen; + sockreq.params.recvfrom_s.len = len; + sockreq.params.recvfrom_s.realpt = realpt; + sockreq.params.recvfrom_s.rp_addr = rp_addr; - for (;;) + TRIGGER_THREAD; + if (sb->resultval == -1) + { + if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR && sb->ftable[sd-1] & SF_BLOCKING) { - sb->resultval = addr ? recvfrom(s,realpt,len,flags,rp_addr,&hlen) : recv(s,realpt,len,flags); + if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) + { + WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_READ); - if (sb->resultval == -1) + WAITSIGNAL; + + cancelasyncmsg(wMsg); + + if (sb->eintr) { - SETERRNO; - - if (sb->sb_errno == WSAEWOULDBLOCK-WSABASEERR && sb->ftable[sd-1] & SF_BLOCKING) - { - if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) - { - WSAAsyncSelect(s,hAmigaWnd,wMsg,FD_READ); - - WAITSIGNAL; - - cancelasyncmsg(wMsg); - - if (sb->eintr) - { - TRACE(("[interrupted]\n")); - return; - } - } - else break; - } - else break; + TRACE(("[interrupted]\n")); + return; } - else break; + } + else break; } - - ENDBLOCKING; + else break; + } + else break; + } + + ENDBLOCKING; - if (addr) - { - prepamigaaddr(rp_addr,hlen); - put_long(addrlen,hlen); - } + if (addr) + { + prepamigaaddr(rp_addr,hlen); + put_long (addrlen,hlen); } - else sb->resultval = -1; + } + else sb->resultval = -1; #ifdef TRACING_ENABLED - if (sb->resultval == -1) TRACE(("failed (%d)\n",sb->sb_errno)) - else TRACE(("%d\n",sb->resultval)); + if (sb->resultval == -1) TRACE(("failed (%d)\n",sb->sb_errno)) + else TRACE(("%d\n",sb->resultval)); #endif } uae_u32 host_shutdown(SB, uae_u32 sd, uae_u32 how) { - SOCKET s; - - TRACE(("shutdown(%d,%d) -> ",sd,how)); - - s = getsock(sb,sd); - - if (s != INVALID_SOCKET) + SOCKET s; + + TRACE(("shutdown(%d,%d) -> ",sd,how)); + + s = getsock(sb,sd); + + if (s != INVALID_SOCKET) + { + if (shutdown(s,how)) { - if (shutdown(s,how)) - { - SETERRNO; - TRACE(("failed (%d)\n",sb->sb_errno)); - } - else - { - TRACE(("OK\n")); - return 0; - } + SETERRNO; + TRACE(("failed (%d)\n",sb->sb_errno)); + } + else + { + TRACE(("OK\n")); + return 0; } + } - return -1; + return -1; } void host_setsockopt(SB, uae_u32 sd, uae_u32 level, uae_u32 optname, uae_u32 optval, uae_u32 len) { - SOCKET s; - char buf[MAXADDRLEN]; + SOCKET s; + char buf[MAXADDRLEN]; - TRACE(("setsockopt(%d,%d,0x%lx,0x%lx,%d) -> ",sd,(short)level,optname,optval,len)); + TRACE(("setsockopt(%d,%d,0x%lx,0x%lx,%d) -> ",sd,(short)level,optname,optval,len)); - s = getsock(sb,sd); + s = getsock(sb,sd); - if (s != INVALID_SOCKET) + if (s != INVALID_SOCKET) + { + if (len > sizeof buf) { - if (len > sizeof buf) - { - write_log("bsdsocket: WARNING: Excessive optlen in setsockopt() (%d)\n",len); - len = sizeof buf; - } - - if (level == SOL_SOCKET && optname == SO_LINGER) - { - ((LINGER *)buf)->l_onoff = get_long(optval); - ((LINGER *)buf)->l_linger = get_long(optval+4); - } - else - { - if (len == 4) *(long *)buf = get_long(optval); - else if (len == 2) *(short *)buf = get_word(optval); - else write_log("bsdsocket: ERROR: Unknown optlen (%d) in setsockopt(%d,%d)\n",level,optname); - } - - // handle SO_EVENTMASK - if (level == 0xffff && optname == 0x2001) - { - long wsbevents = 0; - uae_u32 eventflags = get_long(optval); - - sb->ftable[sd-1] = (sb->ftable[sd-1] & ~REP_ALL) | (eventflags & REP_ALL); - - if (eventflags & REP_ACCEPT) wsbevents |= FD_ACCEPT; - if (eventflags & REP_CONNECT) wsbevents |= FD_CONNECT; - if (eventflags & REP_OOB) wsbevents |= FD_OOB; - if (eventflags & REP_READ) wsbevents |= FD_READ; - if (eventflags & REP_WRITE) wsbevents |= FD_WRITE; - if (eventflags & REP_CLOSE) wsbevents |= FD_CLOSE; - - if (sb->mtable[sd-1] || (sb->mtable[sd-1] = allocasyncmsg(sb,sd,s))) - { - WSAAsyncSelect(s,hAmigaWnd,sb->mtable[sd-1],wsbevents); - sb->resultval = 0; - } - else sb->resultval = -1; - } - else sb->resultval = setsockopt(s,level,optname,buf,len); + write_log ("BSDSOCK: WARNING - Excessive optlen in setsockopt() (%d)\n",len); + len = sizeof buf; + } - if (!sb->resultval) - { - TRACE(("OK\n")); - return; - } - else SETERRNO; + if (level == SOL_SOCKET && optname == SO_LINGER) + { + ((LINGER *)buf)->l_onoff = get_long (optval); + ((LINGER *)buf)->l_linger = get_long (optval+4); + } + else + { + if (len == 4) *(long *)buf = get_long (optval); + else if (len == 2) *(short *)buf = get_word (optval); + else write_log ("BSDSOCK: ERROR - Unknown optlen (%d) in setsockopt(%d,%d)\n",level,optname); + } + + // handle SO_EVENTMASK + if (level == 0xffff && optname == 0x2001) + { + long wsbevents = 0; + uae_u32 eventflags = get_long (optval); + + sb->ftable[sd-1] = (sb->ftable[sd-1] & ~REP_ALL) | (eventflags & REP_ALL); + + if (eventflags & REP_ACCEPT) wsbevents |= FD_ACCEPT; + if (eventflags & REP_CONNECT) wsbevents |= FD_CONNECT; + if (eventflags & REP_OOB) wsbevents |= FD_OOB; + if (eventflags & REP_READ) wsbevents |= FD_READ; + if (eventflags & REP_WRITE) wsbevents |= FD_WRITE; + if (eventflags & REP_CLOSE) wsbevents |= FD_CLOSE; + + if (sb->mtable[sd-1] || (sb->mtable[sd-1] = allocasyncmsg(sb,sd,s))) + { + WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,sb->mtable[sd-1],wsbevents); + sb->resultval = 0; + } + else sb->resultval = -1; + } + else sb->resultval = setsockopt(s,level,optname,buf,len); - TRACE(("failed (%d)\n",sb->sb_errno)); + if (!sb->resultval) + { + TRACE(("OK\n")); + return; } + else SETERRNO; + + TRACE(("failed (%d)\n",sb->sb_errno)); + } } uae_u32 host_getsockopt(SB, uae_u32 sd, uae_u32 level, uae_u32 optname, uae_u32 optval, uae_u32 optlen) @@ -819,17 +1100,17 @@ uae_u32 host_getsockopt(SB, uae_u32 sd, { if (level == SOL_SOCKET && optname == SO_LINGER) { - put_long(optval,((LINGER *)buf)->l_onoff); - put_long(optval+4,((LINGER *)buf)->l_linger); + put_long (optval,((LINGER *)buf)->l_onoff); + put_long (optval+4,((LINGER *)buf)->l_linger); } else { - if (len == 4) put_long(optval,*(long *)buf); - else if (len == 2) put_word(optval,*(short *)buf); - else write_log("bsdsocket: ERROR: Unknown optlen (%d) in setsockopt(%d,%d)\n",level,optname); + if (len == 4) put_long (optval,*(long *)buf); + else if (len == 2) put_word (optval,*(short *)buf); + else write_log ("BSDSOCK: ERROR - Unknown optlen (%d) in setsockopt(%d,%d)\n",level,optname); } -// put_long(optlen,len); // some programs pass the actual ength instead of a pointer to the length, so... +// put_long (optlen,len); // some programs pass the actual ength instead of a pointer to the length, so... TRACE(("OK (%d,%d)\n",len,*(long *)buf)); return 0; } @@ -849,7 +1130,7 @@ uae_u32 host_getsockname(SB, uae_u32 sd, int len; struct sockaddr *rp_name; - len = get_long(namelen); + len = get_long (namelen); TRACE(("getsockname(%d,0x%lx,%d) -> ",sd,name,len)); @@ -857,7 +1138,7 @@ uae_u32 host_getsockname(SB, uae_u32 sd, if (s != INVALID_SOCKET) { - rp_name = (struct sockaddr *)get_real_address(name); + rp_name = (struct sockaddr *)get_real_address (name); if (getsockname(s,rp_name,&len)) { @@ -868,7 +1149,7 @@ uae_u32 host_getsockname(SB, uae_u32 sd, { TRACE(("%d\n",len)); prepamigaaddr(rp_name,len); - put_long(namelen,len); + put_long (namelen,len); return 0; } } @@ -882,7 +1163,7 @@ uae_u32 host_getpeername(SB, uae_u32 sd, int len; struct sockaddr *rp_name; - len = get_long(namelen); + len = get_long (namelen); TRACE(("getpeername(%d,0x%lx,%d) -> ",sd,name,len)); @@ -890,7 +1171,7 @@ uae_u32 host_getpeername(SB, uae_u32 sd, if (s != INVALID_SOCKET) { - rp_name = (struct sockaddr *)get_real_address(name); + rp_name = (struct sockaddr *)get_real_address (name); if (getpeername(s,rp_name,&len)) { @@ -901,7 +1182,7 @@ uae_u32 host_getpeername(SB, uae_u32 sd, { TRACE(("%d\n",len)); prepamigaaddr(rp_name,len); - put_long(namelen,len); + put_long (namelen,len); return 0; } } @@ -925,7 +1206,7 @@ uae_u32 host_IoctlSocket(SB, uae_u32 sd, { case FIONBIO: TRACE(("[FIONBIO] -> ")); - if (get_long(arg)) + if (get_long (arg)) { TRACE(("nonblocking\n")); sb->ftable[sd-1] &= ~SF_BLOCKING; @@ -940,28 +1221,28 @@ uae_u32 host_IoctlSocket(SB, uae_u32 sd, case FIONREAD: ioctlsocket(s,request,(u_long *)&data); TRACE(("[FIONREAD] -> %d\n",data)); - put_long(arg,data); + put_long (arg,data); success = 0; break; case FIOASYNC: - if (get_long(arg)) + if (get_long (arg)) { sb->ftable[sd-1] |= REP_ALL; TRACE(("[FIOASYNC] -> enabled\n")); if (sb->mtable[sd-1] || (sb->mtable[sd-1] = allocasyncmsg(sb,sd,s))) { - WSAAsyncSelect(s,hAmigaWnd,sb->mtable[sd-1],FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE | FD_CLOSE); + WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,sb->mtable[sd-1],FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE | FD_CLOSE); success = 0; break; } } - else write_log(("bsdsocket: WARNING: FIOASYNC disabling unsupported.\n")); + else write_log (("BSDSOCK: WARNING - FIOASYNC disabling unsupported.\n")); success = -1; break; default: - write_log("bsdsocket: WARNING: Unknown IoctlSocket request: 0x%08lx\n",request); + write_log ("BSDSOCK: WARNING - Unknown IoctlSocket request: 0x%08lx\n",request); seterrno(sb,22); // EINVAL } } @@ -971,66 +1252,67 @@ uae_u32 host_IoctlSocket(SB, uae_u32 sd, int host_CloseSocket(SB, int sd) { - unsigned int wMsg; - SOCKET s; + unsigned int wMsg; + SOCKET s; - TRACE(("CloseSocket(%d) -> ",sd)); + TRACE(("CloseSocket(%d) -> ",sd)); - s = getsock(sb,sd); + s = getsock(sb,sd); - if (s != INVALID_SOCKET) + if (s != INVALID_SOCKET) + { + if (sb->mtable[sd-1]) { - if (sb->mtable[sd-1]) - { - asyncsb[(sb->mtable[sd-1]-0xb000)/2] = NULL; - sb->mtable[sd-1] = 0; - } + asyncsb[(sb->mtable[sd-1]-0xb000)/2] = NULL; + sb->mtable[sd-1] = 0; + } - BEGINBLOCKING; + BEGINBLOCKING; - for (;;) - { - if (!closesocket(s)) - { - releasesock(sb,sd); - TRACE(("OK\n")); - return 0; - } + for (;;) + { + //shutdown(s,1); + if (!closesocket(s)) + { + releasesock(sb,sd); + TRACE(("OK\n")); + return 0; + } - SETERRNO; - - if (sb->sb_errno != WSAEWOULDBLOCK-WSABASEERR || !(sb->ftable[sd-1] & SF_BLOCKING)) break; + SETERRNO; + + if (sb->sb_errno != WSAEWOULDBLOCK-WSABASEERR || !(sb->ftable[sd-1] & SF_BLOCKING)) break; + + if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) + { + WSAAsyncSelect(s,hWndSelector ? hAmigaWnd : hSockWnd,wMsg,FD_CLOSE); - if ((wMsg = allocasyncmsg(sb,sd,s)) != 0) - { - WSAAsyncSelect(s,hAmigaWnd,wMsg,FD_CLOSE); - - WAITSIGNAL; - - cancelasyncmsg(wMsg); - - if (sb->eintr) - { - TRACE(("[interrupted]\n")); - break; - } - } - else break; + WAITSIGNAL; + + cancelasyncmsg(wMsg); + + if (sb->eintr) + { + TRACE(("[interrupted]\n")); + break; } - - ENDBLOCKING; + } + else break; } + + ENDBLOCKING; + } - TRACE(("failed (%d)\n",sb->sb_errno)); - - return -1; + TRACE(("failed (%d)\n",sb->sb_errno)); + + return -1; } // For the sake of efficiency, we do not malloc() the fd_sets here. // 64 sockets should be enough for everyone. static void makesocktable(SB, uae_u32 fd_set_amiga, struct fd_set *fd_set_win, int nfds, SOCKET addthis) { - int i, j, maxbit; + int i, j; uae_u32 currlong, mask; SOCKET s; @@ -1049,13 +1331,13 @@ static void makesocktable(SB, uae_u32 fd if (nfds > sb->dtablesize) { - write_log("bsdsock: ERROR: select()ing more sockets (%d) than socket descriptors available (%d)!\n",nfds,sb->dtablesize); + write_log ("BSDSOCK: ERROR - select()ing more sockets (%d) than socket descriptors available (%d)!\n",nfds,sb->dtablesize); nfds = sb->dtablesize; } for (j = 0; ; j += 32, fd_set_amiga += 4) { - currlong = get_long(fd_set_amiga); + currlong = get_long (fd_set_amiga); mask = 1; @@ -1077,7 +1359,7 @@ static void makesocktable(SB, uae_u32 fd if (fd_set_win->fd_count >= FD_SETSIZE) { - write_log("bsdsock: ERROR: select()ing more sockets (%d) than the hard-coded fd_set limit (%d) - please report\n",nfds,FD_SETSIZE); + write_log ("BSDSOCK: ERROR - select()ing more sockets (%d) than the hard-coded fd_set limit (%d) - please report\n",nfds,FD_SETSIZE); return; } } @@ -1113,7 +1395,7 @@ static void makesockbitfield(SB, uae_u32 } } - put_long(fd_set_amiga,val); + put_long (fd_set_amiga,val); } } @@ -1121,81 +1403,86 @@ static void fd_zero(uae_u32 fdset, uae_u { unsigned int i; - for (i = 0; i < nfds; i += 32, fdset += 4) put_long(fdset,0); + for (i = 0; i < nfds; i += 32, fdset += 4) put_long (fdset,0); } // This seems to be the only way of implementing a cancelable WinSock2 select() call... sigh. -static void thread_WaitSelect(uae_u32 index) +static unsigned int __stdcall thread_WaitSelect(void *index2) { - long nfds; - uae_u32 readfds, writefds, exceptfds; - uae_u32 timeout; - uae_u32 sigmp; - struct fd_set readsocks, writesocks, exceptsocks; - struct timeval tv; - uae_u32 *args; - - SB; - - for (;;) - { - WaitForSingleObject(hEvents[index],INFINITE); - - if ((args = threadargs[index]) != NULL) - { - sb = (struct socketbase *)*args; - nfds = args[1]; - readfds = args[2]; - writefds = args[3]; - exceptfds = args[4]; - timeout = args[5]; - - // construct descriptor tables - makesocktable(sb,readfds,&readsocks,nfds,sb->sockAbort); - if (writefds) makesocktable(sb,writefds,&writesocks,nfds,INVALID_SOCKET); - if (exceptfds) makesocktable(sb,exceptfds,&exceptsocks,nfds,INVALID_SOCKET); - - if (timeout) - { - tv.tv_sec = get_long(timeout); - tv.tv_usec = get_long(timeout+4); - TRACE(("(timeout: %d.%06d) ",tv.tv_sec,tv.tv_usec)) - } - - TRACE(("-> ")); - - sb->resultval = select(nfds+1,&readsocks,writefds ? &writesocks : NULL,exceptfds ? &exceptsocks : NULL,timeout ? &tv : 0); - sb->needAbort = 0; - - if (sb->resultval == SOCKET_ERROR) - { - SETERRNO; - TRACE(("failed (%d) - ",sb->sb_errno)); - if (readfds) fd_zero(readfds,nfds); - if (writefds) fd_zero(writefds,nfds); - if (exceptfds) fd_zero(exceptfds,nfds); - } - else - { - if (readfds) makesockbitfield(sb,readfds,&readsocks,nfds); - if (writefds) makesockbitfield(sb,writefds,&writesocks,nfds); - if (exceptfds) makesockbitfield(sb,exceptfds,&exceptsocks,nfds); - } - - SETSIGNAL; - - threadargs[index] = NULL; - SetEvent(sb->hEvent); - } - } + uae_u32 index = (uae_u32)index2; + unsigned int result = 0; + long nfds; + uae_u32 readfds, writefds, exceptfds; + uae_u32 timeout; + struct fd_set readsocks, writesocks, exceptsocks; + struct timeval tv; + uae_u32 *args; + + SB; + + for (;;) + { + WaitForSingleObject(hEvents[index],INFINITE); + + if ((args = threadargs[index]) != NULL) + { + sb = (struct socketbase *)*args; + nfds = args[1]; + readfds = args[2]; + writefds = args[3]; + exceptfds = args[4]; + timeout = args[5]; + + // construct descriptor tables + makesocktable(sb,readfds,&readsocks,nfds,sb->sockAbort); + if (writefds) makesocktable(sb,writefds,&writesocks,nfds,INVALID_SOCKET); + if (exceptfds) makesocktable(sb,exceptfds,&exceptsocks,nfds,INVALID_SOCKET); + + if (timeout) + { + tv.tv_sec = get_long (timeout); + tv.tv_usec = get_long (timeout+4); + TRACE(("(timeout: %d.%06d) ",tv.tv_sec,tv.tv_usec)) + } + + TRACE(("-> ")); + + sb->resultval = select(nfds+1,&readsocks,writefds ? &writesocks : NULL,exceptfds ? &exceptsocks : NULL,timeout ? &tv : 0); + sb->needAbort = 0; + + if (sb->resultval == SOCKET_ERROR) + { + SETERRNO; + TRACE(("failed (%d) - ",sb->sb_errno)); + if (readfds) fd_zero(readfds,nfds); + if (writefds) fd_zero(writefds,nfds); + if (exceptfds) fd_zero(exceptfds,nfds); + } + else + { + if (readfds) makesockbitfield(sb,readfds,&readsocks,nfds); + if (writefds) makesockbitfield(sb,writefds,&writesocks,nfds); + if (exceptfds) makesockbitfield(sb,exceptfds,&exceptsocks,nfds); + } + + SETSIGNAL; + + threadargs[index] = NULL; + SetEvent(sb->hEvent); + } + } +#ifndef __GNUC__ + _endthreadex( result ); +#endif + return result; } -void __stdcall host_WaitSelect(SB, uae_u32 nfds, uae_u32 readfds, uae_u32 writefds, uae_u32 exceptfds, uae_u32 timeout, uae_u32 sigmp) +void host_WaitSelect(SB, uae_u32 nfds, uae_u32 readfds, uae_u32 writefds, uae_u32 exceptfds, uae_u32 timeout, uae_u32 sigmp) { uae_u32 sigs, wssigs; int i; - wssigs = sigmp ? get_long(sigmp) : 0; + wssigs = sigmp ? get_long (sigmp) : 0; TRACE(("WaitSelect(%d,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx) ",nfds,readfds,writefds,exceptfds,timeout,wssigs)); @@ -1208,14 +1495,14 @@ void __stdcall host_WaitSelect(SB, uae_u if (wssigs) { - m68k_dreg(regs,0) = 0; - m68k_dreg(regs,1) = wssigs; - sigs = CallLib(get_long(4),-0x132) & wssigs; // SetSignal() + m68k_dreg (regs,0) = 0; + m68k_dreg (regs,1) = wssigs; + sigs = CallLib (get_long (4),-0x132) & wssigs; // SetSignal() if (sigs) { TRACE(("-> [preempted by signals 0x%08lx]\n",sigs & wssigs)); - put_long(sigmp,sigs & wssigs); + put_long (sigmp,sigs & wssigs); fd_zero(readfds,nfds); fd_zero(writefds,nfds); fd_zero(exceptfds,nfds); @@ -1233,24 +1520,27 @@ void __stdcall host_WaitSelect(SB, uae_u if (i >= MAX_SELECT_THREADS) { - for (i = 0; i < MAX_SELECT_THREADS; i++) if (!hThreads[i]) - { - if ((hEvents[i] = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL || (hThreads[i] = THREAD(thread_WaitSelect,i)) == NULL) - { - hThreads[i] = 0; - write_log("bsdsocket: ERROR: Thread/Event creation failed - error code: %d\n",GetLastError()); - seterrno(sb,12); // ENOMEM - sb->resultval = -1; - return; - } - - // this should improve responsiveness - SetThreadPriority(hThreads[i],THREAD_PRIORITY_TIME_CRITICAL); - break; + for (i = 0; i < MAX_SELECT_THREADS; i++) + { + if (!hThreads[i]) + { + if ((hEvents[i] = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL || (hThreads[i] = (void *)THREAD(thread_WaitSelect,i)) == NULL) + { + hThreads[i] = 0; + write_log ("BSDSOCK: ERROR - Thread/Event creation failed - error code: %d\n",GetLastError()); + seterrno(sb,12); // ENOMEM + sb->resultval = -1; + return; + } + + // this should improve responsiveness + SetThreadPriority(hThreads[i],THREAD_PRIORITY_TIME_CRITICAL); + break; } + } } - if (i >= MAX_SELECT_THREADS) write_log("bsdsocket: ERROR: Too many select()s\n"); + if (i >= MAX_SELECT_THREADS) write_log ("BSDSOCK: ERROR - Too many select()s\n"); else { SOCKET newsock = INVALID_SOCKET; @@ -1259,14 +1549,14 @@ void __stdcall host_WaitSelect(SB, uae_u SetEvent(hEvents[i]); - m68k_dreg(regs,0) = (((uae_u32)1)<signal)|sb->eintrsigs|wssigs; - sigs = CallLib(get_long(4),-0x13e); // Wait() + m68k_dreg (regs,0) = (((uae_u32)1)<signal)|sb->eintrsigs|wssigs; + sigs = CallLib (get_long (4),-0x13e); // Wait() if (sb->needAbort) { if ((newsock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET) - write_log("bsdsocket: ERROR: Cannot create socket: %d\n",WSAGetLastError()); - + write_log ("BSDSOCK: ERROR - Cannot create socket: %d\n",WSAGetLastError()); + //shutdown(sb->sockAbort,1); closesocket(sb->sockAbort); } @@ -1276,20 +1566,23 @@ void __stdcall host_WaitSelect(SB, uae_u if (newsock != INVALID_SOCKET) sb->sockAbort = newsock; - put_long(sigmp,sigs & wssigs); + if( sigmp ) + { + put_long (sigmp,sigs & wssigs); - if (sigs & sb->eintrsigs) - { - TRACE(("[interrupted]\n")); - sb->resultval = -1; - seterrno(sb,4); // EINTR - } - else if (sigs & wssigs) - { - TRACE(("[interrupted by signals 0x%08lx]\n",sigs & wssigs)); - sb->resultval = 0; - seterrno(sb,0); - } + if (sigs & sb->eintrsigs) + { + TRACE(("[interrupted]\n")); + sb->resultval = -1; + seterrno(sb,4); // EINTR + } + else if (sigs & wssigs) + { + TRACE(("[interrupted by signals 0x%08lx]\n",sigs & wssigs)); + sb->resultval = 0; + seterrno(sb,0); + } + } else TRACE(("%d\n",sb->resultval)); } } @@ -1306,7 +1599,7 @@ uae_u32 host_Inet_NtoA(SB, uae_u32 in) if ((addr = inet_ntoa(ina)) != NULL) { - scratchbuf = m68k_areg(regs,6)+offsetof(struct UAEBSDBase,scratchbuf); + scratchbuf = m68k_areg (regs,6)+offsetof(struct UAEBSDBase,scratchbuf); strncpyha(scratchbuf,addr,SCRATCHBUFSIZE); TRACE(("%s\n",addr)); return scratchbuf; @@ -1323,7 +1616,7 @@ uae_u32 host_inet_addr(uae_u32 cp) uae_u32 addr; char *cp_rp; - cp_rp = get_real_address(cp); + cp_rp = get_real_address (cp); addr = htonl(inet_addr(cp_rp)); @@ -1336,7 +1629,7 @@ void host_gethostbynameaddr(SB, uae_u32 { HOSTENT *h; int size, numaliases = 0, numaddr = 0; - uae_u32 aptr, asize; + uae_u32 aptr; char *name_rp; int i; uae_u32 addr; @@ -1345,7 +1638,7 @@ void host_gethostbynameaddr(SB, uae_u32 char buf[MAXGETHOSTSTRUCT]; unsigned int wMsg = 0; - name_rp = get_real_address(name); + name_rp = get_real_address (name); if (addrtype == -1) { @@ -1373,7 +1666,7 @@ void host_gethostbynameaddr(SB, uae_u32 if ((wMsg = allocasyncmsg(sb,0,INVALID_SOCKET)) != 0) { - if ((sb->hAsyncTask = addrtype == -1 ? WSAAsyncGetHostByName(hAmigaWnd,wMsg,name_rp,buf,sizeof buf) : WSAAsyncGetHostByAddr(hAmigaWnd,wMsg,name_rp,namelen,addrtype,buf,sizeof buf)) != NULL) + 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) { while (sb->hAsyncTask) WAITSIGNAL; @@ -1399,18 +1692,14 @@ kludge: if (sb->hostent) { - m68k_areg(regs,1) = sb->hostent; - m68k_dreg(regs,0) = sb->hostentsize; - CallLib(get_long(4),-0xd2); // FreeMem() + uae_FreeMem( sb->hostent, sb->hostentsize ); } - - m68k_dreg(regs,0) = size; - m68k_dreg(regs,1) = 0; - sb->hostent = CallLib(get_long(4),-0xc6); // AllocMem() + + sb->hostent = uae_AllocMem( size, 0 ); if (!sb->hostent) { - write_log("bsdsocket: 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); + 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); seterrno(sb,12); // ENOMEM return; } @@ -1420,16 +1709,16 @@ kludge: aptr = sb->hostent+28+numaliases*4+numaddr*4; // transfer hostent to Amiga memory - put_long(sb->hostent+4,sb->hostent+20); - put_long(sb->hostent+8,h->h_addrtype); - put_long(sb->hostent+12,h->h_length); - put_long(sb->hostent+16,sb->hostent+24+numaliases*4); + put_long (sb->hostent+4,sb->hostent+20); + put_long (sb->hostent+8,h->h_addrtype); + put_long (sb->hostent+12,h->h_length); + put_long (sb->hostent+16,sb->hostent+24+numaliases*4); - for (i = 0; i < numaliases; i++) put_long(sb->hostent+20+i*4,addstr(&aptr,h->h_aliases[i])); - put_long(sb->hostent+20+numaliases*4,0); - for (i = 0; i < numaddr; i++) put_long(sb->hostent+24+(numaliases+i)*4,addmem(&aptr,h->h_addr_list[i],h->h_length)); - put_long(sb->hostent+24+numaliases*4+numaddr*4,0); - put_long(sb->hostent,aptr); + for (i = 0; i < numaliases; i++) put_long (sb->hostent+20+i*4,addstr(&aptr,h->h_aliases[i])); + put_long (sb->hostent+20+numaliases*4,0); + for (i = 0; i < numaddr; i++) put_long (sb->hostent+24+(numaliases+i)*4,addmem(&aptr,h->h_addr_list[i],h->h_length)); + put_long (sb->hostent+24+numaliases*4+numaddr*4,0); + put_long (sb->hostent,aptr); addstr(&aptr,h->h_name); TRACE(("OK (%s)\n",h->h_name)); @@ -1443,7 +1732,7 @@ kludge: else { seterrno(sb,12); // ENOMEM - well... - write_log("bsdsocket: ERROR: WSAAsyncGetHostBy%s() failed - error code: %d\n",addrtype == -1 ? "Name" : "Addr",WSAGetLastError()); + write_log ("BSDSOCK: ERROR - WSAAsyncGetHostBy%s() failed - error code: %d\n",addrtype == -1 ? "Name" : "Addr",WSAGetLastError()); } if (wMsg) cancelasyncmsg(wMsg); @@ -1454,14 +1743,14 @@ void host_getservbynameport(SB, uae_u32 { SERVENT *s; int size, numaliases = 0; - uae_u32 aptr, asize; + uae_u32 aptr; char *name_rp = NULL, *proto_rp = NULL; int i; char buf[MAXGETHOSTSTRUCT]; unsigned int wMsg; - if (proto) proto_rp = get_real_address(proto); + if (proto) proto_rp = get_real_address (proto); if (type) { @@ -1469,13 +1758,13 @@ void host_getservbynameport(SB, uae_u32 } else { - name_rp = get_real_address(nameport); + name_rp = get_real_address (nameport); TRACE(("getservbyname(%s,%s) -> ",name_rp,proto_rp ? proto_rp : "NULL")); } if ((wMsg = allocasyncmsg(sb,0,INVALID_SOCKET)) != 0) { - if ((sb->hAsyncTask = type ? WSAAsyncGetServByPort(hAmigaWnd,wMsg,nameport,proto_rp,buf,sizeof buf) : WSAAsyncGetServByName(hAmigaWnd,wMsg,name_rp,proto_rp,buf,sizeof buf)) != NULL) + 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) { while (sb->hAsyncTask) WAITSIGNAL; @@ -1495,18 +1784,14 @@ void host_getservbynameport(SB, uae_u32 if (sb->servent) { - m68k_areg(regs,1) = sb->servent; - m68k_dreg(regs,0) = sb->serventsize; - CallLib(get_long(4),-0xd2); // FreeMem() + uae_FreeMem( sb->servent, sb->serventsize ); } - m68k_dreg(regs,0) = size; - m68k_dreg(regs,1) = 0; - sb->servent = CallLib(get_long(4),-0xc6); // AllocMem() + sb->servent = uae_AllocMem( size, 0 ); if (!sb->servent) { - write_log("bsdsocket: WARNING: getservby%s() ran out of Amiga memory (couldn't allocate %ld bytes)\n",type ? "port" : "name",size); + write_log ("BSDSOCK: WARNING - getservby%s() ran out of Amiga memory (couldn't allocate %ld bytes)\n",type ? "port" : "name",size); seterrno(sb,12); // ENOMEM return; } @@ -1516,14 +1801,14 @@ void host_getservbynameport(SB, uae_u32 aptr = sb->servent+20+numaliases*4; // transfer servent to Amiga memory - put_long(sb->servent+4,sb->servent+16); - put_long(sb->servent+8,(unsigned short)htons(s->s_port)); + put_long (sb->servent+4,sb->servent+16); + put_long (sb->servent+8,(unsigned short)htons(s->s_port)); - for (i = 0; i < numaliases; i++) put_long(sb->servent+16+i*4,addstr(&aptr,s->s_aliases[i])); - put_long(sb->servent+16+numaliases*4,0); - put_long(sb->servent,aptr); + for (i = 0; i < numaliases; i++) put_long (sb->servent+16+i*4,addstr(&aptr,s->s_aliases[i])); + put_long (sb->servent+16+numaliases*4,0); + put_long (sb->servent,aptr); addstr(&aptr,s->s_name); - put_long(sb->servent+12,aptr); + put_long (sb->servent+12,aptr); addstr(&aptr,s->s_proto); TRACE(("OK (%s, %d)\n",s->s_name,(unsigned short)htons(s->s_port))); @@ -1537,7 +1822,7 @@ void host_getservbynameport(SB, uae_u32 else { seterrno(sb,12); // ENOMEM - well... - write_log("bsdsocket: ERROR: WSAAsyncGetServBy%s() failed - error code: %d\n",type ? "Port" : "Name",WSAGetLastError()); + write_log ("BSDSOCK: ERROR - WSAAsyncGetServBy%s() failed - error code: %d\n",type ? "Port" : "Name",WSAGetLastError()); } cancelasyncmsg(wMsg); @@ -1548,20 +1833,20 @@ void host_getprotobyname(SB, uae_u32 nam { PROTOENT *p; int size, numaliases = 0; - uae_u32 aptr, asize; + uae_u32 aptr; char *name_rp; int i; char buf[MAXGETHOSTSTRUCT]; unsigned int wMsg; - name_rp = get_real_address(name); + name_rp = get_real_address (name); TRACE(("getprotobyname(%s) -> ",name_rp)); if ((wMsg = allocasyncmsg(sb,0,INVALID_SOCKET)) != 0) { - if ((sb->hAsyncTask = WSAAsyncGetProtoByName(hAmigaWnd,wMsg,name_rp,buf,sizeof buf)) != NULL) + if ((sb->hAsyncTask = WSAAsyncGetProtoByName(hWndSelector ? hAmigaWnd : hSockWnd,wMsg,name_rp,buf,sizeof buf)) != NULL) { while (sb->hAsyncTask) WAITSIGNAL; @@ -1580,18 +1865,14 @@ void host_getprotobyname(SB, uae_u32 nam if (sb->protoent) { - m68k_areg(regs,1) = sb->protoent; - m68k_dreg(regs,0) = sb->protoentsize; - CallLib(get_long(4),-0xd2); // FreeMem() + uae_FreeMem( sb->protoent, sb->protoentsize ); } - m68k_dreg(regs,0) = size; - m68k_dreg(regs,1) = 0; - sb->protoent = CallLib(get_long(4),-0xc6); // AllocMem() + sb->protoent = uae_AllocMem( size, 0 ); if (!sb->protoent) { - write_log("bsdsocket: WARNING: getprotobyname() ran out of Amiga memory (couldn't allocate %ld bytes) while returning result of lookup for '%s'\n",size,(char *)name); + 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); seterrno(sb,12); // ENOMEM return; } @@ -1601,12 +1882,12 @@ void host_getprotobyname(SB, uae_u32 nam aptr = sb->protoent+16+numaliases*4; // transfer protoent to Amiga memory - put_long(sb->protoent+4,sb->protoent+12); - put_long(sb->protoent+8,p->p_proto); + put_long (sb->protoent+4,sb->protoent+12); + put_long (sb->protoent+8,p->p_proto); - for (i = 0; i < numaliases; i++) put_long(sb->protoent+12+i*4,addstr(&aptr,p->p_aliases[i])); - put_long(sb->protoent+12+numaliases*4,0); - put_long(sb->protoent,aptr); + for (i = 0; i < numaliases; i++) put_long (sb->protoent+12+i*4,addstr(&aptr,p->p_aliases[i])); + put_long (sb->protoent+12+numaliases*4,0); + put_long (sb->protoent,aptr); addstr(&aptr,p->p_name); TRACE(("OK (%s, %d)\n",p->p_name,p->p_proto)); seterrno(sb,0); @@ -1619,7 +1900,7 @@ void host_getprotobyname(SB, uae_u32 nam else { seterrno(sb,12); // ENOMEM - well... - write_log("bsdsocket: ERROR: WSAAsyncGetProtoByName() failed - error code: %d\n",WSAGetLastError()); + write_log ("BSDSOCK: ERROR - WSAAsyncGetProtoByName() failed - error code: %d\n",WSAGetLastError()); } cancelasyncmsg(wMsg); @@ -1628,5 +1909,7 @@ void host_getprotobyname(SB, uae_u32 nam uae_u32 host_gethostname(uae_u32 name, uae_u32 namelen) { - return gethostname(get_real_address(name),namelen); + return gethostname(get_real_address (name),namelen); } + +#endif