home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / net_udpamiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  7.8 KB  |  342 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.  
  21. /*
  22.  * net_udpamiga.c
  23.  * AMIGA Quake World network support
  24.  * Written by Frank Wille <frank@phoenix.owl.de>
  25.  */
  26.  
  27. #include "quakedef.h"
  28.  
  29. /* Amiga includes */
  30. #pragma amiga-align
  31. #include <exec/types.h>
  32. #include <exec/libraries.h>
  33. #include <amitcp/socketbasetags.h>
  34. #include <proto/exec.h>
  35. #include <proto/socket.h>
  36. #pragma default-align
  37.  
  38. /* AmiTCP SDK includes */
  39. #include <sys/socket.h>
  40. #include <netinet/in.h>
  41. #include <netdb.h>
  42. #include <sys/param.h>
  43. #include <sys/ioctl.h>
  44. #include <errno.h>
  45.  
  46.  
  47. struct Library *SocketBase = NULL;  /* bsdsocket.library */
  48. #define SOCKETVERSION 4             /* required version */
  49.  
  50. netadr_t  net_local_adr;
  51.  
  52. netadr_t  net_from;
  53. sizebuf_t net_message;
  54. int net_socket = -1;
  55.  
  56. #define MAX_UDP_PACKET  8192
  57. byte    net_message_buffer[MAX_UDP_PACKET];
  58.  
  59.  
  60. //=============================================================================
  61.  
  62. void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
  63. {
  64.   memset (s, 0, sizeof(*s));
  65.   s->sin_family = AF_INET;
  66.  
  67.   *(int *)&s->sin_addr = *(int *)&a->ip;
  68.   s->sin_port = a->port;
  69. }
  70.  
  71. void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
  72. {
  73.   *(int *)&a->ip = *(int *)&s->sin_addr;
  74.   a->port = s->sin_port;
  75. }
  76.  
  77. qboolean  NET_CompareBaseAdr (netadr_t a, netadr_t b)
  78. {
  79.   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])
  80.     return true;
  81.   return false;
  82. }
  83.  
  84.  
  85. qboolean  NET_CompareAdr (netadr_t a, netadr_t b)
  86. {
  87.   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)
  88.     return true;
  89.   return false;
  90. }
  91.  
  92. char  *NET_AdrToString (netadr_t a)
  93. {
  94.   static  char  s[64];
  95.   
  96.   sprintf (s, "%i.%i.%i.%i:%i", (int)a.ip[0], (int)a.ip[1],
  97.            (int)a.ip[2], (int)a.ip[3], (int)ntohs(a.port));
  98.  
  99.   return s;
  100. }
  101.  
  102. char  *NET_BaseAdrToString (netadr_t a)
  103. {
  104.   static  char  s[64];
  105.   
  106.   sprintf (s, "%i.%i.%i.%i", (int)a.ip[0], (int)a.ip[1],
  107.            (int)a.ip[2], (int)a.ip[3]);
  108.  
  109.   return s;
  110. }
  111.  
  112. /*
  113. =============
  114. NET_StringToAdr
  115.  
  116. idnewt
  117. idnewt:28000
  118. 192.246.40.70
  119. 192.246.40.70:28000
  120. =============
  121. */
  122. qboolean  NET_StringToAdr (char *s, netadr_t *a)
  123. {
  124.   struct hostent  *h;
  125.   struct sockaddr_in sadr;
  126.   char  *colon;
  127.   char  copy[128];
  128.   
  129.   
  130.   memset (&sadr, 0, sizeof(sadr));
  131.   sadr.sin_family = AF_INET;
  132.   
  133.   sadr.sin_port = 0;
  134.  
  135.   strcpy (copy, s);
  136.   // strip off a trailing :port if present
  137.   for (colon = copy ; *colon ; colon++)
  138.     if (*colon == ':')
  139.     {
  140.       *colon = 0;
  141.       sadr.sin_port = htons(atoi(colon+1)); 
  142.     }
  143.   
  144.   if (copy[0] >= '0' && copy[0] <= '9')
  145.   {
  146.     *(int *)&sadr.sin_addr = inet_addr(copy);
  147.   }
  148.   else
  149.   {
  150.     if (! (h = (struct hostent *)gethostbyname(copy)) )
  151.       return 0;
  152.     *(int *)&sadr.sin_addr = *(int *)h->h_addr_list[0];
  153.   }
  154.   
  155.   SockadrToNetadr (&sadr, a);
  156.  
  157.   return true;
  158. }
  159.  
  160. // Returns true if we can't bind the address locally--in other words, 
  161. // the IP is NOT one of our interfaces.
  162. qboolean NET_IsClientLegal(netadr_t *adr)
  163. {
  164.   return true;
  165. }
  166.  
  167. char *inet_ntoa(struct in_addr addr)
  168. {
  169.   return Inet_NtoA(addr.s_addr);
  170. }
  171.  
  172.  
  173. //=============================================================================
  174.  
  175. qboolean NET_GetPacket (void)
  176. {
  177.   int   ret;
  178.   struct sockaddr_in  from;
  179.   LONG fromlen;
  180.  
  181.   fromlen = sizeof(from);
  182.   ret = recvfrom (net_socket, (UBYTE *)net_message_buffer,
  183.                   sizeof(net_message_buffer), 0,
  184.                   (struct sockaddr *)&from, &fromlen);
  185.   if (ret == -1) {
  186.     if (errno == EWOULDBLOCK)
  187.       return false;
  188.     if (errno == ECONNREFUSED)
  189.       return false;
  190.     Sys_Printf ("NET_GetPacket: %s\n", strerror(errno));
  191.     return false;
  192.   }
  193.  
  194.   net_message.cursize = ret;
  195.   SockadrToNetadr (&from, &net_from);
  196.  
  197.   return ret;
  198. }
  199.  
  200. //=============================================================================
  201.  
  202. void NET_SendPacket (int length, void *data, netadr_t to)
  203. {
  204.   int ret;
  205.   struct sockaddr_in  addr;
  206.  
  207.   NetadrToSockadr (&to, &addr);
  208.  
  209.   ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
  210.   if (ret == -1) {
  211.     if (errno == EWOULDBLOCK)
  212.       return;
  213.     if (errno == ECONNREFUSED)
  214.       return;
  215.     Sys_Printf ("NET_SendPacket: %s\n", strerror(errno));
  216.   }
  217. }
  218.  
  219. //=============================================================================
  220.  
  221. int UDP_OpenSocket (int port)
  222. {
  223.   int newsocket;
  224.   struct sockaddr_in address;
  225.   qboolean _true = true;
  226.   int i;
  227.  
  228.   if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  229.     Sys_Error ("UDP_OpenSocket: socket:", strerror(errno));
  230.   if (IoctlSocket(newsocket, FIONBIO, (char *)&_true) == -1) {
  231.     CloseSocket(newsocket);
  232.     Sys_Error ("UDP_OpenSocket: ioctl FIONBIO:", strerror(errno));
  233.   }
  234.   address.sin_family = AF_INET;
  235. //ZOID -- check for interface binding option
  236.   if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) {
  237.     address.sin_addr.s_addr = inet_addr(com_argv[i+1]);
  238.     Con_Printf("Binding to IP Interface Address of %s\n",
  239.         inet_ntoa(address.sin_addr));
  240.   } else
  241.     address.sin_addr.s_addr = INADDR_ANY;
  242.   if (port == PORT_ANY)
  243.     address.sin_port = 0;
  244.   else
  245.     address.sin_port = htons((short)port);
  246.   if( bind (newsocket, (void *)&address, sizeof(address)) == -1) {
  247.     CloseSocket(newsocket);
  248.     Sys_Error ("UDP_OpenSocket: bind: %s", strerror(errno));
  249.   }
  250.  
  251.   return newsocket;
  252. }
  253.  
  254. void NET_GetLocalAddress (void)
  255. {
  256.   char  buff[MAXHOSTNAMELEN];
  257.   struct sockaddr_in  address;
  258.   LONG namelen;
  259.  
  260.   gethostname(buff, MAXHOSTNAMELEN);
  261.   buff[MAXHOSTNAMELEN-1] = 0;
  262.  
  263.   NET_StringToAdr (buff, &net_local_adr);
  264.  
  265.   namelen = sizeof(address);
  266.   if (getsockname (net_socket, (struct sockaddr *)&address, &namelen) == -1)
  267.     Sys_Error ("NET_Init: getsockname:", strerror(errno));
  268.   net_local_adr.port = address.sin_port;
  269.  
  270.   Con_Printf("IP address %s\n", NET_AdrToString (net_local_adr) );
  271. }
  272.  
  273. /*
  274. ====================
  275. NET_Init
  276. ====================
  277. */
  278. void NET_Init (int port)
  279. {
  280.   /* Amiga socket initialization */
  281.   if (!(SocketBase = OpenLibrary("bsdsocket.library",SOCKETVERSION)))
  282.     Sys_Error ("NET_Init: Can't open bsdsocket.library V%d",SOCKETVERSION);
  283.   if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),&errno,
  284.                          SBTM_SETVAL(SBTC_LOGTAGPTR),"QuakeWorldAmiga UDP",
  285.                          TAG_END)) {
  286.     CloseLibrary(SocketBase);
  287.     Sys_Error ("NET_Init: Can't set errno");
  288.   }
  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 via bsdsocket.library V%d initialized\n",SOCKETVERSION);
  307. }
  308.  
  309. /*
  310. ====================
  311. NET_Shutdown
  312. ====================
  313. */
  314. void  NET_Shutdown (void)
  315. {
  316.   if (SocketBase) {
  317.     if (net_socket >= 0) {
  318.       CloseSocket(net_socket);
  319.       net_socket = -1;
  320.     }
  321.     CloseLibrary(SocketBase);
  322.   }
  323. }
  324.  
  325.  
  326. /*
  327. ====================
  328. NET_Select
  329. ====================
  330. */
  331. void NET_Select (unsigned long usec)
  332. {
  333.   struct timeval timeout;
  334.   fd_set fdset;
  335.  
  336.   FD_ZERO(&fdset);
  337.   FD_SET(net_socket,&fdset);
  338.   timeout.tv_sec = usec/1000000;
  339.   timeout.tv_usec = usec%1000000;
  340.   WaitSelect(net_socket+1, &fdset, NULL, NULL, &timeout, 0);
  341. }
  342.