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

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

unix.superglobalmegacorp.com

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