home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 15 / MA_Cover_15.iso / source / winquake / net_amigaudp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-29  |  11.9 KB  |  487 lines

  1. /*
  2. Copyright (C) 2000 Peter McGavin.
  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. #include <exec/exec.h>
  33. #ifdef __PPC__
  34. #if defined(__STORM__) || defined(__VBCC__)
  35. #include <clib/exec_protos.h>
  36. #else
  37. #include <proto/exec.h>
  38. #endif
  39. #include <clib/socket_protos.h>
  40. #else
  41. #include <proto/exec.h>
  42. #include <proto/socket.h>
  43. #endif
  44.  
  45. extern void I_Error (char *error, ...);
  46. extern cvar_t hostname;
  47.  
  48. struct Library *SocketBase = NULL;
  49.  
  50. static int net_acceptsocket = -1;        // socket for fielding new connections
  51. static int net_controlsocket = -1;
  52. static int net_broadcastsocket = 0;
  53. static struct qsockaddr broadcastaddr;
  54.  
  55. static unsigned long myAddr;
  56.  
  57. #include "net_udp.h"
  58.  
  59. //=============================================================================
  60.  
  61. int UDP_Init (void)
  62. {
  63.     struct hostent *local;
  64.     char    buff[MAXHOSTNAMELEN];
  65.     struct qsockaddr addr;
  66.     char *colon;
  67.     
  68. //    Con_Printf ("UDP_Init()\n");
  69.     if (COM_CheckParm ("-noudp"))
  70.         return -1;
  71.  
  72.         if ((SocketBase = OpenLibrary ("bsdsocket.library", 0)) == NULL) {
  73.           Con_Printf ("OpenLibrary(\"bsdsocket.library\") failed, no networking available\n");
  74.           return -1;
  75.         }
  76.  
  77.     // determine my name & address
  78.     gethostname(buff, MAXHOSTNAMELEN);
  79.     local = gethostbyname(buff);
  80.     myAddr = *(int *)local->h_addr_list[0];
  81.  
  82.     // if the quake hostname isn't set, set it to the machine name
  83.     if (Q_strcmp(hostname.string, "UNNAMED") == 0)
  84.     {
  85.         buff[15] = 0;
  86.         Cvar_Set ("hostname", buff);
  87.     }
  88.  
  89.     if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
  90.         Sys_Error("UDP_Init: Unable to open control socket\n");
  91.  
  92.     ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
  93.     ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
  94.     ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
  95.  
  96.     UDP_GetSocketAddr (net_controlsocket, &addr);
  97.     Q_strcpy(my_tcpip_address,  UDP_AddrToString (&addr));
  98.     colon = Q_strrchr (my_tcpip_address, ':');
  99.     if (colon)
  100.         *colon = 0;
  101.  
  102.     Con_Printf("UDP Initialized\n");
  103.     tcpipAvailable = true;
  104.  
  105.     return net_controlsocket;
  106. }
  107.  
  108. //=============================================================================
  109.  
  110. void UDP_Shutdown (void)
  111. {
  112. //    Con_Printf ("UDP_Shutdown()\n");
  113.     if (SocketBase != NULL) {
  114.         UDP_Listen (false);
  115.         if (net_controlsocket != -1) {
  116.             UDP_CloseSocket (net_controlsocket);
  117.             net_controlsocket = -1;
  118.         }
  119.         CloseLibrary (SocketBase);
  120.         SocketBase = NULL;
  121.     }
  122. }
  123.  
  124. //=============================================================================
  125.  
  126. void UDP_Listen (qboolean state)
  127. {
  128. //    Con_Printf ("UDP_Listen()\n");
  129.     // enable listening
  130.     if (state)
  131.     {
  132.         if (net_acceptsocket != -1)
  133.             return;
  134.         if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
  135.             Sys_Error ("UDP_Listen: Unable to open accept socket\n");
  136.         return;
  137.     }
  138.  
  139.     // disable listening
  140.     if (net_acceptsocket == -1)
  141.         return;
  142.     UDP_CloseSocket (net_acceptsocket);
  143.     net_acceptsocket = -1;
  144. }
  145.  
  146. //=============================================================================
  147.  
  148. int UDP_OpenSocket (int port)
  149. {
  150.     int newsocket;
  151.     struct sockaddr_in address;
  152.     long _true = true;
  153.  
  154. //    Con_Printf ("UDP_OpenSocket()\n");
  155.     if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  156.         return -1;
  157.  
  158.     if (IoctlSocket (newsocket, FIONBIO, (char *)&_true) == -1)
  159.         goto ErrorReturn;
  160.  
  161.     address.sin_family = AF_INET;
  162.     address.sin_addr.s_addr = INADDR_ANY;
  163.     address.sin_port = htons(port);
  164.     if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  165.         goto ErrorReturn;
  166.  
  167.     return newsocket;
  168.  
  169. ErrorReturn:
  170.     CloseSocket (newsocket);
  171.     return -1;
  172. }
  173.  
  174. //=============================================================================
  175.  
  176. int UDP_CloseSocket (int socket)
  177. {
  178. //    Con_Printf ("UDP_CloseSocket()\n");
  179.     if (socket == net_broadcastsocket)
  180.         net_broadcastsocket = 0;
  181.     return CloseSocket (socket);
  182. }
  183.  
  184.  
  185. //=============================================================================
  186. /*
  187. ============
  188. PartialIPAddress
  189.  
  190. this lets you type only as much of the net address as required, using
  191. the local network components to fill in the rest
  192. ============
  193. */
  194. static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
  195. {
  196.     char buff[256];
  197.     char *b;
  198.     int addr;
  199.     int num;
  200.     int mask;
  201.     int run;
  202.     int port;
  203.     
  204. //    Con_Printf ("UDP_PartialIPAddress()\n");
  205.     buff[0] = '.';
  206.     b = buff;
  207.     strcpy(buff+1, in);
  208.     if (buff[1] == '.')
  209.         b++;
  210.  
  211.     addr = 0;
  212.     mask=-1;
  213.     while (*b == '.')
  214.     {
  215.         b++;
  216.         num = 0;
  217.         run = 0;
  218.         while (!( *b < '0' || *b > '9'))
  219.         {
  220.           num = num*10 + *b++ - '0';
  221.           if (++run > 3)
  222.               return -1;
  223.         }
  224.         if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
  225.             return -1;
  226.         if (num < 0 || num > 255)
  227.             return -1;
  228.         mask<<=8;
  229.         addr = (addr<<8) + num;
  230.     }
  231.     
  232.     if (*b++ == ':')
  233.         port = Q_atoi(b);
  234.     else
  235.         port = net_hostport;
  236.  
  237.     ((struct sockaddr_in *)hostaddr)->sin_family = AF_INET;
  238.     ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);    
  239.     ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
  240.     
  241.     return 0;
  242. }
  243. //=============================================================================
  244.  
  245. int UDP_Connect (int socket, struct qsockaddr *addr)
  246. {
  247. //    Con_Printf ("UDP_Connect()\n");
  248.     return 0;
  249. }
  250.  
  251. //=============================================================================
  252.  
  253. int UDP_CheckNewConnections (void)
  254. {
  255.     long    available;
  256.  
  257. //    Con_Printf ("UDP_CheckNewConnections()\n");
  258.     if (net_acceptsocket == -1)
  259.         return -1;
  260.  
  261.     if (IoctlSocket (net_acceptsocket, FIONREAD, (char *)&available) == -1)
  262.         Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
  263.     if (available)
  264.         return net_acceptsocket;
  265.     return -1;
  266. }
  267.  
  268. //=============================================================================
  269.  
  270. int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
  271. {
  272.     LONG addrlen = sizeof (struct qsockaddr);
  273.     int ret;
  274.     long err;
  275.  
  276. //    Con_Printf ("UDP_Read()\n");
  277.     ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
  278.     err = Errno();
  279.     if (ret == -1 && (err == EWOULDBLOCK || err == ECONNREFUSED))
  280.         return 0;
  281.     return ret;
  282. }
  283.  
  284. //=============================================================================
  285.  
  286. int UDP_MakeSocketBroadcastCapable (int socket)
  287. {
  288.     int                i = 1;
  289.  
  290. //    Con_Printf ("UDP_MakeSocketBroadcastCapable()\n");
  291.     // make this socket broadcast capable
  292.     if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
  293.         return -1;
  294.     net_broadcastsocket = socket;
  295.  
  296.     return 0;
  297. }
  298.  
  299. //=============================================================================
  300.  
  301. int UDP_Broadcast (int socket, byte *buf, int len)
  302. {
  303.     int ret;
  304.  
  305. //    Con_Printf ("UDP_Broadcast()\n");
  306.     if (socket != net_broadcastsocket)
  307.     {
  308.         if (net_broadcastsocket != 0)
  309.             Sys_Error("Attempted to use multiple broadcasts sockets\n");
  310.         ret = UDP_MakeSocketBroadcastCapable (socket);
  311.         if (ret == -1)
  312.         {
  313.             Con_Printf("Unable to make socket broadcast capable\n");
  314.             return ret;
  315.         }
  316.     }
  317.  
  318.     return UDP_Write (socket, buf, len, &broadcastaddr);
  319. }
  320.  
  321. //=============================================================================
  322.  
  323. int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
  324. {
  325.     int ret;
  326.  
  327. //    Con_Printf ("UDP_Write()\n");
  328.     ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
  329.     if (ret == -1 && Errno() == EWOULDBLOCK)
  330.         return 0;
  331.     return ret;
  332. }
  333.  
  334. //=============================================================================
  335.  
  336. char *UDP_AddrToString (struct qsockaddr *addr)
  337. {
  338.     static char buffer[22];
  339.     int haddr;
  340.  
  341. //    Con_Printf ("UDP_AddrToString()\n");
  342.     haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
  343.     sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff,
  344.             (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff,
  345.             ntohs(((struct sockaddr_in *)addr)->sin_port));
  346.     return buffer;
  347. }
  348.  
  349. //=============================================================================
  350.  
  351. int UDP_StringToAddr (char *string, struct qsockaddr *addr)
  352. {
  353.     int ha1, ha2, ha3, ha4, hp;
  354.     int ipaddr;
  355.  
  356. //    Con_Printf ("UDP_StringToAddr()\n");
  357.     sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  358.     ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  359.  
  360.     ((struct sockaddr_in *)addr)->sin_family = AF_INET;
  361.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  362.     ((struct sockaddr_in *)addr)->sin_port = htons(hp);
  363.     return 0;
  364. }
  365.  
  366. //=============================================================================
  367.  
  368. int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
  369. {
  370.     LONG addrlen = sizeof(struct qsockaddr);
  371.     unsigned int a;
  372.  
  373. //    Con_Printf ("UDP_GetSocketAddr()\n");
  374.     Q_memset(addr, 0, sizeof(struct qsockaddr));
  375.     getsockname(socket, (struct sockaddr *)addr, &addrlen);
  376.     a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  377.     if (a == 0 || a == inet_addr("127.0.0.1"))
  378.         ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
  379.  
  380.     return 0;
  381. }
  382.  
  383. //=============================================================================
  384.  
  385. int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
  386. {
  387.     struct hostent *hostentry;
  388.  
  389. //    Con_Printf ("UDP_GetNameFromAddr()\n");
  390.     hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
  391.     if (hostentry)
  392.     {
  393.         Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
  394.         return 0;
  395.     }
  396.  
  397.     Q_strcpy (name, UDP_AddrToString (addr));
  398.     return 0;
  399. }
  400.  
  401. //=============================================================================
  402.  
  403. int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
  404. {
  405.     struct hostent *hostentry;
  406.  
  407. //    Con_Printf ("UDP_GetAddrFromName()\n");
  408.     if (name[0] >= '0' && name[0] <= '9')
  409.         return PartialIPAddress (name, addr);
  410.     
  411.     hostentry = gethostbyname (name);
  412.     if (!hostentry)
  413.         return -1;
  414.  
  415.     ((struct sockaddr_in *)addr)->sin_family = AF_INET;
  416.     ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);    
  417.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
  418.  
  419.     return 0;
  420. }
  421.  
  422. //=============================================================================
  423.  
  424. int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  425. {
  426. //    Con_Printf ("UDP_AddrCompare()\n");
  427.  
  428.     if (((struct sockaddr_in *)addr1)->sin_family !=
  429.             ((struct sockaddr_in *)addr2)->sin_family)
  430.         return -1;
  431.  
  432.     if (((struct sockaddr_in *)addr1)->sin_addr.s_addr !=
  433.             ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  434.         return -1;
  435.  
  436.     if (((struct sockaddr_in *)addr1)->sin_port !=
  437.             ((struct sockaddr_in *)addr2)->sin_port)
  438.         return 1;
  439.  
  440.     return 0;
  441. }
  442.  
  443. //=============================================================================
  444.  
  445. int UDP_GetSocketPort (struct qsockaddr *addr)
  446. {
  447. //    Con_Printf ("UDP_GetSocketPort()\n");
  448.     return ntohs(((struct sockaddr_in *)addr)->sin_port);
  449. }
  450.  
  451.  
  452. int UDP_SetSocketPort (struct qsockaddr *addr, int port)
  453. {
  454.     ((struct sockaddr_in *)addr)->sin_port = htons(port);
  455.     return 0;
  456. }
  457.  
  458. /**********************************************************************/
  459.  
  460. #ifdef __SASC
  461. void _STD_UDP_Shutdown (void)
  462. {
  463. //  Con_Printf ("_STD_UDP_Shutdown()\n");
  464.   UDP_Shutdown ();
  465. }
  466. #endif
  467.  
  468. /**********************************************************************/
  469. #ifdef __STORM__
  470. void EXIT_9_UDP_Shutdown (void)
  471. {
  472. //  Con_Printf ("EXIT_9_UDP_Shutdown()\n");
  473.   UDP_Shutdown ();
  474. }
  475. #endif
  476.  
  477. /**********************************************************************/
  478. #ifdef __VBCC__
  479. void _EXIT_9_UDP_Shutdown (void)
  480. {
  481. //  Con_Printf ("_EXIT_9_UDP_Shutdown()\n");
  482.   UDP_Shutdown ();
  483. }
  484. #endif
  485.  
  486. /**********************************************************************/
  487.