Annotation of quake1/net_ipx.c, revision 1.1.1.2

1.1       root        1: // net_ipx.c
                      2: 
                      3: #include <stdio.h>
                      4: #include <stdlib.h>
                      5: #include <dpmi.h>
                      6: 
                      7: #include "quakedef.h"
                      8: #include "dosisms.h"
                      9: #include "net_ipx.h"
                     10: 
1.1.1.2 ! root       11: #define        DEFAULTnet_hostport     26000
        !            12: 
1.1       root       13: #define        EIO                             5       /* I/O error */
                     14: 
                     15: #define AF_NETWARE             64
                     16: 
                     17: #define IPX_OPEN                                       0
                     18: #define IPX_CLOSE                                      1
                     19: #define IPX_GETROUTE                           2
                     20: #define IPX_SEND                                       3
                     21: #define IPX_LISTEN                                     4
                     22: #define IPX_SCHEDULEEVENT                      5
                     23: #define IPX_CANCEL                                     6
                     24: #define IPX_SCHEDULESPECIALEVENT       7
                     25: #define IPX_GETINTERVALMARKER          8
                     26: #define IPX_GETADDRESS                         9
                     27: #define IPX_RELINQUISH                         10
                     28: 
                     29: #define PTYPE_UNKNOWN                          0
                     30: #define PTYPE_RIP                                      1
                     31: #define PTYPE_ECHO                                     2
                     32: #define PTYPE_ERROR                                    3
                     33: #define PTYPE_IPX                                      4
                     34: #define PTYPE_SPX                                      5
                     35: 
                     36: #pragma pack(1)
                     37: 
                     38: typedef struct
                     39: {
                     40:        byte    network[4];
                     41:        byte    node[6];
                     42:        short   socket;
                     43: } IPXaddr;
                     44: 
                     45: struct sockaddr_ipx
                     46: {
                     47:     short                      sipx_family;
                     48:        IPXaddr                 sipx_addr;
                     49:     char                       sipx_zero[2];
                     50: };
                     51: #define sipx_port sipx_addr.socket
                     52: 
                     53: typedef struct
                     54: {
                     55:        short                   checkSum;
                     56:        short                   length;
                     57:        byte                    transportControl;
                     58:        byte                    type;
                     59:        IPXaddr                 destination;
                     60:        IPXaddr                 source;
                     61: } IPXheader;
                     62: 
                     63: typedef struct ECBStructure
                     64: {
                     65:        struct ECBStructure *link;
                     66:        unsigned short  ESR_off;
                     67:        unsigned short  ESR_seg;
                     68:        byte    inUse;
                     69:        byte    completionCode;
                     70:        short   socket;
                     71:        byte    IPXWorkspace[4];
                     72:        byte    driverWorkspace[12];
                     73:        byte    immediateAddress[6];
                     74:        short   fragCount;
                     75:        short   fragOff;
                     76:        short   fragSeg;
                     77:        short   fragSize;
                     78: } ECB;
                     79: 
                     80: #pragma pack()
                     81: 
                     82: typedef struct
                     83: {
                     84:        ECB                     ecb;
                     85:        IPXheader       header;
                     86:        int                     sequence;
                     87:        char            data[NET_DATAGRAMSIZE];
                     88: } ipx_lowmem_buffer_t;
                     89: 
                     90: #define LOWMEMSIZE             (100 * 1024)
                     91: #define LOWMEMSAVE             256
                     92: #define IPXBUFFERS             ((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t))
                     93: #define IPXSOCKBUFFERS 5
                     94: #define IPXSOCKETS             (IPXBUFFERS / IPXSOCKBUFFERS)
                     95: 
                     96: // each socket's socketbuffer 0 is used for sending, the others for listening
                     97: 
                     98: typedef struct
                     99: {
                    100:        char                            reserved[LOWMEMSAVE];
                    101:        ipx_lowmem_buffer_t     socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS];
                    102: } ipx_lowmem_area_t;
                    103: 
                    104: 
                    105: static int ipxsocket[IPXSOCKETS];
                    106: static ECB *readlist[IPXSOCKETS];
                    107: static int sequence[IPXSOCKETS];
                    108: static int handlesInUse;
                    109: static ipx_lowmem_area_t *lma;
                    110: static char *lowmem_buffer;
                    111: static int lowmem_bufseg;
                    112: static int lowmem_bufoff;
                    113: static unsigned short ipx_cs;
                    114: static unsigned short ipx_ip;
                    115: static int net_acceptsocket = -1;
                    116: static int net_controlsocket;
1.1.1.2 ! root      117: static int net_hostport;
1.1       root      118: 
                    119: static void IPX_PollProcedure(void);
                    120: static PollProcedure pollProcedure = {NULL, 0.0, IPX_PollProcedure};
                    121: 
                    122: //=============================================================================
                    123: 
                    124: static void IPX_GetLocalAddress(IPXaddr *addr)
                    125: {
                    126:        regs.x.cs = ipx_cs;
                    127:        regs.x.ip = ipx_ip;
                    128:        regs.x.bx = IPX_GETADDRESS;
                    129:        regs.x.es = lowmem_bufseg;
                    130:        regs.x.si = lowmem_bufoff;
                    131:        __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
                    132:        Q_memcpy(addr, lowmem_buffer, 10);
                    133: }
                    134: 
                    135: //=============================================================================
                    136: 
                    137: static int IPX_GetLocalTarget(IPXaddr *addr, byte *localTarget)
                    138: {
                    139:        regs.x.cs = ipx_cs;
                    140:        regs.x.ip = ipx_ip;
                    141:        regs.x.bx = IPX_GETROUTE;
                    142:        regs.x.es = lowmem_bufseg;
                    143:        regs.x.si = lowmem_bufoff;
                    144:        regs.x.di = lowmem_bufoff + sizeof(IPXaddr);
                    145:        Q_memcpy(lowmem_buffer, addr, sizeof(IPXaddr));
                    146:        __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
                    147:        if (regs.h.al)
                    148:                return -1;
                    149:        Q_memcpy(localTarget, lowmem_buffer + sizeof(IPXaddr), 6);
                    150:        return 0;
                    151: }
                    152: 
                    153: //=============================================================================
                    154: 
                    155: static void IPX_ListenForPacket(ECB *ecb)
                    156: {
                    157:        regs.x.cs = ipx_cs;
                    158:        regs.x.ip = ipx_ip;
                    159:        regs.x.bx = IPX_LISTEN;
                    160:        regs.x.es = ptr2real(ecb) >> 4;
                    161:        regs.x.si = ptr2real(ecb) & 0xf;
                    162:        __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
                    163: }
                    164: 
                    165: //=============================================================================
                    166: 
                    167: static void IPX_RelinquishControl(void)
                    168: {
                    169:        regs.x.cs = ipx_cs;
                    170:        regs.x.ip = ipx_ip;
                    171:        regs.x.bx = IPX_RELINQUISH;
                    172:        __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
                    173: }
                    174: 
                    175: 
                    176: void IPX_PollProcedure(void)
                    177: {
                    178:        IPX_RelinquishControl();
                    179:        SchedulePollProcedure(&pollProcedure, 0.01);
                    180: }
                    181: 
                    182: //=============================================================================
                    183: 
                    184: static void ProcessReadyList(int s)
                    185: {
                    186:        int n;
                    187:        ECB *ecb;
                    188:        ECB *prev;
                    189: 
                    190:        for (n = 1; n < IPXSOCKBUFFERS; n++)
                    191:        {
                    192:                if (lma->socketbuffer[s][n].ecb.inUse == 0)
                    193:                {
                    194:                        for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link)
                    195:                        {
                    196:                                if (lma->socketbuffer[s][n].sequence < ((ipx_lowmem_buffer_t *) ecb)->sequence)
                    197:                                        break;
                    198:                                prev = ecb;
                    199:                        }
                    200:                        if (ecb)
                    201:                                lma->socketbuffer[s][n].ecb.link = ecb;
                    202:                        else
                    203:                                lma->socketbuffer[s][n].ecb.link = NULL;
                    204:                        if (prev)
                    205:                                prev->link = &lma->socketbuffer[s][n].ecb;
                    206:                        else
                    207:                                readlist[s] = &lma->socketbuffer[s][n].ecb;
                    208:                        lma->socketbuffer[s][n].ecb.inUse = 0xff;
                    209:                }
                    210:        }
                    211: }
                    212: 
                    213: //=============================================================================
                    214: 
                    215: int IPX_Init(void)
                    216: {
                    217:        int s;
                    218:        int n;
                    219:        struct qsockaddr addr;
                    220:        char *colon;
                    221: 
                    222:        if (COM_CheckParm ("-noipx"))
                    223:                return -1;
                    224: 
                    225:        // find the IPX far call entry point
                    226:        regs.x.ax = 0x7a00;
                    227:        __dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *)&regs);
                    228:        if (regs.h.al != 0xff)
                    229:        {
                    230:                Con_Printf("IPX not detected\n");
                    231:                return -1;
                    232:        }
                    233:        ipx_cs = regs.x.es;
                    234:        ipx_ip = regs.x.di;
                    235: 
1.1.1.2 ! root      236:        // get command line options
        !           237:        n = COM_CheckParm ("-ipxport");
        !           238:        if (n == 0)
        !           239:                net_hostport = DEFAULTnet_hostport;
        !           240:        else if (n < com_argc-1)
        !           241:                net_hostport = Q_atoi (com_argv[n+1]);
        !           242:        else
        !           243:                Sys_Error ("IPX_Init: you must specify a number after -ipxport");
        !           244: 
1.1       root      245:        // grab a chunk of memory down in DOS land
                    246:        lowmem_buffer = dos_getmemory(LOWMEMSIZE);
                    247:        if (!lowmem_buffer)
                    248:        {
                    249:                Con_Printf("IPX_Init: Not enough low memory\n");
                    250:                return -1;
                    251:        }
                    252:        lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
                    253:        lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
                    254: 
                    255:        // init socket handles & buffers
                    256:        handlesInUse = 0;
                    257:        lma = (ipx_lowmem_area_t *)lowmem_buffer;
                    258:        for (s = 0; s < IPXSOCKETS; s++)
                    259:        {
                    260:                ipxsocket[s] = 0;
                    261:                for (n = 0; n < IPXSOCKBUFFERS; n++)
                    262:                {
                    263:                        lma->socketbuffer[s][n].ecb.link = NULL;
                    264:                        lma->socketbuffer[s][n].ecb.ESR_off = 0;
                    265:                        lma->socketbuffer[s][n].ecb.ESR_seg = 0;
                    266:                        lma->socketbuffer[s][n].ecb.socket = 0;
                    267:                        lma->socketbuffer[s][n].ecb.inUse = 0xff;
                    268:                        lma->socketbuffer[s][n].ecb.completionCode = 0;
                    269:                        lma->socketbuffer[s][n].ecb.fragCount = 1;
                    270:                        lma->socketbuffer[s][n].ecb.fragOff = ptr2real(&lma->socketbuffer[s][n].header) & 0xf;
                    271:                        lma->socketbuffer[s][n].ecb.fragSeg = ptr2real(&lma->socketbuffer[s][n].header) >> 4;
                    272:                        lma->socketbuffer[s][n].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
                    273:                }
                    274:        }
                    275: 
                    276:        if ((net_controlsocket = IPX_OpenSocket (0)) == -1)
                    277:        {
                    278:                dos_freememory(lowmem_buffer);
                    279:                Con_DPrintf ("IPX_Init: Unable to open control socket\n");
                    280:                return -1;
                    281:        }
                    282: 
                    283:        SchedulePollProcedure(&pollProcedure, 0.01);
                    284: 
                    285:        IPX_GetSocketAddr (net_controlsocket, &addr);
                    286:        Q_strcpy(my_ipx_address,  IPX_AddrToString (&addr));
                    287:        colon = Q_strrchr (my_ipx_address, ':');
                    288:        if (colon)
                    289:                *colon = 0;
                    290: 
                    291:        Con_Printf("IPX initialized\n");
                    292:        ipxAvailable = true;
                    293:        return net_controlsocket;
                    294: }
                    295: 
                    296: //=============================================================================
                    297: 
                    298: void IPX_Shutdown(void)
                    299: {
                    300:        IPX_Listen (false);
                    301:        IPX_CloseSocket (net_controlsocket);
                    302:        dos_freememory(lowmem_buffer);
                    303: }
                    304: 
                    305: //=============================================================================
                    306: 
                    307: void IPX_Listen (qboolean state)
                    308: {
                    309:        // enable listening
                    310:        if (state)
                    311:        {
                    312:                if (net_acceptsocket != -1)
                    313:                        return;
                    314:                if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1)
                    315:                        Sys_Error ("IPX_Listen: Unable to open accept socket\n");
                    316:                return;
                    317:        }
                    318: 
                    319:        // disable listening
                    320:        if (net_acceptsocket == -1)
                    321:                return;
                    322:        IPX_CloseSocket (net_acceptsocket);
                    323:        net_acceptsocket = -1;
                    324: }
                    325: 
                    326: //=============================================================================
                    327: 
                    328: int IPX_OpenSocket(int port)
                    329: {
                    330:        int handle;
                    331:        int n;
                    332:        unsigned short socket;
                    333: 
                    334:        if (handlesInUse == IPXSOCKETS)
                    335:                return -1;
                    336: 
                    337:        // open the IPX socket
                    338:        regs.x.cs = ipx_cs;
                    339:        regs.x.ip = ipx_ip;
                    340:        regs.x.bx = IPX_OPEN;
                    341:        regs.h.al = 0;
                    342:        regs.x.dx = htons(port);
                    343:        __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
                    344:        if (regs.h.al == 0xfe)
                    345:        {
                    346:                Con_DPrintf("IPX_OpenSocket: all sockets in use\n");
                    347:                return -1;
                    348:        }
                    349:        if (regs.h.al == 0xff)
                    350:        {
                    351:                Con_DPrintf("IPX_OpenSocket: socket already open\n");
                    352:                return -1;
                    353:        }
                    354:        if (regs.h.al != 0)
                    355:        {
                    356:                Con_DPrintf("IPX_OpenSocket: error %02x\n", regs.h.al);
                    357:                return -1;
                    358:        }
                    359:        socket = regs.x.dx;
                    360: 
                    361: // grab a handle; fill in the ECBs, and get them listening
                    362:        for (handle = 0; handle < IPXSOCKETS; handle++)
                    363:        {
                    364:                if (ipxsocket[handle] == 0)
                    365:                {
                    366:                        ipxsocket[handle] = socket;
                    367:                        readlist[handle] = NULL;
                    368:                        sequence[handle] = 0;
                    369:                        for (n = 0; n < IPXSOCKBUFFERS; n ++)
                    370:                        {
                    371:                                lma->socketbuffer[handle][n].ecb.socket = socket;
                    372:                                lma->socketbuffer[handle][n].ecb.inUse = 0;
                    373:                                if (n)
                    374:                                        IPX_ListenForPacket(&lma->socketbuffer[handle][n].ecb);
                    375:                        }
                    376:                        handlesInUse++;
                    377:                        return handle;
                    378:                }
                    379:        }
                    380: 
                    381:        // "this will NEVER happen"
                    382:        Sys_Error("IPX_OpenSocket: handle allocation failed\n");
                    383:        return -1;
                    384: }
                    385: 
                    386: //=============================================================================
                    387: 
                    388: int IPX_CloseSocket(int handle)
                    389: {
                    390:        // if there's a send in progress, give it one last chance
                    391:        if (lma->socketbuffer[handle][0].ecb.inUse != 0)
                    392:                IPX_RelinquishControl();
                    393: 
                    394:        // close the socket (all pending sends/received are cancelled)
                    395:        regs.x.cs = ipx_cs;
                    396:        regs.x.ip = ipx_ip;
                    397:        regs.x.bx = IPX_CLOSE;
                    398:        regs.x.dx = ipxsocket[handle];
                    399:        __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
                    400: 
                    401:        ipxsocket[handle] = 0;
                    402:        handlesInUse--;
                    403: 
                    404:        return 0;
                    405: }
                    406: 
                    407: //=============================================================================
                    408: 
                    409: int IPX_Connect (int handle, struct qsockaddr *addr)
                    410: {
                    411:        IPXaddr ipxaddr;
                    412: 
                    413:        Q_memcpy(&ipxaddr, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
                    414:        if (IPX_GetLocalTarget(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
                    415:        {
                    416:                Con_Printf("Get Local Target failed\n");
                    417:                return -1;
                    418:        }
                    419: 
                    420:        return 0;
                    421: }
                    422: 
                    423: //=============================================================================
                    424: 
                    425: int IPX_CheckNewConnections (void)
                    426: {
                    427:        int n;
                    428: 
                    429:        if (net_acceptsocket == -1)
                    430:                return -1;
                    431: 
                    432:        for (n = 1; n < IPXSOCKBUFFERS; n ++)
                    433:                if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0)
                    434:                        return net_acceptsocket;
                    435:        return -1;
                    436: }
                    437: 
                    438: //=============================================================================
                    439: 
                    440: int IPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr)
                    441: {
                    442:        ECB             *ecb;
                    443:        ipx_lowmem_buffer_t *rcvbuf;
                    444:        int             copylen;
                    445: 
                    446:        ProcessReadyList(handle);
                    447: tryagain:
                    448:        if (readlist[handle] == NULL)
                    449:                return 0;
                    450:        ecb = readlist[handle];
                    451:        readlist[handle] = ecb->link;
                    452: 
                    453:        if (ecb->completionCode != 0)
                    454:        {
                    455:                Con_Printf("Warning: IPX_Read error %02x\n", ecb->completionCode);      
                    456:                ecb->fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
                    457:                IPX_ListenForPacket(ecb);
                    458:                goto tryagain;
                    459:        }
                    460: 
                    461:        rcvbuf = (ipx_lowmem_buffer_t *)ecb;
                    462: 
                    463:        // copy the data up to the buffer
                    464:        copylen = ntohs(rcvbuf->header.length) - (sizeof(int) + sizeof(IPXheader));
                    465:        if (len < copylen)
                    466:                Sys_Error("IPX_Read: buffer too small (%d vs %d)\n", len, copylen);
                    467:        Q_memcpy(buf, rcvbuf->data, copylen);
                    468: 
                    469:        // fill in the addr if they want it
                    470:        if (addr)
                    471:        {
                    472:                ((struct sockaddr_ipx *)addr)->sipx_family = AF_NETWARE;
                    473:                Q_memcpy(&((struct sockaddr_ipx *)addr)->sipx_addr, rcvbuf->header.source.network, sizeof(IPXaddr));
                    474:                ((struct sockaddr_ipx *)addr)->sipx_zero[0] = 0;
                    475:                ((struct sockaddr_ipx *)addr)->sipx_zero[1] = 0;
                    476:        }
                    477: 
                    478:        // update the send ecb's immediate address
                    479:        Q_memcpy(lma->socketbuffer[handle][0].ecb.immediateAddress, rcvbuf->ecb.immediateAddress, 6);
                    480: 
                    481:        // get this ecb listening again
                    482:        rcvbuf->ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
                    483:        IPX_ListenForPacket(&rcvbuf->ecb);
                    484:        return copylen;
                    485: }
                    486: 
                    487: //=============================================================================
                    488: 
                    489: int IPX_Broadcast (int handle, byte *buf, int len)
                    490: {
                    491:        struct sockaddr_ipx addr;
                    492:        int ret;
                    493: 
                    494:        Q_memset(addr.sipx_addr.network, 0x00, 4);
                    495:        Q_memset(addr.sipx_addr.node, 0xff, 6);
                    496:        addr.sipx_port = htons(net_hostport);
                    497:        Q_memset(lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6);
                    498:        ret = IPX_Write (handle, buf, len, (struct qsockaddr *)&addr);
                    499:        return ret;
                    500: }
                    501: 
                    502: //=============================================================================
                    503: 
                    504: int IPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr)
                    505: {
                    506:        // has the previous send completed?
                    507:        while (lma->socketbuffer[handle][0].ecb.inUse != 0)
                    508:                IPX_RelinquishControl();
                    509: 
                    510:        switch (lma->socketbuffer[handle][0].ecb.completionCode)
                    511:        {
                    512:                case 0x00: // success
                    513:                case 0xfc: // request cancelled
                    514:                        break;
                    515: 
                    516:                case 0xfd: // malformed packet
                    517:                default:
                    518:                        Con_Printf("IPX driver send failure: %02x\n", lma->socketbuffer[handle][0].ecb.completionCode);
                    519:                        break;
                    520: 
                    521:                case 0xfe: // packet undeliverable
                    522:                case 0xff: // unable to send packet
                    523:                        Con_Printf("IPX lost route, trying to re-establish\n");
                    524: 
                    525:                        // look for a new route
                    526:                        if (IPX_GetLocalTarget (&lma->socketbuffer[handle][0].header.destination, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
                    527:                                return -1;
                    528: 
                    529:                        // re-send the one that failed
                    530:                        regs.x.cs = ipx_cs;
                    531:                        regs.x.ip = ipx_ip;
                    532:                        regs.x.bx = IPX_SEND;
                    533:                        regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
                    534:                        regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
                    535:                        __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
                    536: 
                    537:                        // report that we did not send the current one
                    538:                        return 0;
                    539:        }
                    540: 
                    541:        // ecb : length
                    542:        lma->socketbuffer[handle][0].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + len;
                    543: 
                    544:        // ipx header : type
                    545:        lma->socketbuffer[handle][0].header.type = PTYPE_IPX;
                    546: 
                    547:        // ipx header : destination
                    548:        Q_memcpy(&lma->socketbuffer[handle][0].header.destination, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr));
                    549: 
                    550:        // sequence number
                    551:        lma->socketbuffer[handle][0].sequence = sequence[handle];
                    552:        sequence[handle]++;
                    553: 
                    554:        // copy down the data
                    555:        Q_memcpy(lma->socketbuffer[handle][0].data, buf, len);
                    556: 
                    557:        regs.x.cs = ipx_cs;
                    558:        regs.x.ip = ipx_ip;
                    559:        regs.x.bx = IPX_SEND;
                    560:        regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4;
                    561:        regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf;
                    562:        __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
                    563: 
                    564:        return len;
                    565: }
                    566: 
                    567: //=============================================================================
                    568: 
                    569: char *IPX_AddrToString (struct qsockaddr *addr)
                    570: {
                    571:        static char buf[28];
                    572: 
                    573:        sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u",
                    574:                ((struct sockaddr_ipx *)addr)->sipx_addr.network[0],
                    575:                ((struct sockaddr_ipx *)addr)->sipx_addr.network[1],
                    576:                ((struct sockaddr_ipx *)addr)->sipx_addr.network[2],
                    577:                ((struct sockaddr_ipx *)addr)->sipx_addr.network[3],
                    578:                ((struct sockaddr_ipx *)addr)->sipx_addr.node[0],
                    579:                ((struct sockaddr_ipx *)addr)->sipx_addr.node[1],
                    580:                ((struct sockaddr_ipx *)addr)->sipx_addr.node[2],
                    581:                ((struct sockaddr_ipx *)addr)->sipx_addr.node[3],
                    582:                ((struct sockaddr_ipx *)addr)->sipx_addr.node[4],
                    583:                ((struct sockaddr_ipx *)addr)->sipx_addr.node[5],
                    584:                ntohs(((struct sockaddr_ipx *)addr)->sipx_port)
                    585:                );
                    586:        return buf;
                    587: }
                    588: 
                    589: //=============================================================================
                    590: 
                    591: int IPX_StringToAddr (char *string, struct qsockaddr *addr)
                    592: {
                    593:        int  val;
                    594:        char buf[3];
                    595: 
                    596:        buf[2] = 0;
                    597:        Q_memset(addr, 0, sizeof(struct qsockaddr));
                    598:        addr->sa_family = AF_NETWARE;
                    599: 
                    600: #define DO(src,dest)   \
                    601:        buf[0] = string[src];   \
                    602:        buf[1] = string[src + 1];       \
                    603:        if (sscanf (buf, "%x", &val) != 1)      \
                    604:                return -1;      \
                    605:        ((struct sockaddr_ipx *)addr)->sipx_addr.dest = val
                    606: 
                    607:        DO(0, network[0]);
                    608:        DO(2, network[1]);
                    609:        DO(4, network[2]);
                    610:        DO(6, network[3]);
                    611:        DO(9, node[0]);
                    612:        DO(11, node[1]);
                    613:        DO(13, node[2]);
                    614:        DO(15, node[3]);
                    615:        DO(17, node[4]);
                    616:        DO(19, node[5]);
                    617: #undef DO
                    618: 
                    619:        sscanf (&string[22], "%u", &val);
                    620:        ((struct sockaddr_ipx *)addr)->sipx_port = htons(val);
                    621: 
                    622:        return 0;
                    623: }
                    624: 
                    625: //=============================================================================
                    626: 
                    627: int IPX_GetSocketAddr (int handle, struct qsockaddr *addr)
                    628: {
                    629:        Q_memset(addr, 0, sizeof(struct qsockaddr));
                    630:        addr->sa_family = AF_NETWARE;
                    631:        IPX_GetLocalAddress(&((struct sockaddr_ipx *)addr)->sipx_addr);
                    632:        ((struct sockaddr_ipx *)addr)->sipx_port = ipxsocket[handle];
                    633:        return 0;
                    634: }
                    635: 
                    636: //=============================================================================
                    637: 
                    638: int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
                    639: {
                    640:        Q_strcpy(name, IPX_AddrToString(addr));
                    641:        return 0;
                    642: }
                    643: 
                    644: //=============================================================================
                    645: 
                    646: int IPX_GetAddrFromName (char *name, struct qsockaddr *addr)
                    647: {
                    648:        int n;
                    649:        char buf[32];
                    650: 
                    651:        n = Q_strlen(name);
                    652: 
                    653:        if (n == 12)
                    654:        {
                    655:                sprintf(buf, "00000000:%s:%u", name, net_hostport);
                    656:                return IPX_StringToAddr (buf, addr);
                    657:        }
                    658:        if (n == 21)
                    659:        {
                    660:                sprintf(buf, "%s:%u", name, net_hostport);
                    661:                return IPX_StringToAddr (buf, addr);
                    662:        }
                    663:        if (n > 21 && n <= 27)
                    664:                return IPX_StringToAddr (name, addr);
                    665: 
                    666:        return -1;
                    667: }
                    668: 
                    669: //=============================================================================
                    670: 
                    671: int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
                    672: {
                    673:        if (addr1->sa_family != addr2->sa_family)
                    674:                return -1;
                    675: 
                    676:        if(Q_memcmp(&((struct sockaddr_ipx *)addr1)->sipx_addr, &((struct sockaddr_ipx *)addr2)->sipx_addr, 10))
                    677:                return -1;
                    678: 
                    679:        if (((struct sockaddr_ipx *)addr1)->sipx_port != ((struct sockaddr_ipx *)addr2)->sipx_port)
                    680:                return 1;
                    681: 
                    682:        return 0;
                    683: }
                    684: 
                    685: //=============================================================================
                    686: 
                    687: int IPX_GetSocketPort (struct qsockaddr *addr)
                    688: {
                    689:        return ntohs(((struct sockaddr_ipx *)addr)->sipx_port);
                    690: }
                    691: 
                    692: 
                    693: int IPX_SetSocketPort (struct qsockaddr *addr, int port)
                    694: {
                    695:        ((struct sockaddr_ipx *)addr)->sipx_port = htons(port);
                    696:        return 0;
                    697: }
                    698: 
                    699: //=============================================================================

unix.superglobalmegacorp.com

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