home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / net_bw.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  18.9 KB  |  764 lines

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