home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / net_bsdsocket.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  10.0 KB  |  414 lines

  1. /* 
  2. **  net_bsdsocket.c
  3. */
  4.  
  5. /* Quake includes */
  6. #include "quakedef.h"
  7.  
  8. /* Amiga includes */
  9. #pragma amiga-align
  10. #include <exec/types.h>
  11. #include <exec/libraries.h>
  12. #include <amitcp/socketbasetags.h>
  13. #include <proto/exec.h>
  14. #include <proto/socket.h>
  15.  
  16. /* standard net includes */
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <netdb.h>
  20. #include <sys/param.h>
  21. #include <sys/ioctl.h>
  22. #pragma default-align
  23. #include <errno.h>
  24.  
  25.  
  26. struct Library *SocketBase = NULL;  /* bsdsocket.library */
  27. #define SOCKETVERSION 4             /* required version */
  28.  
  29. extern cvar_t hostname;
  30.  
  31. static int net_acceptsocket = -1;        // socket for fielding new connections
  32. static int net_controlsocket;
  33. static int net_broadcastsocket = 0;
  34. static struct qsockaddr broadcastaddr;
  35.  
  36. static unsigned long myAddr;
  37.  
  38. #include "net_udp.h"
  39.  
  40.  
  41. //=============================================================================
  42.  
  43. char *inet_ntoa(struct in_addr addr)
  44. {
  45.   return Inet_NtoA(addr.s_addr);
  46. }
  47.  
  48. //=============================================================================
  49.  
  50. int UDP_Init (void)
  51. {
  52.     int        p;
  53.     struct hostent *local;
  54.     char    buff[MAXHOSTNAMELEN];
  55.     struct qsockaddr addr;
  56.     char *colon;
  57.     
  58.   if (COM_CheckParm ("-noudp"))
  59.     return (-1);
  60.  
  61.   /* Amiga socket initialization */
  62.   if (!(SocketBase = OpenLibrary("bsdsocket.library",SOCKETVERSION)))
  63.     return (-1);
  64.   if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),&errno,
  65.                          SBTM_SETVAL(SBTC_LOGTAGPTR),"QuakeAmiga UDP",
  66.                          TAG_END)) {
  67.     CloseLibrary(SocketBase);
  68.     return (-1);
  69.   }
  70.  
  71.     p = COM_CheckParm ("-udpport");
  72.     if (p == 0)
  73.         net_hostport = DEFAULTnet_hostport;
  74.     else if (p < com_argc-1)
  75.         net_hostport = Q_atoi (com_argv[p+1]);
  76.     else
  77.         Sys_Error ("UDP_Init: you must specify a number after -udpport");
  78.  
  79.     // determine my name & address
  80.     gethostname(buff, MAXHOSTNAMELEN);
  81.     local = gethostbyname(buff);
  82.     myAddr = *(int *)local->h_addr_list[0];
  83.  
  84.     // if the quake hostname isn't set, set it to the machine name
  85.     if (Q_strcmp(hostname.string, "UNNAMED") == 0)
  86.     {
  87.         buff[15] = 0;
  88.         Cvar_Set ("hostname", buff);
  89.     }
  90.  
  91.     if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
  92.         Sys_Error("UDP_Init: Unable to open control socket\n");
  93.  
  94.     ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
  95.     ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
  96.     ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
  97.  
  98.     UDP_GetSocketAddr (net_controlsocket, &addr);
  99.     Q_strcpy(my_tcpip_address,  UDP_AddrToString (&addr));
  100.     colon = Q_strrchr (my_tcpip_address, ':');
  101.     if (colon)
  102.         *colon = 0;
  103.  
  104.   Con_Printf("bsdsocket.library V%d TCP/IP\n",SOCKETVERSION);
  105.   tcpipAvailable = true;
  106.  
  107.   return net_controlsocket;
  108. }
  109.  
  110. //=============================================================================
  111.  
  112. void UDP_Shutdown (void)
  113. {
  114.   if (SocketBase) {
  115.     UDP_Listen (false);
  116.     UDP_CloseSocket (net_controlsocket);
  117.     CloseLibrary(SocketBase);
  118.   }
  119. }
  120.  
  121. //=============================================================================
  122.  
  123. void UDP_Listen (qboolean state)
  124. {
  125.     // enable listening
  126.     if (state)
  127.     {
  128.         if (net_acceptsocket != -1)
  129.             return;
  130.         if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
  131.             Sys_Error ("UDP_Listen: Unable to open accept socket\n");
  132.         return;
  133.     }
  134.  
  135.     // disable listening
  136.     if (net_acceptsocket == -1)
  137.         return;
  138.     UDP_CloseSocket (net_acceptsocket);
  139.     net_acceptsocket = -1;
  140. }
  141.  
  142. //=============================================================================
  143.  
  144. int UDP_OpenSocket (int port)
  145. {
  146.     int newsocket;
  147.     struct sockaddr_in address;
  148.     qboolean _true = true;
  149.  
  150.     if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  151.         return -1;
  152.  
  153.     if (IoctlSocket (newsocket, FIONBIO, (char *)&_true) == -1)
  154.         goto ErrorReturn;
  155.  
  156.     address.sin_family = AF_INET;
  157.     address.sin_addr.s_addr = INADDR_ANY;
  158.     address.sin_port = htons(port);
  159.     if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  160.         goto ErrorReturn;
  161.  
  162.     return newsocket;
  163.  
  164. ErrorReturn:
  165.   CloseSocket(newsocket);
  166.     return -1;
  167. }
  168.  
  169. //=============================================================================
  170.  
  171. int UDP_CloseSocket (int socket)
  172. {
  173.     if (socket == net_broadcastsocket)
  174.         net_broadcastsocket = 0;
  175.   return (CloseSocket(socket));
  176. }
  177.  
  178.  
  179. //=============================================================================
  180. /*
  181. ============
  182. PartialIPAddress
  183.  
  184. this lets you type only as much of the net address as required, using
  185. the local network components to fill in the rest
  186. ============
  187. */
  188. static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
  189. {
  190.     char buff[256];
  191.     char *b;
  192.     int addr;
  193.     int num;
  194.     int mask;
  195.     
  196.     buff[0] = '.';
  197.     b = buff;
  198.     strcpy(buff+1, in);
  199.     if (buff[1] == '.') b++;
  200.  
  201.     addr = 0;
  202.     mask=-1;
  203.     while (*b == '.')
  204.     {
  205.         num = 0;
  206.         if (*++b < '0' || *b > '9') return -1;
  207.         while (!( *b < '0' || *b > '9'))
  208.           num = num*10 + *(b++) - '0';
  209.         mask<<=8;
  210.         addr = (addr<<8) + num;
  211.     }
  212.     
  213.     hostaddr->sa_family = AF_INET;
  214.     ((struct sockaddr_in *)hostaddr)->sin_port = htons(net_hostport);    
  215.     ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
  216.     
  217.     return 0;
  218. }
  219. //=============================================================================
  220.  
  221. int UDP_Connect (int socket, struct qsockaddr *addr)
  222. {
  223.     return 0;
  224. }
  225.  
  226. //=============================================================================
  227.  
  228. int UDP_CheckNewConnections (void)
  229. {
  230.     char buf[4];
  231.  
  232.     if (net_acceptsocket == -1)
  233.         return -1;
  234.  
  235.     if (recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
  236.         return net_acceptsocket;
  237.     return -1;
  238. }
  239.  
  240. //=============================================================================
  241.  
  242. int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
  243. {
  244.     LONG addrlen = sizeof (struct qsockaddr);
  245.     int ret;
  246.  
  247.     ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
  248.     if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
  249.         return 0;
  250.     return ret;
  251. }
  252.  
  253. //=============================================================================
  254.  
  255. int UDP_MakeSocketBroadcastCapable (int socket)
  256. {
  257.     int                i = 1;
  258.  
  259.     // make this socket broadcast capable
  260.     if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i)) < 0)
  261.         return -1;
  262.     net_broadcastsocket = socket;
  263.  
  264.     return 0;
  265. }
  266.  
  267. //=============================================================================
  268.  
  269. int UDP_Broadcast (int socket, byte *buf, int len)
  270. {
  271.     int ret;
  272.  
  273.     if (socket != net_broadcastsocket)
  274.     {
  275.         if (net_broadcastsocket != 0)
  276.             Sys_Error("Attempted to use multiple broadcasts sockets\n");
  277.         ret = UDP_MakeSocketBroadcastCapable (socket);
  278.         if (ret == -1)
  279.         {
  280.             Con_Printf("Unable to make socket broadcast capable\n");
  281.             return ret;
  282.         }
  283.     }
  284.  
  285.     return UDP_Write (socket, buf, len, &broadcastaddr);
  286. }
  287.  
  288. //=============================================================================
  289.  
  290. int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
  291. {
  292.     int ret;
  293.  
  294.     ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
  295.     if (ret == -1 && errno == EWOULDBLOCK)
  296.         return 0;
  297.     return ret;
  298. }
  299.  
  300. //=============================================================================
  301.  
  302. char *UDP_AddrToString (struct qsockaddr *addr)
  303. {
  304.     static char buffer[22];
  305.     int haddr;
  306.  
  307.   haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
  308.   sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff,
  309.           (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, 
  310.           (int)ntohs(((struct sockaddr_in *)addr)->sin_port));
  311.   return buffer;
  312. }
  313.  
  314. //=============================================================================
  315.  
  316. int UDP_StringToAddr (char *string, struct qsockaddr *addr)
  317. {
  318.     int ha1, ha2, ha3, ha4, hp;
  319.     int ipaddr;
  320.  
  321.     sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  322.     ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  323.  
  324.     addr->sa_family = AF_INET;
  325.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  326.     ((struct sockaddr_in *)addr)->sin_port = htons(hp);
  327.     return 0;
  328. }
  329.  
  330. //=============================================================================
  331.  
  332. int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
  333. {
  334.     LONG addrlen = sizeof(struct qsockaddr);
  335.     unsigned int a;
  336.  
  337.     Q_memset(addr, 0, sizeof(struct qsockaddr));
  338.     getsockname(socket, (struct sockaddr *)addr, &addrlen);
  339.     a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  340.     if (a == 0 || a == inet_addr("127.0.0.1"))
  341.         ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
  342.  
  343.     return 0;
  344. }
  345.  
  346. //=============================================================================
  347.  
  348. int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
  349. {
  350.     struct hostent *hostentry;
  351.  
  352.     hostentry = (struct hostent *)gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
  353.     if (hostentry)
  354.     {
  355.         Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
  356.         return 0;
  357.     }
  358.  
  359.     Q_strcpy (name, UDP_AddrToString (addr));
  360.     return 0;
  361. }
  362.  
  363. //=============================================================================
  364.  
  365. int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
  366. {
  367.     struct hostent *hostentry;
  368.  
  369.     if (name[0] >= '0' && name[0] <= '9')
  370.         return PartialIPAddress (name, addr);
  371.     
  372.     hostentry = gethostbyname (name);
  373.     if (!hostentry)
  374.         return -1;
  375.  
  376.     addr->sa_family = AF_INET;
  377.     ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);    
  378.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
  379.  
  380.     return 0;
  381. }
  382.  
  383. //=============================================================================
  384.  
  385. int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  386. {
  387.     if ((addr1->sa_family&0xff) != (addr2->sa_family&0xff))
  388.         return -1;
  389.  
  390.     if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  391.         return -1;
  392.  
  393.     if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
  394.         return 1;
  395.  
  396.     return 0;
  397. }
  398.  
  399. //=============================================================================
  400.  
  401. int UDP_GetSocketPort (struct qsockaddr *addr)
  402. {
  403.     return ntohs(((struct sockaddr_in *)addr)->sin_port);
  404. }
  405.  
  406.  
  407. int UDP_SetSocketPort (struct qsockaddr *addr, int port)
  408. {
  409.     ((struct sockaddr_in *)addr)->sin_port = htons(port);
  410.     return 0;
  411. }
  412.  
  413. //=============================================================================
  414.