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

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

unix.superglobalmegacorp.com

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