home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / net_udp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  7.0 KB  |  319 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_main.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 <sys/uio.h>
  31. #include <arpa/inet.h>
  32. #include <errno.h>
  33.  
  34. #if defined(sun)
  35. #include <unistd.h>
  36. #endif
  37.  
  38. #ifdef sun
  39. #include <sys/filio.h>
  40. #endif
  41.  
  42. #ifdef NeXT
  43. #include <libc.h>
  44. #endif
  45.  
  46. netadr_t  net_local_adr;
  47.  
  48. netadr_t  net_from;
  49. sizebuf_t net_message;
  50. int     net_socket;     // non blocking, for receives
  51. int     net_send_socket;  // blocking, for sends
  52.  
  53. #define MAX_UDP_PACKET  8192
  54. byte    net_message_buffer[MAX_UDP_PACKET];
  55.  
  56. int gethostname (char *, int);
  57. int close (int);
  58.  
  59. //=============================================================================
  60.  
  61. void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
  62. {
  63.   memset (s, 0, sizeof(*s));
  64.   s->sin_family = AF_INET;
  65.  
  66.   *(int *)&s->sin_addr = *(int *)&a->ip;
  67.   s->sin_port = a->port;
  68. }
  69.  
  70. void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
  71. {
  72.   *(int *)&a->ip = *(int *)&s->sin_addr;
  73.   a->port = s->sin_port;
  74. }
  75.  
  76. qboolean  NET_CompareBaseAdr (netadr_t a, netadr_t b)
  77. {
  78.   if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3])
  79.     return true;
  80.   return false;
  81. }
  82.  
  83.  
  84. qboolean  NET_CompareAdr (netadr_t a, netadr_t b)
  85. {
  86.   if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port)
  87.     return true;
  88.   return false;
  89. }
  90.  
  91. char  *NET_AdrToString (netadr_t a)
  92. {
  93.   static  char  s[64];
  94.   
  95.   sprintf (s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
  96.  
  97.   return s;
  98. }
  99.  
  100. char  *NET_BaseAdrToString (netadr_t a)
  101. {
  102.   static  char  s[64];
  103.   
  104.   sprintf (s, "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
  105.  
  106.   return s;
  107. }
  108.  
  109. /*
  110. =============
  111. NET_StringToAdr
  112.  
  113. idnewt
  114. idnewt:28000
  115. 192.246.40.70
  116. 192.246.40.70:28000
  117. =============
  118. */
  119. qboolean  NET_StringToAdr (char *s, netadr_t *a)
  120. {
  121.   struct hostent  *h;
  122.   struct sockaddr_in sadr;
  123.   char  *colon;
  124.   char  copy[128];
  125.   
  126.   
  127.   memset (&sadr, 0, sizeof(sadr));
  128.   sadr.sin_family = AF_INET;
  129.   
  130.   sadr.sin_port = 0;
  131.  
  132.   strcpy (copy, s);
  133.   // strip off a trailing :port if present
  134.   for (colon = copy ; *colon ; colon++)
  135.     if (*colon == ':')
  136.     {
  137.       *colon = 0;
  138.       sadr.sin_port = htons(atoi(colon+1)); 
  139.     }
  140.   
  141.   if (copy[0] >= '0' && copy[0] <= '9')
  142.   {
  143.     *(int *)&sadr.sin_addr = inet_addr(copy);
  144.   }
  145.   else
  146.   {
  147.     if (! (h = gethostbyname(copy)) )
  148.       return 0;
  149.     *(int *)&sadr.sin_addr = *(int *)h->h_addr_list[0];
  150.   }
  151.   
  152.   SockadrToNetadr (&sadr, a);
  153.  
  154.   return true;
  155. }
  156.  
  157. // Returns true if we can't bind the address locally--in other words, 
  158. // the IP is NOT one of our interfaces.
  159. qboolean NET_IsClientLegal(netadr_t *adr)
  160. {
  161.   struct sockaddr_in sadr;
  162.   int newsocket;
  163.  
  164. #if 0
  165.   if (adr->ip[0] == 127)
  166.     return false; // no local connections period
  167.  
  168.   NetadrToSockadr (adr, &sadr);
  169.  
  170.   if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  171.     Sys_Error ("NET_IsClientLegal: socket:", strerror(errno));
  172.  
  173.   sadr.sin_port = 0;
  174.  
  175.   if( bind (newsocket, (void *)&sadr, sizeof(sadr)) == -1) 
  176.   {
  177.     // It is not a local address
  178.     close(newsocket);
  179.     return true;
  180.   }
  181.   close(newsocket);
  182.   return false;
  183. #else
  184.   return true;
  185. #endif
  186. }
  187.  
  188.  
  189. //=============================================================================
  190.  
  191. qboolean NET_GetPacket (void)
  192. {
  193.   int   ret;
  194.   struct sockaddr_in  from;
  195.   int   fromlen;
  196.  
  197.   fromlen = sizeof(from);
  198.   ret = recvfrom (net_socket, net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr *)&from, &fromlen);
  199.   if (ret == -1) {
  200.     if (errno == EWOULDBLOCK)
  201.       return false;
  202.     if (errno == ECONNREFUSED)
  203.       return false;
  204.     Sys_Printf ("NET_GetPacket: %s\n", strerror(errno));
  205.     return false;
  206.   }
  207.  
  208.   net_message.cursize = ret;
  209.   SockadrToNetadr (&from, &net_from);
  210.  
  211.   return ret;
  212. }
  213.  
  214. //=============================================================================
  215.  
  216. void NET_SendPacket (int length, void *data, netadr_t to)
  217. {
  218.   int ret;
  219.   struct sockaddr_in  addr;
  220.  
  221.   NetadrToSockadr (&to, &addr);
  222.  
  223.   ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
  224.   if (ret == -1) {
  225.     if (errno == EWOULDBLOCK)
  226.       return;
  227.     if (errno == ECONNREFUSED)
  228.       return;
  229.     Sys_Printf ("NET_SendPacket: %s\n", strerror(errno));
  230.   }
  231. }
  232.  
  233. //=============================================================================
  234.  
  235. int UDP_OpenSocket (int port)
  236. {
  237.   int newsocket;
  238.   struct sockaddr_in address;
  239.   qboolean _true = true;
  240.   int i;
  241.  
  242.   if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  243.     Sys_Error ("UDP_OpenSocket: socket:", strerror(errno));
  244.   if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
  245.     Sys_Error ("UDP_OpenSocket: ioctl FIONBIO:", strerror(errno));
  246.   address.sin_family = AF_INET;
  247. //ZOID -- check for interface binding option
  248.   if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) {
  249.     address.sin_addr.s_addr = inet_addr(com_argv[i+1]);
  250.     Con_Printf("Binding to IP Interface Address of %s\n",
  251.         inet_ntoa(address.sin_addr));
  252.   } else
  253.     address.sin_addr.s_addr = INADDR_ANY;
  254.   if (port == PORT_ANY)
  255.     address.sin_port = 0;
  256.   else
  257.     address.sin_port = htons((short)port);
  258.   if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  259.     Sys_Error ("UDP_OpenSocket: bind: %s", strerror(errno));
  260.  
  261.   return newsocket;
  262. }
  263.  
  264. void NET_GetLocalAddress (void)
  265. {
  266.   char  buff[MAXHOSTNAMELEN];
  267.   struct sockaddr_in  address;
  268.   int   namelen;
  269.  
  270.   gethostname(buff, MAXHOSTNAMELEN);
  271.   buff[MAXHOSTNAMELEN-1] = 0;
  272.  
  273.   NET_StringToAdr (buff, &net_local_adr);
  274.  
  275.   namelen = sizeof(address);
  276.   if (getsockname (net_socket, (struct sockaddr *)&address, &namelen) == -1)
  277.     Sys_Error ("NET_Init: getsockname:", strerror(errno));
  278.   net_local_adr.port = address.sin_port;
  279.  
  280.   Con_Printf("IP address %s\n", NET_AdrToString (net_local_adr) );
  281. }
  282.  
  283. /*
  284. ====================
  285. NET_Init
  286. ====================
  287. */
  288. void NET_Init (int port)
  289. {
  290.   //
  291.   // open the single socket to be used for all communications
  292.   //
  293.   net_socket = UDP_OpenSocket (port);
  294.  
  295.   //
  296.   // init the message buffer
  297.   //
  298.   net_message.maxsize = sizeof(net_message_buffer);
  299.   net_message.data = net_message_buffer;
  300.  
  301.   //
  302.   // determine my name & address
  303.   //
  304.   NET_GetLocalAddress ();
  305.  
  306.   Con_Printf("UDP Initialized\n");
  307. }
  308.  
  309. /*
  310. ====================
  311. NET_Shutdown
  312. ====================
  313. */
  314. void  NET_Shutdown (void)
  315. {
  316.   close (net_socket);
  317. }
  318.  
  319.