Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 0
  138.         if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
  139.                 goto ErrorReturn;
  140. #endif
  141.         address.sin_family = AF_INET;
  142.         address.sin_addr.s_addr = INADDR_ANY;
  143.         address.sin_port = htons(port);
  144.         if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  145.                 goto ErrorReturn;
  146.  
  147.         return newsocket;
  148.  
  149. ErrorReturn:
  150.         close (newsocket);
  151.         return -1;
  152. }
  153.  
  154. //=============================================================================
  155.  
  156. int UDP_CloseSocket (int socket)
  157. {
  158.         if (socket == net_broadcastsocket)
  159.                 net_broadcastsocket = 0;
  160.         return close (socket);
  161. }
  162.  
  163.  
  164. //=============================================================================
  165. /*
  166. ============
  167. PartialIPAddress
  168.  
  169. this lets you type only as much of the net address as required, using
  170. the local network components to fill in the rest
  171. ============
  172. */
  173. static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
  174. {
  175.         char buff[256];
  176.         char *b;
  177.         int addr;
  178.         int num;
  179.         int mask;
  180.         int run;
  181.         int port;
  182.        
  183.         buff[0] = '.';
  184.         b = buff;
  185.         strcpy(buff+1, in);
  186.         if (buff[1] == '.')
  187.                 b++;
  188.  
  189.         addr = 0;
  190.         mask=-1;
  191.         while (*b == '.')
  192.         {
  193.                 b++;
  194.                 num = 0;
  195.                 run = 0;
  196.                 while (!( *b < '0' || *b > '9'))
  197.                 {
  198.                   num = num*10 + *b++ - '0';
  199.                   if (++run > 3)
  200.                         return -1;
  201.                 }
  202.                 if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
  203.                         return -1;
  204.                 if (num < 0 || num > 255)
  205.                         return -1;
  206.                 mask<<=8;
  207.                 addr = (addr<<8) + num;
  208.         }
  209.        
  210.         if (*b++ == ':')
  211.                 port = Q_atoi(b);
  212.         else
  213.                 port = net_hostport;
  214.  
  215.         hostaddr->sa_family = AF_INET;
  216.         ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);       
  217.         ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
  218.        
  219.         return 0;
  220. }
  221. //=============================================================================
  222.  
  223. int UDP_Connect (int socket, struct qsockaddr *addr)
  224. {
  225.         return 0;
  226. }
  227.  
  228. //=============================================================================
  229.  
  230. int UDP_CheckNewConnections (void)
  231. {
  232.         unsigned long   available;
  233.  
  234.         if (net_acceptsocket == -1)
  235.                 return -1;
  236.  
  237.         if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
  238.                 Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
  239.         if (available)
  240.                 return net_acceptsocket;
  241.         return -1;
  242. }
  243.  
  244. //=============================================================================
  245.  
  246. int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
  247. {
  248.         int addrlen = sizeof (struct qsockaddr);
  249.         int ret;
  250.  
  251.         ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
  252.         if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
  253.                 return 0;
  254.         return ret;
  255. }
  256.  
  257. //=============================================================================
  258.  
  259. int UDP_MakeSocketBroadcastCapable (int socket)
  260. {
  261.         int                             i = 1;
  262.  
  263.         // make this socket broadcast capable
  264.         if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
  265.                 return -1;
  266.         net_broadcastsocket = socket;
  267.  
  268.         return 0;
  269. }
  270.  
  271. //=============================================================================
  272.  
  273. int UDP_Broadcast (int socket, byte *buf, int len)
  274. {
  275.         int ret;
  276.  
  277.         if (socket != net_broadcastsocket)
  278.         {
  279.                 if (net_broadcastsocket != 0)
  280.                         Sys_Error("Attempted to use multiple broadcasts sockets\n");
  281.                 ret = UDP_MakeSocketBroadcastCapable (socket);
  282.                 if (ret == -1)
  283.                 {
  284.                         Con_Printf("Unable to make socket broadcast capable\n");
  285.                         return ret;
  286.                 }
  287.         }
  288.  
  289.         return UDP_Write (socket, buf, len, &broadcastaddr);
  290. }
  291.  
  292. //=============================================================================
  293.  
  294. int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
  295. {
  296.         int ret;
  297.  
  298.         ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
  299.         if (ret == -1 && errno == EWOULDBLOCK)
  300.                 return 0;
  301.         return ret;
  302. }
  303.  
  304. //=============================================================================
  305.  
  306. char *UDP_AddrToString (struct qsockaddr *addr)
  307. {
  308.         static char buffer[22];
  309.         int haddr;
  310.  
  311.         haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
  312.         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));
  313.         return buffer;
  314. }
  315.  
  316. //=============================================================================
  317.  
  318. int UDP_StringToAddr (char *string, struct qsockaddr *addr)
  319. {
  320.         int ha1, ha2, ha3, ha4, hp;
  321.         int ipaddr;
  322.  
  323.         sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  324.         ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  325.  
  326.         addr->sa_family = AF_INET;
  327.         ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  328.         ((struct sockaddr_in *)addr)->sin_port = htons(hp);
  329.         return 0;
  330. }
  331.  
  332. //=============================================================================
  333.  
  334. int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
  335. {
  336.         int addrlen = sizeof(struct qsockaddr);
  337.         unsigned int a;
  338.  
  339.         Q_memset(addr, 0, sizeof(struct qsockaddr));
  340.         getsockname(socket, (struct sockaddr *)addr, &addrlen);
  341.         a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  342.         if (a == 0 || a == inet_addr("127.0.0.1"))
  343.                 ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
  344.  
  345.         return 0;
  346. }
  347.  
  348. //=============================================================================
  349.  
  350. int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
  351. {
  352.         struct hostent *hostentry;
  353.  
  354.         hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
  355.         if (hostentry)
  356.         {
  357.                 Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
  358.                 return 0;
  359.         }
  360.  
  361.         Q_strcpy (name, UDP_AddrToString (addr));
  362.         return 0;
  363. }
  364.  
  365. //=============================================================================
  366.  
  367. int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
  368. {
  369.         struct hostent *hostentry;
  370.  
  371.         if (name[0] >= '0' && name[0] <= '9')
  372.                 return PartialIPAddress (name, addr);
  373.        
  374.         hostentry = gethostbyname (name);
  375.         if (!hostentry)
  376.                 return -1;
  377.  
  378.         addr->sa_family = AF_INET;
  379.         ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);  
  380.         ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
  381.  
  382.         return 0;
  383. }
  384.  
  385. //=============================================================================
  386.  
  387. int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  388. {
  389.         if (addr1->sa_family != addr2->sa_family)
  390.                 return -1;
  391.  
  392.         if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  393.                 return -1;
  394.  
  395.         if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
  396.                 return 1;
  397.  
  398.         return 0;
  399. }
  400.  
  401. //=============================================================================
  402.  
  403. int UDP_GetSocketPort (struct qsockaddr *addr)
  404. {
  405.         return ntohs(((struct sockaddr_in *)addr)->sin_port);
  406. }
  407.  
  408.  
  409. int UDP_SetSocketPort (struct qsockaddr *addr, int port)
  410. {
  411.         ((struct sockaddr_in *)addr)->sin_port = htons(port);
  412.         return 0;
  413. }
  414.  
  415. //=============================================================================
  416.