Annotation of quake1/net_bw.c, revision 1.1

1.1     ! root        1: // net_bw.c
        !             2: 
        !             3: #include <stdio.h>
        !             4: #include <stdlib.h>
        !             5: #include <dpmi.h>
        !             6: 
        !             7: #include "quakedef.h"
        !             8: #include "dosisms.h"
        !             9: 
        !            10: 
        !            11: // this section is general Unix stuff that we need
        !            12: 
        !            13: #define        EIO                             5       /* I/O error */
        !            14: #define EBADS                  9
        !            15: #define EWOULDBLOCK            35      /* function would block */
        !            16: #define EMSGSIZE               40      /* message to big for buffers */
        !            17: #define        EPROTONOSUPPORT 43      /* Protocol not supported */
        !            18: #define        ESOCKTNOSUPPORT 44      /* Socket type not supported */
        !            19: #define        EPFNOSUPPORT    46      /* Protocol family not supported */
        !            20: #define EAFNOSUPPORT   47      /* Address family not supported */
        !            21: #define ECONNABORTED   53      /* User requested hangup */
        !            22: #define ENOBUFS                55      /* No buffers available */
        !            23: #define EISCONN                56      /* Socket has closed */
        !            24: #define ENOTCONN               57      /* Socket is not connected */
        !            25: #define ESHUTDOWN              58      /* Socket is closed */
        !            26: #define ETOOMANYREFS   59      /* Too many sockets open */
        !            27: #define ETIMEDOUT              60      /* Connection timed out */
        !            28: #define ECONNREFUSED   61      /* Connection refused */
        !            29: 
        !            30: #define AF_INET                2       /* internet */
        !            31: 
        !            32: #define PF_INET                        AF_INET
        !            33: 
        !            34: #define SOCK_STREAM            1               /* stream */
        !            35: #define SOCK_DGRAM             2               /* datagram */
        !            36: 
        !            37: #define IPPROTO_TCP            6
        !            38: #define IPPROTO_UDP            17
        !            39: 
        !            40: #define INADDR_ANY             0
        !            41: 
        !            42: #define SIOCDONE               0x7300
        !            43: #define FIONREAD               0x667f
        !            44: #define FIONBIO                0x667e
        !            45: #define FIONWIN                0x1000
        !            46: #define FIONTIN                0x2000
        !            47: 
        !            48: #define BRDINIT                0
        !            49: #define BRDADDR                10
        !            50: 
        !            51: #define MAXHOSTNAMELEN 256
        !            52: 
        !            53: #define SOL_SOCKET             0xffff          /* options for socket level */
        !            54: 
        !            55: /*
        !            56:  * Option flags per-socket.
        !            57:  */
        !            58: #define SO_DEBUG               0x0001          /* turn on debugging info recording */
        !            59: #define SO_ACCEPTCONN  0x0002          /* socket has had listen() */
        !            60: #define SO_REUSEADDR   0x0004          /* allow local address reuse */
        !            61: #define SO_KEEPALIVE   0x0008          /* keep connections alive */
        !            62: #define SO_DONTROUTE   0x0010          /* just use interface addresses */
        !            63: #define SO_BROADCAST   0x0020          /* permit sending of broadcast msgs */
        !            64: #define SO_USELOOPBACK 0x0040          /* bypass hardware when possible */
        !            65: #define SO_LINGER              0x0080          /* linger on close if data present */
        !            66: #define SO_OOBINLINE   0x0100          /* leave received OOB data in line */
        !            67: #define SO_USEPRIV             0x4000          /* allocate from privileged port area */
        !            68: #define SO_CANTSIG             0x8000          /* prevent SIGPIPE on SS_CANTSENDMORE */
        !            69: 
        !            70: /*
        !            71:  * Additional options, not kept in so_options.
        !            72:  */
        !            73: #define SO_SNDBUF              0x1001          /* send buffer size */
        !            74: #define SO_RCVBUF              0x1002          /* receive buffer size */
        !            75: #define SO_SNDLOWAT            0x1003          /* send low-water mark */
        !            76: #define SO_RCVLOWAT            0x1004          /* receive low-water mark */
        !            77: #define SO_SNDTIMEO            0x1005          /* send timeout */
        !            78: #define SO_RCVTIMEO            0x1006          /* receive timeout */
        !            79: #define SO_ERROR               0x1007          /* get error status and clear */
        !            80: #define SO_TYPE                        0x1008          /* get socket type */
        !            81: 
        !            82: 
        !            83: struct in_addr
        !            84: {
        !            85:        union
        !            86:        {
        !            87:                struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
        !            88:                struct { unsigned short s_w1,s_w2; } S_un_w;
        !            89:                unsigned long S_addr;
        !            90:        } S_un;
        !            91: };
        !            92: #define        s_addr  S_un.S_addr     /* can be used for most tcp & ip code */
        !            93: #define        s_host  S_un.S_un_b.s_b2        /* host on imp */
        !            94: #define        s_net   S_un.S_un_b.s_b1        /* network */
        !            95: #define        s_imp   S_un.S_un_w.s_w2        /* imp */
        !            96: #define        s_impno S_un.S_un_b.s_b4        /* imp # */
        !            97: #define        s_lh    S_un.S_un_b.s_b3        /* logical host */
        !            98: 
        !            99: struct sockaddr_in
        !           100: {
        !           101:     short                      sin_family;
        !           102:     unsigned short     sin_port;
        !           103:        struct in_addr  sin_addr;
        !           104:     char                       sin_zero[8];
        !           105: };
        !           106: 
        !           107: struct hostent {
        !           108:        char    *h_name;        /* official name of host */
        !           109:        char    **h_aliases;    /* alias list */
        !           110:        int     h_addrtype;     /* host address type */
        !           111:        int     h_length;       /* length of address */
        !           112:        char    **h_addr_list;  /* list of addresses from name server */
        !           113: #define        h_addr  h_addr_list[0]  /* address, for backward compatiblity */
        !           114: };
        !           115: 
        !           116: char *inet_ntoa(struct in_addr in);
        !           117: 
        !           118: 
        !           119: // this section is B&W specific constants & structures
        !           120: 
        !           121: #define BW_IOCTL_BIND                  0
        !           122: #define BW_IOCTL_CLEAROPTIONS  5
        !           123: #define BW_IOCTL_SETOPTIONS            6
        !           124: #define BW_IOCTL_PEEK                  7
        !           125: #define BW_IOCTL_SETWINMASK            8
        !           126: 
        !           127: #define BW_OPTION_BLOCKING             0x01
        !           128: #define BW_OPTION_REUSEBUFFERS 0x80
        !           129: 
        !           130: #define BW_ERR_USR_HANGUP              50
        !           131: #define BW_ERR_HANGUP                  51
        !           132: #define BW_ERR_NET_ERR                 52
        !           133: #define BW_ERR_IS_CLOSED               53
        !           134: #define BW_ERR_TIME_OUT                        54
        !           135: #define BW_ERR_RESET                   55
        !           136: #define BW_ERR_FULL                            56
        !           137: #define BW_ERR_BLOCK                   57
        !           138: #define BW_ERR_SHUTDOWN                        58
        !           139: 
        !           140: #pragma pack(1)
        !           141: 
        !           142: typedef struct
        !           143: {
        !           144:        char                    state;                  // always 1
        !           145:        short                   localPort;
        !           146:        struct in_addr  localAddr;
        !           147:        char                    reason;                 // always 0
        !           148:        char                    options;
        !           149:        short                   dataAvailable;
        !           150: } BW_UDPinfo_t;
        !           151: 
        !           152: typedef struct
        !           153: {
        !           154:        char                    reserved1 [6];
        !           155:        unsigned short  info2Offset;
        !           156:        char                    reserved2 [18];
        !           157:        struct in_addr  remoteAddr;
        !           158: } BW_UDPreadInfo1_t;
        !           159: 
        !           160: typedef struct
        !           161: {
        !           162:        short                   remotePort;
        !           163:        char                    reserved1 [2];
        !           164:        unsigned short  dataLenPlus8;
        !           165:        char                    reserved2 [2];
        !           166:        char                    data[1];                        // actual size is <dataLenPlus8> - 8            
        !           167: } BW_UDPreadInfo2_t;
        !           168: 
        !           169: typedef struct
        !           170: {
        !           171:        char                    reserved1 [2];
        !           172:        short                   remotePort;
        !           173:        unsigned short  dataLen;
        !           174:        struct in_addr  remoteAddr;
        !           175:        char                    reserved2 [42];
        !           176:        char                    data[1];                        // actual size is <datalen>
        !           177: } BW_writeInfo_t;
        !           178: 
        !           179: typedef struct
        !           180: {
        !           181:        short   ioport;
        !           182:        byte    dma;
        !           183:        byte    vector;
        !           184:        byte    irq;
        !           185:        short   bufferSize;
        !           186:        short   maxWindow;
        !           187:        short   timeZone;
        !           188:        byte    myType;
        !           189:        int             inetAddr;
        !           190:        short   value;
        !           191:        byte    subnetMask;
        !           192:        short   etherPointer;
        !           193:        short   logserverPointer;
        !           194:        short   nameserverPointer;
        !           195:        short   printserverPointer;
        !           196:        short   timeserverPointer;
        !           197:        short   gatewayPointer;
        !           198:        short   driverSegment;
        !           199:        byte    transferSize;
        !           200:        char    cardName [9];
        !           201: } BW_ethdevinfo_t;
        !           202: 
        !           203: #pragma pack()
        !           204: 
        !           205: #define LOWMEM_SIZE    4096
        !           206: 
        !           207: static unsigned char *lowmem_buffer;
        !           208: static int lowmem_bufseg;
        !           209: static int lowmem_bufoff;
        !           210: static BW_ethdevinfo_t ethdevinfo;
        !           211: static int netmask;
        !           212: static struct in_addr bcastaddr;
        !           213: 
        !           214: extern regs_t regs;
        !           215: 
        !           216: static int net_acceptsocket = -1;              // socket for fielding new connections
        !           217: static int net_controlsocket = 0;
        !           218: 
        !           219: #include "net_bw.h"
        !           220: 
        !           221: //=============================================================================
        !           222: 
        !           223: static int BW_ioctl(int s, char *msg, int msglen)
        !           224: {
        !           225:        Q_memcpy(lowmem_buffer, msg, msglen);
        !           226: 
        !           227:        regs.x.ax = 0x4403;
        !           228:        regs.x.bx = s;
        !           229:        regs.x.cx = msglen;
        !           230:        regs.x.dx = lowmem_bufoff;
        !           231:        regs.x.ds = lowmem_bufseg;
        !           232:        if (dos_int86(0x21))
        !           233:                return regs.x.ax;
        !           234:        return 0;
        !           235: }
        !           236: 
        !           237: //=============================================================================
        !           238: 
        !           239: static int BW_TranslateError(int error)
        !           240: {
        !           241:        switch(error)
        !           242:        {
        !           243:                case BW_ERR_USR_HANGUP: return ECONNABORTED;
        !           244:                case BW_ERR_HANGUP:             return EISCONN;
        !           245:                case BW_ERR_NET_ERR:    return ENOTCONN;
        !           246:                case BW_ERR_IS_CLOSED:  return ENOTCONN;
        !           247:                case BW_ERR_TIME_OUT:   return ETIMEDOUT;
        !           248:                case BW_ERR_RESET:              return ECONNREFUSED;
        !           249:                case BW_ERR_FULL:               return ETOOMANYREFS;
        !           250:                case BW_ERR_BLOCK:              return EWOULDBLOCK;
        !           251:                case BW_ERR_SHUTDOWN:   return ESHUTDOWN;
        !           252:        }
        !           253:        return EIO;
        !           254: }
        !           255: 
        !           256: //=============================================================================
        !           257: 
        !           258: static int GetEthdevinfo(void)
        !           259: {
        !           260:        int fd;
        !           261: 
        !           262:        Q_strcpy((char *)lowmem_buffer, "ETHDEV27");
        !           263:        regs.x.ax = 0x3d42;
        !           264:        regs.x.ds = lowmem_bufseg;
        !           265:        regs.x.dx = lowmem_bufoff;
        !           266:        if (dos_int86(0x21))
        !           267:                return -1;
        !           268:        fd = regs.x.ax;
        !           269: 
        !           270:        regs.x.ax = 0x4401;
        !           271:        regs.x.bx = fd;
        !           272:        regs.x.dx = 0x60;
        !           273:        dos_int86(0x21);
        !           274: 
        !           275:        regs.h.ah = 0x3f;
        !           276:        regs.x.cx = sizeof(ethdevinfo);
        !           277:        regs.x.es = regs.x.ds = lowmem_bufseg;
        !           278:        regs.x.dx = lowmem_bufoff;
        !           279:        regs.x.bx = fd;
        !           280:        if (dos_int86(0x21))
        !           281:                return -1;
        !           282:        Q_memcpy(&ethdevinfo, lowmem_buffer, regs.x.ax);
        !           283: 
        !           284:        regs.h.ah = 0x3e;
        !           285:        regs.x.bx = fd;
        !           286:        dos_int86(0x21);
        !           287: 
        !           288:        return 0;
        !           289: }
        !           290: 
        !           291: //=============================================================================
        !           292: 
        !           293: int BW_Init(void)
        !           294: {
        !           295:        struct qsockaddr addr;
        !           296:        char *colon;
        !           297: 
        !           298:        if (COM_CheckParm ("-noudp"))
        !           299:                return -1;
        !           300: 
        !           301:        lowmem_buffer = dos_getmemory(LOWMEM_SIZE);
        !           302:        if (!lowmem_buffer)
        !           303:                Sys_Error("not enough low memory\n");
        !           304:        lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
        !           305:        lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
        !           306: 
        !           307:        if (GetEthdevinfo())
        !           308:        {
        !           309:                Con_DPrintf("Beame & Whiteside TCP/IP not detected\n");
        !           310:                dos_freememory(lowmem_buffer);
        !           311:                return -1;
        !           312:        }
        !           313:        netmask = 0xffffffff >> (32 - ethdevinfo.subnetMask);
        !           314:        bcastaddr.s_addr = (ethdevinfo.inetAddr & netmask) | (~netmask);
        !           315: 
        !           316:        if ((net_controlsocket = BW_OpenSocket (0)) == -1)
        !           317:        {
        !           318:                dos_freememory(lowmem_buffer);
        !           319:                Con_DPrintf ("BW_Init unable to open control socket; disabled\n");
        !           320:                return -1;
        !           321:        }
        !           322: 
        !           323:        BW_GetSocketAddr (net_controlsocket, &addr);
        !           324:        Q_strcpy(my_tcpip_address,  BW_AddrToString (&addr));
        !           325:        colon = Q_strrchr (my_tcpip_address, ':');
        !           326:        if (colon)
        !           327:                *colon = 0;
        !           328: 
        !           329:        Con_Printf("BW_Init: UDP initialized\n");
        !           330:        tcpipAvailable = true;
        !           331: 
        !           332:        return net_controlsocket;
        !           333: }
        !           334: 
        !           335: //=============================================================================
        !           336: 
        !           337: void BW_Shutdown(void)
        !           338: {
        !           339:        BW_Listen (false);
        !           340:        BW_CloseSocket (net_controlsocket);
        !           341:        dos_freememory(lowmem_buffer);
        !           342: }
        !           343: 
        !           344: //=============================================================================
        !           345: 
        !           346: void BW_Listen (qboolean state)
        !           347: {
        !           348:        // enable listening
        !           349:        if (state)
        !           350:        {
        !           351:                if (net_acceptsocket != -1)
        !           352:                        return;
        !           353:                if ((net_acceptsocket = BW_OpenSocket (net_hostport)) == -1)
        !           354:                        Sys_Error ("BW_Listen: Unable to open accept socket\n");
        !           355:                return;
        !           356:        }
        !           357: 
        !           358:        // disable listening
        !           359:        if (net_acceptsocket == -1)
        !           360:                return;
        !           361:        BW_CloseSocket (net_acceptsocket);
        !           362:        net_acceptsocket = -1;
        !           363: }
        !           364: 
        !           365: 
        !           366: //=============================================================================
        !           367: 
        !           368: /*
        !           369: OpenSocket returns a handle to a network socket that has been opened,
        !           370: set to nonblocking, and bound to <port>.  Additional socket options
        !           371: should be set here if they are needed.  -1 is returned on failure.
        !           372: */
        !           373: 
        !           374: int BW_OpenSocket(int port)
        !           375: {
        !           376:        int s;
        !           377:        int ret;
        !           378:        int deadman = 3 * 1024;
        !           379:        static int dynamic = 1024;
        !           380:        static char reuse_msg[2] = {BW_IOCTL_SETOPTIONS, BW_OPTION_REUSEBUFFERS};
        !           381:        static char bind_msg[3] = {BW_IOCTL_BIND, 0, 0};
        !           382:        static char nonblock_msg[2] = {BW_IOCTL_CLEAROPTIONS, BW_OPTION_BLOCKING};
        !           383: 
        !           384:        // allocate a UDP socket
        !           385:        Q_strcpy((char *)lowmem_buffer, "UDP-IP10");
        !           386:        regs.x.ax = 0x3d42;
        !           387:        regs.x.ds = lowmem_bufseg;
        !           388:        regs.x.dx = lowmem_bufoff;
        !           389:        if (dos_int86(0x21))
        !           390:        {
        !           391:                Con_Printf("BW_OpenSocket failed: %u\n", BW_TranslateError(regs.x.ax));
        !           392:                return -1;
        !           393:        }
        !           394:        s = regs.x.ax;
        !           395: 
        !           396:        // set file descriptor to raw mode
        !           397:        regs.x.ax = 0x4401;
        !           398:        regs.x.bx = s;
        !           399:        regs.x.dx = 0x60;
        !           400:        dos_int86(0x21);
        !           401: 
        !           402:        if (BW_ioctl(s, reuse_msg, 2))
        !           403:        {
        !           404:                Con_Printf("BW_OpenSocket ioctl(reuse) failed\n");
        !           405:                return -1;
        !           406:        }
        !           407: 
        !           408:        if (BW_ioctl(s, nonblock_msg, 2))
        !           409:        {
        !           410:                Con_Printf("BW_OpenSocket ioctl(nonblocking) failed\n");
        !           411:                return -1;
        !           412:        }
        !           413: 
        !           414:        // if a socket was specified, bind to it and return
        !           415:        if (port)
        !           416:        {
        !           417:                *(short *)&bind_msg[1] = port;
        !           418:                if (BW_ioctl(s, bind_msg, 3))
        !           419:                {
        !           420:                        BW_CloseSocket(s);
        !           421:                        return -1;
        !           422:                }
        !           423:                return s;
        !           424:        }
        !           425: 
        !           426:        // B&W does NOT do dynamic allocation, so if port == 0 we must fake it
        !           427:        do
        !           428:        {
        !           429:                port = dynamic++;
        !           430:                if (dynamic == 4096)
        !           431:                        dynamic = 1024;
        !           432:                deadman--;
        !           433:                *(short *)&bind_msg[1] = port;
        !           434:                ret = BW_ioctl(s, bind_msg, 3);
        !           435:        }
        !           436:        while (ret && deadman);
        !           437:        if (ret)
        !           438:                return -1;
        !           439:        return s;
        !           440: }
        !           441: 
        !           442: //=============================================================================
        !           443: 
        !           444: int BW_CloseSocket(int socket)
        !           445: {
        !           446:        regs.h.ah = 0x3e;
        !           447:        regs.x.bx = socket;
        !           448:        if(dos_int86(0x21))
        !           449:                {
        !           450:                        Con_Printf("BW_CloseSocket %u failed: %u\n", socket, BW_TranslateError(regs.x.ax));
        !           451:                        return -1;
        !           452:                }
        !           453:        return 0;
        !           454: }
        !           455: 
        !           456: //=============================================================================
        !           457: 
        !           458: int BW_Connect (int socket, struct qsockaddr *hostaddr)
        !           459: {
        !           460:        return 0;
        !           461: }
        !           462: 
        !           463: //=============================================================================
        !           464: 
        !           465: int BW_CheckNewConnections(void)
        !           466: {
        !           467:        if (net_acceptsocket == 0)
        !           468:                return -1;
        !           469: 
        !           470:        // see if there's anything waiting
        !           471:        regs.x.ax = 0x4406;
        !           472:        regs.x.bx = net_acceptsocket;
        !           473:        dos_int86(0x21);
        !           474:        if (regs.x.ax == 0)
        !           475:                return -1;
        !           476:        return net_acceptsocket;
        !           477: }
        !           478: 
        !           479: //=============================================================================
        !           480: 
        !           481: int BW_Read(int s, byte *buf, int len, struct qsockaddr *from)
        !           482: {
        !           483:        BW_UDPreadInfo1_t *info1;
        !           484:        BW_UDPreadInfo2_t *info2;
        !           485: 
        !           486:        // ask if there's anything waiting
        !           487:        regs.x.ax = 0x4406;
        !           488:        regs.x.bx = s;
        !           489:        dos_int86(0x21);
        !           490:        if (regs.x.ax == 0)
        !           491:                return 0;
        !           492: 
        !           493:        // there was, so let's get it
        !           494:        regs.h.ah = 0x3f;
        !           495:        regs.x.cx = /* len + 53 */ LOWMEM_SIZE;
        !           496:        regs.x.es = regs.x.ds = lowmem_bufseg;
        !           497:        regs.x.dx = lowmem_bufoff;
        !           498:        regs.x.bx = s;
        !           499:        if (dos_int86(0x21))
        !           500:        {
        !           501:                Con_Printf("BW UDP read error: %u\n", BW_TranslateError(regs.x.ax));
        !           502:                return -1;
        !           503:        }
        !           504: 
        !           505:        info1 = (BW_UDPreadInfo1_t *)lowmem_buffer;
        !           506:        info2 = (BW_UDPreadInfo2_t *)(lowmem_buffer + info1->info2Offset);
        !           507: 
        !           508:        if (from)
        !           509:        {
        !           510:                from->sa_family = AF_INET;
        !           511:                ((struct sockaddr_in *)from)->sin_addr = info1->remoteAddr;
        !           512:                ((struct sockaddr_in *)from)->sin_port = htons(info2->remotePort);
        !           513:        }
        !           514: 
        !           515:        len = info2->dataLenPlus8 - 8;
        !           516:        if (len > NET_DATAGRAMSIZE)
        !           517:        {
        !           518:                Con_Printf("BW UDP read packet too large: %u\n", len);
        !           519:                return -1;
        !           520:        }
        !           521:        Q_memcpy(buf, info2->data, len);
        !           522: 
        !           523:        return len;
        !           524: }
        !           525: 
        !           526: //=============================================================================
        !           527: 
        !           528: int BW_Broadcast(int s, byte *msg, int len)
        !           529: {
        !           530:        BW_writeInfo_t *writeInfo;
        !           531: 
        !           532:        // ask if we're clear to send
        !           533:        regs.x.ax = 0x4407;
        !           534:        regs.x.bx = s;
        !           535:        dos_int86(0x21);
        !           536:        if (regs.x.ax == 0)
        !           537:                return 0;
        !           538: 
        !           539:        // yes, let's do it
        !           540:        writeInfo = (BW_writeInfo_t *)lowmem_buffer;
        !           541:        writeInfo->remoteAddr = bcastaddr;
        !           542:        writeInfo->remotePort = net_hostport;
        !           543:        writeInfo->dataLen = len;
        !           544:        if (len > NET_DATAGRAMSIZE)
        !           545:                Sys_Error("BW UDP write packet too large: %u\n", len);
        !           546:        Q_memcpy(writeInfo->data, msg, len);
        !           547:        writeInfo->data[len] = 0;
        !           548:        regs.h.ah = 0x40;
        !           549:        regs.x.bx = s;
        !           550:        regs.x.cx = len + sizeof(BW_writeInfo_t);
        !           551:        regs.x.es = regs.x.ds = lowmem_bufseg;
        !           552:        regs.x.dx = lowmem_bufoff;
        !           553:        if (dos_int86(0x21))
        !           554:        {
        !           555:                Con_Printf("BW_Broadcast failed: %u\n", BW_TranslateError(regs.x.ax));
        !           556:                return -1;
        !           557:        }
        !           558: 
        !           559:        return len;
        !           560: }
        !           561: 
        !           562: //=============================================================================
        !           563: 
        !           564: int BW_Write(int s, byte *msg, int len, struct qsockaddr *to)
        !           565: {
        !           566:        BW_writeInfo_t *writeInfo;
        !           567: 
        !           568:        // ask if we're clear to send
        !           569:        regs.x.ax = 0x4407;
        !           570:        regs.x.bx = s;
        !           571:        dos_int86(0x21);
        !           572:        if (regs.x.ax == 0)
        !           573:                return 0;
        !           574: 
        !           575:        // yes, let's do it
        !           576:        writeInfo = (BW_writeInfo_t *)lowmem_buffer;
        !           577:        writeInfo->remoteAddr = ((struct sockaddr_in *)to)->sin_addr;
        !           578:        writeInfo->remotePort = ntohs(((struct sockaddr_in *)to)->sin_port);
        !           579:        writeInfo->dataLen = len;
        !           580:        if (len > NET_DATAGRAMSIZE)
        !           581:                Sys_Error("BW UDP write packet too large: %u\n", len);
        !           582:        Q_memcpy(writeInfo->data, msg, len);
        !           583:        writeInfo->data[len] = 0;
        !           584:        regs.h.ah = 0x40;
        !           585:        regs.x.bx = s;
        !           586:        regs.x.cx = len + sizeof(BW_writeInfo_t);
        !           587:        regs.x.es = regs.x.ds = lowmem_bufseg;
        !           588:        regs.x.dx = lowmem_bufoff;
        !           589:        if (dos_int86(0x21))
        !           590:        {
        !           591:                Con_Printf("BW_Write failed: %u\n", BW_TranslateError(regs.x.ax));
        !           592:                return -1;
        !           593:        }
        !           594: 
        !           595:        return len;
        !           596: }
        !           597: 
        !           598: //=============================================================================
        !           599: 
        !           600: 
        !           601: char *BW_AddrToString (struct qsockaddr *addr)
        !           602: {
        !           603:        static char buffer[22];
        !           604: 
        !           605:        sprintf(buffer, "%d.%d.%d.%d:%d",
        !           606:                ((struct sockaddr_in *)addr)->sin_addr.s_net,
        !           607:                ((struct sockaddr_in *)addr)->sin_addr.s_host,
        !           608:                ((struct sockaddr_in *)addr)->sin_addr.s_lh,
        !           609:                ((struct sockaddr_in *)addr)->sin_addr.s_impno,
        !           610:                ntohs(((struct sockaddr_in *)addr)->sin_port)
        !           611:                );
        !           612:        return buffer;
        !           613: }
        !           614: 
        !           615: //=============================================================================
        !           616: 
        !           617: int BW_StringToAddr (char *string, struct qsockaddr *addr)
        !           618: {
        !           619:        int ha1, ha2, ha3, ha4, hp;
        !           620:        int ipaddr;
        !           621: 
        !           622:        sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
        !           623:        ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
        !           624: 
        !           625:        addr->sa_family = AF_INET;
        !           626:        ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
        !           627:        ((struct sockaddr_in *)addr)->sin_port = htons((short)hp);
        !           628:        return 0;
        !           629: }
        !           630: 
        !           631: //=============================================================================
        !           632: 
        !           633: int BW_GetSocketAddr (int socket, struct qsockaddr *addr)
        !           634: {
        !           635:        regs.x.ax = 0x4402;
        !           636:        regs.x.bx = socket;
        !           637:        regs.x.cx = sizeof(BW_UDPinfo_t);
        !           638:        regs.x.dx = lowmem_bufoff;
        !           639:        regs.x.ds = lowmem_bufseg;
        !           640:        dos_int86(0x21);
        !           641: 
        !           642:        addr->sa_family = AF_INET;
        !           643:        ((struct sockaddr_in *)addr)->sin_addr.s_addr = ((BW_UDPinfo_t *)lowmem_buffer)->localAddr.s_addr;
        !           644:        ((struct sockaddr_in *)addr)->sin_port = htons(((BW_UDPinfo_t *)lowmem_buffer)->localPort);
        !           645: 
        !           646:        return 0;
        !           647: }
        !           648: 
        !           649: //=============================================================================
        !           650: 
        !           651: int BW_GetNameFromAddr (struct qsockaddr *addr, char *name)
        !           652: {
        !           653:        Q_strcpy(name, BW_AddrToString(addr));
        !           654:        return 0;
        !           655: }
        !           656: 
        !           657: ///=============================================================================
        !           658: 
        !           659: int BW_GetAddrFromName (char *name, struct qsockaddr *hostaddr)
        !           660: {
        !           661:        char buff[MAXHOSTNAMELEN];
        !           662:        char *b;
        !           663:        int addr;
        !           664:        int num;
        !           665:        int mask;
        !           666:        int run;
        !           667:        int port;
        !           668: 
        !           669:        if (name[0] < '0' || name[0] > '9')
        !           670:                return -1;
        !           671: 
        !           672:        buff[0] = '.';
        !           673:        b = buff;
        !           674:        Q_strcpy(buff+1, name);
        !           675:        if (buff[1] == '.')
        !           676:                b++;
        !           677: 
        !           678:        addr = 0;
        !           679:        mask = -1;
        !           680:        while (*b == '.')
        !           681:        {
        !           682:                b++;
        !           683:                num = 0;
        !           684:                run = 0;
        !           685:                while (!( *b < '0' || *b > '9'))
        !           686:                {
        !           687:                  num = num*10 + *b++ - '0';
        !           688:                  if (++run > 3)
        !           689:                        return -1;
        !           690:                }
        !           691:                if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
        !           692:                        return -1;
        !           693:                if (num < 0 || num > 255)
        !           694:                        return -1;
        !           695:                mask<<=8;
        !           696:                addr = (addr<<8) + num;
        !           697:        }
        !           698:        addr = htonl(addr);
        !           699:        mask = htonl(mask);
        !           700: 
        !           701:        if (*b++ == ':')
        !           702:                port = Q_atoi(b);
        !           703:        else
        !           704:                port = net_hostport;
        !           705: 
        !           706:        hostaddr->sa_family = AF_INET;
        !           707:        ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);        
        !           708:        ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr =
        !           709:        ((ethdevinfo.inetAddr & mask) | addr);
        !           710: 
        !           711:        return 0;
        !           712: }
        !           713: 
        !           714: //=============================================================================
        !           715: 
        !           716: int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
        !           717: {
        !           718:        if (addr1->sa_family != addr2->sa_family)
        !           719:                return -1;
        !           720: 
        !           721:        if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
        !           722:                return -1;
        !           723: 
        !           724:        if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
        !           725:                return 1;
        !           726: 
        !           727:        return 0;
        !           728: }
        !           729: 
        !           730: //=============================================================================
        !           731: 
        !           732: int BW_GetSocketPort (struct qsockaddr *addr)
        !           733: {
        !           734:        return ntohs(((struct sockaddr_in *)addr)->sin_port);
        !           735: }
        !           736: 
        !           737: 
        !           738: int BW_SetSocketPort (struct qsockaddr *addr, int port)
        !           739: {
        !           740:        ((struct sockaddr_in *)addr)->sin_port = htons(port);
        !           741:        return 0;
        !           742: }
        !           743: 
        !           744: //=============================================================================

unix.superglobalmegacorp.com

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