Annotation of uae/src/od-win32/bsdsock.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.