Annotation of quake1/net_ipx.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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