home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / net_mp.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  11KB  |  444 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_mpath.c
  21.  
  22. #include <dpmi.h>
  23. #include "quakedef.h"
  24. #include "mpdosock.h"
  25.  
  26. short flat_selector;
  27.  
  28. int WSAGetLastError(void);
  29. void sockets_flush(void);
  30.  
  31. extern cvar_t hostname;
  32.  
  33. #define MAXHOSTNAMELEN    256
  34.  
  35. static int net_acceptsocket = -1;   // socket for fielding new connections
  36. static int net_controlsocket;
  37. static int net_broadcastsocket = 0;
  38. //static qboolean ifbcastinit = false;
  39. static struct qsockaddr broadcastaddr;
  40.  
  41. static unsigned long myAddr;
  42.  
  43. #include "net_mp.h"
  44.  
  45.  
  46. //=============================================================================
  47.  
  48. int MPATH_Init (void)
  49. {
  50.   int   i;
  51.   struct hostent *local = NULL;
  52.   char  buff[MAXHOSTNAMELEN];
  53.   struct qsockaddr addr;
  54.   char  *p;
  55.  
  56.   if (COM_CheckParm ("-mpath") == 0)
  57.     return -1;
  58.  
  59.    flat_selector = __dpmi_allocate_ldt_descriptors(1);
  60.    if (flat_selector == -1) {
  61.       Con_Printf("MPATH_Init: Can't get flat selector\n");
  62.       return -1;
  63.    }
  64.    if (__dpmi_set_segment_base_address(flat_selector, 0) == -1) {
  65.       Con_Printf("MPATH_Init: Can't seg flat base!\n");
  66.       return -1;
  67.    }
  68.    if (__dpmi_set_segment_limit(flat_selector, 0xffffffff) == -1) {
  69.       Con_Printf("MPATH_Init: Can't set segment limit\n");
  70.       return -1;
  71.    }
  72.   // determine my name & address
  73.   if (gethostname(buff, MAXHOSTNAMELEN) == 0)
  74.     local = gethostbyname(buff);
  75.   if (local)
  76.   {
  77.     myAddr = *(int *)local->h_addr_list[0];
  78.  
  79.     // if the quake hostname isn't set, set it to the machine name
  80.     if (Q_strcmp(hostname.string, "UNNAMED") == 0)
  81.     {
  82.       // see if it's a text IP address (well, close enough)
  83.       for (p = buff; *p; p++)
  84.         if ((*p < '0' || *p > '9') && *p != '.')
  85.           break;
  86.  
  87.       // if it is a real name, strip off the domain; we only want the host
  88.       if (*p)
  89.       {
  90.         for (i = 0; i < 15; i++)
  91.           if (buff[i] == '.')
  92.             break;
  93.         buff[i] = 0;
  94.       }
  95.       Cvar_Set ("hostname", buff);
  96.     }
  97.   }
  98.  
  99.   if ((net_controlsocket = MPATH_OpenSocket (0)) == -1)
  100.     Sys_Error("MPATH_Init: Unable to open control socket\n");
  101.  
  102.   ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
  103.   ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
  104.   ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
  105.  
  106.   MPATH_GetSocketAddr (net_controlsocket, &addr);
  107.   Q_strcpy(my_tcpip_address,  MPATH_AddrToString (&addr));
  108.   p = Q_strrchr (my_tcpip_address, ':');
  109.   if (p)
  110.     *p = 0;
  111.  
  112.   Con_Printf("MPath Initialized\n");
  113.   tcpipAvailable = true;
  114.  
  115.   return net_controlsocket;
  116. }
  117.  
  118. //=============================================================================
  119.  
  120. void MPATH_Shutdown (void)
  121. {
  122.   MPATH_Listen (false);
  123.   MPATH_CloseSocket (net_controlsocket);
  124. }
  125.  
  126. //=============================================================================
  127.  
  128. void MPATH_Listen (qboolean state)
  129. {
  130.   // enable listening
  131.   if (state)
  132.   {
  133.     if (net_acceptsocket != -1)
  134.       return;
  135.     if ((net_acceptsocket = MPATH_OpenSocket (net_hostport)) == -1)
  136.       Sys_Error ("MPATH_Listen: Unable to open accept socket\n");
  137.     return;
  138.   }
  139.  
  140.   // disable listening
  141.   if (net_acceptsocket == -1)
  142.     return;
  143.   MPATH_CloseSocket (net_acceptsocket);
  144.   net_acceptsocket = -1;
  145. }
  146.  
  147. //=============================================================================
  148.  
  149. int MPATH_OpenSocket (int port)
  150. {
  151.   int newsocket;
  152.   struct sockaddr_in address;
  153.   u_long _true = 1;
  154.  
  155.   if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  156.     return -1;
  157.  
  158.   if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
  159.     goto ErrorReturn;
  160.  
  161.   address.sin_family = AF_INET;
  162.   address.sin_addr.s_addr = INADDR_ANY;
  163.   address.sin_port = htons(port);
  164.   if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  165.     goto ErrorReturn;
  166.  
  167.   return newsocket;
  168.  
  169. ErrorReturn:
  170.   closesocket (newsocket);
  171.   return -1;
  172. }
  173.  
  174. //=============================================================================
  175.  
  176. int MPATH_CloseSocket (int socket)
  177. {
  178.   if (socket == net_broadcastsocket)
  179.     net_broadcastsocket = 0;
  180.   return closesocket (socket);
  181. }
  182.  
  183.  
  184. //=============================================================================
  185. /*
  186. ============
  187. PartialIPAddress
  188.  
  189. this lets you type only as much of the net address as required, using
  190. the local network components to fill in the rest
  191. ============
  192. */
  193. static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
  194. {
  195.   char buff[256];
  196.   char *b;
  197.   int addr;
  198.   int num;
  199.   int mask;
  200.   int run;
  201.   int port;
  202.   
  203.   buff[0] = '.';
  204.   b = buff;
  205.   strcpy(buff+1, in);
  206.   if (buff[1] == '.')
  207.     b++;
  208.  
  209.   addr = 0;
  210.   mask=-1;
  211.   while (*b == '.')
  212.   {
  213.     b++;
  214.     num = 0;
  215.     run = 0;
  216.     while (!( *b < '0' || *b > '9'))
  217.     {
  218.       num = num*10 + *b++ - '0';
  219.       if (++run > 3)
  220.         return -1;
  221.     }
  222.     if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
  223.       return -1;
  224.     if (num < 0 || num > 255)
  225.       return -1;
  226.     mask<<=8;
  227.     addr = (addr<<8) + num;
  228.   }
  229.   
  230.   if (*b++ == ':')
  231.     port = Q_atoi(b);
  232.   else
  233.     port = net_hostport;
  234.  
  235.   hostaddr->sa_family = AF_INET;
  236.   ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);  
  237.   ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
  238.   
  239.   return 0;
  240. }
  241. //=============================================================================
  242.  
  243. int MPATH_Connect (int socket, struct qsockaddr *addr)
  244. {
  245.   return 0;
  246. }
  247.  
  248. //=============================================================================
  249.  
  250. int MPATH_CheckNewConnections (void)
  251. {
  252.   char buf[4];
  253.  
  254.   if (net_acceptsocket == -1)
  255.     return -1;
  256.  
  257.   if (recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
  258.     return net_acceptsocket;
  259.   return -1;
  260. }
  261.  
  262. //=============================================================================
  263.  
  264. int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
  265. {
  266.   int addrlen = sizeof (struct qsockaddr);
  267.   int ret;
  268.  
  269.   ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
  270.   if (ret == -1)
  271.   {
  272.     int errno = WSAGetLastError();
  273.  
  274.     if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
  275.       return 0;
  276.  
  277.   }
  278.   return ret;
  279. }
  280.  
  281. //=============================================================================
  282.  
  283. int MPATH_MakeSocketBroadcastCapable (int socket)
  284. {
  285.   int i = 1;
  286.  
  287.   // make this socket broadcast capable
  288.   if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
  289.     return -1;
  290.   net_broadcastsocket = socket;
  291.  
  292.   return 0;
  293. }
  294.  
  295. //=============================================================================
  296.  
  297. int MPATH_Broadcast (int socket, byte *buf, int len)
  298. {
  299.   int ret;
  300.  
  301.   if (socket != net_broadcastsocket)
  302.   {
  303.     if (net_broadcastsocket != 0)
  304.       Sys_Error("Attempted to use multiple broadcasts sockets\n");
  305.     ret = MPATH_MakeSocketBroadcastCapable (socket);
  306.     if (ret == -1)
  307.     {
  308.       Con_Printf("Unable to make socket broadcast capable\n");
  309.       return ret;
  310.     }
  311.   }
  312.  
  313.   return MPATH_Write (socket, buf, len, &broadcastaddr);
  314. }
  315.  
  316. //=============================================================================
  317.  
  318. int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
  319. {
  320.   int ret;
  321.  
  322.   ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
  323.   if (ret == -1)
  324.     if (WSAGetLastError() == WSAEWOULDBLOCK)
  325.       return 0;
  326.  
  327.   sockets_flush();
  328.  
  329.   return ret;
  330. }
  331.  
  332. //=============================================================================
  333.  
  334. char *MPATH_AddrToString (struct qsockaddr *addr)
  335. {
  336.   static char buffer[22];
  337.   int haddr;
  338.  
  339.   haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
  340.   sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
  341.   return buffer;
  342. }
  343.  
  344. //=============================================================================
  345.  
  346. int MPATH_StringToAddr (char *string, struct qsockaddr *addr)
  347. {
  348.   int ha1, ha2, ha3, ha4, hp;
  349.   int ipaddr;
  350.  
  351.   sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  352.   ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  353.  
  354.   addr->sa_family = AF_INET;
  355.   ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  356.   ((struct sockaddr_in *)addr)->sin_port = htons(hp);
  357.   return 0;
  358. }
  359.  
  360. //=============================================================================
  361.  
  362. int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr)
  363. {
  364.   int addrlen = sizeof(struct qsockaddr);
  365.   unsigned int a;
  366.  
  367.   Q_memset(addr, 0, sizeof(struct qsockaddr));
  368.   getsockname(socket, (struct sockaddr *)addr, &addrlen);
  369.   a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  370.   if (a == 0 || a == inet_addr("127.0.0.1"))
  371.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
  372.  
  373.   return 0;
  374. }
  375.  
  376. //=============================================================================
  377.  
  378. int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name)
  379. {
  380.   struct hostent *hostentry;
  381.  
  382.   hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
  383.   if (hostentry)
  384.   {
  385.     Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
  386.     return 0;
  387.   }
  388.  
  389.   Q_strcpy (name, MPATH_AddrToString (addr));
  390.   return 0;
  391. }
  392.  
  393. //=============================================================================
  394.  
  395. int MPATH_GetAddrFromName(char *name, struct qsockaddr *addr)
  396. {
  397.   struct hostent *hostentry;
  398.  
  399.   if (name[0] >= '0' && name[0] <= '9')
  400.     return PartialIPAddress (name, addr);
  401.   
  402.   hostentry = gethostbyname (name);
  403.   if (!hostentry)
  404.     return -1;
  405.  
  406.   addr->sa_family = AF_INET;
  407.   ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport); 
  408.   ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
  409.  
  410.   return 0;
  411. }
  412.  
  413. //=============================================================================
  414.  
  415. int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  416. {
  417.   if (addr1->sa_family != addr2->sa_family)
  418.     return -1;
  419.  
  420.   if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  421.     return -1;
  422.  
  423.   if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
  424.     return 1;
  425.  
  426.   return 0;
  427. }
  428.  
  429. //=============================================================================
  430.  
  431. int MPATH_GetSocketPort (struct qsockaddr *addr)
  432. {
  433.   return ntohs(((struct sockaddr_in *)addr)->sin_port);
  434. }
  435.  
  436.  
  437. int MPATH_SetSocketPort (struct qsockaddr *addr, int port)
  438. {
  439.   ((struct sockaddr_in *)addr)->sin_port = htons(port);
  440.   return 0;
  441. }
  442.  
  443. //=============================================================================
  444.