home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / net_udp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  6.8 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.