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