net_udp.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // net_main.c
  16. #include "quakedef.h"
  17. #include <sys/types.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #include <netdb.h>
  21. #include <sys/param.h>
  22. #include <sys/ioctl.h>
  23. #include <sys/uio.h>
  24. #include <arpa/inet.h>
  25. #include <errno.h>
  26. #if defined(sun)
  27. #include <unistd.h>
  28. #endif
  29. #ifdef sun
  30. #include <sys/filio.h>
  31. #endif
  32. #ifdef NeXT
  33. #include <libc.h>
  34. #endif
  35. netadr_t net_local_adr;
  36. netadr_t net_from;
  37. sizebuf_t net_message;
  38. int net_socket; // non blocking, for receives
  39. int net_send_socket; // blocking, for sends
  40. #define MAX_UDP_PACKET 8192
  41. byte net_message_buffer[MAX_UDP_PACKET];
  42. int gethostname (char *, int);
  43. int close (int);
  44. //=============================================================================
  45. void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
  46. {
  47. memset (s, 0, sizeof(*s));
  48. s->sin_family = AF_INET;
  49. *(int *)&s->sin_addr = *(int *)&a->ip;
  50. s->sin_port = a->port;
  51. }
  52. void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
  53. {
  54. *(int *)&a->ip = *(int *)&s->sin_addr;
  55. a->port = s->sin_port;
  56. }
  57. qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
  58. {
  59. 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])
  60. return true;
  61. return false;
  62. }
  63. qboolean NET_CompareAdr (netadr_t a, netadr_t b)
  64. {
  65. 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)
  66. return true;
  67. return false;
  68. }
  69. char *NET_AdrToString (netadr_t a)
  70. {
  71. static char s[64];
  72. sprintf (s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
  73. return s;
  74. }
  75. char *NET_BaseAdrToString (netadr_t a)
  76. {
  77. static char s[64];
  78. sprintf (s, "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
  79. return s;
  80. }
  81. /*
  82. =============
  83. NET_StringToAdr
  84. idnewt
  85. idnewt:28000
  86. 192.246.40.70
  87. 192.246.40.70:28000
  88. =============
  89. */
  90. qboolean NET_StringToAdr (char *s, netadr_t *a)
  91. {
  92. struct hostent *h;
  93. struct sockaddr_in sadr;
  94. char *colon;
  95. char copy[128];
  96. memset (&sadr, 0, sizeof(sadr));
  97. sadr.sin_family = AF_INET;
  98. sadr.sin_port = 0;
  99. strcpy (copy, s);
  100. // strip off a trailing :port if present
  101. for (colon = copy ; *colon ; colon++)
  102. if (*colon == ':')
  103. {
  104. *colon = 0;
  105. sadr.sin_port = htons(atoi(colon+1));
  106. }
  107. if (copy[0] >= '0' && copy[0] <= '9')
  108. {
  109. *(int *)&sadr.sin_addr = inet_addr(copy);
  110. }
  111. else
  112. {
  113. if (! (h = gethostbyname(copy)) )
  114. return 0;
  115. *(int *)&sadr.sin_addr = *(int *)h->h_addr_list[0];
  116. }
  117. SockadrToNetadr (&sadr, a);
  118. return true;
  119. }
  120. // Returns true if we can't bind the address locally--in other words,
  121. // the IP is NOT one of our interfaces.
  122. qboolean NET_IsClientLegal(netadr_t *adr)
  123. {
  124. struct sockaddr_in sadr;
  125. int newsocket;
  126. #if 0
  127. if (adr->ip[0] == 127)
  128. return false; // no local connections period
  129. NetadrToSockadr (adr, &sadr);
  130. if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  131. Sys_Error ("NET_IsClientLegal: socket:", strerror(errno));
  132. sadr.sin_port = 0;
  133. if( bind (newsocket, (void *)&sadr, sizeof(sadr)) == -1)
  134. {
  135. // It is not a local address
  136. close(newsocket);
  137. return true;
  138. }
  139. close(newsocket);
  140. return false;
  141. #else
  142. return true;
  143. #endif
  144. }
  145. //=============================================================================
  146. qboolean NET_GetPacket (void)
  147. {
  148. int ret;
  149. struct sockaddr_in from;
  150. int fromlen;
  151. fromlen = sizeof(from);
  152. ret = recvfrom (net_socket, net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr *)&from, &fromlen);
  153. if (ret == -1) {
  154. if (errno == EWOULDBLOCK)
  155. return false;
  156. if (errno == ECONNREFUSED)
  157. return false;
  158. Sys_Printf ("NET_GetPacket: %s\n", strerror(errno));
  159. return false;
  160. }
  161. net_message.cursize = ret;
  162. SockadrToNetadr (&from, &net_from);
  163. return ret;
  164. }
  165. //=============================================================================
  166. void NET_SendPacket (int length, void *data, netadr_t to)
  167. {
  168. int ret;
  169. struct sockaddr_in addr;
  170. NetadrToSockadr (&to, &addr);
  171. ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
  172. if (ret == -1) {
  173. if (errno == EWOULDBLOCK)
  174. return;
  175. if (errno == ECONNREFUSED)
  176. return;
  177. Sys_Printf ("NET_SendPacket: %s\n", strerror(errno));
  178. }
  179. }
  180. //=============================================================================
  181. int UDP_OpenSocket (int port)
  182. {
  183. int newsocket;
  184. struct sockaddr_in address;
  185. qboolean _true = true;
  186. int i;
  187. if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  188. Sys_Error ("UDP_OpenSocket: socket:", strerror(errno));
  189. if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
  190. Sys_Error ("UDP_OpenSocket: ioctl FIONBIO:", strerror(errno));
  191. address.sin_family = AF_INET;
  192. //ZOID -- check for interface binding option
  193. if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) {
  194. address.sin_addr.s_addr = inet_addr(com_argv[i+1]);
  195. Con_Printf("Binding to IP Interface Address of %s\n",
  196. inet_ntoa(address.sin_addr));
  197. } else
  198. address.sin_addr.s_addr = INADDR_ANY;
  199. if (port == PORT_ANY)
  200. address.sin_port = 0;
  201. else
  202. address.sin_port = htons((short)port);
  203. if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  204. Sys_Error ("UDP_OpenSocket: bind: %s", strerror(errno));
  205. return newsocket;
  206. }
  207. void NET_GetLocalAddress (void)
  208. {
  209. char buff[MAXHOSTNAMELEN];
  210. struct sockaddr_in address;
  211. int namelen;
  212. gethostname(buff, MAXHOSTNAMELEN);
  213. buff[MAXHOSTNAMELEN-1] = 0;
  214. NET_StringToAdr (buff, &net_local_adr);
  215. namelen = sizeof(address);
  216. if (getsockname (net_socket, (struct sockaddr *)&address, &namelen) == -1)
  217. Sys_Error ("NET_Init: getsockname:", strerror(errno));
  218. net_local_adr.port = address.sin_port;
  219. Con_Printf("IP address %s\n", NET_AdrToString (net_local_adr) );
  220. }
  221. /*
  222. ====================
  223. NET_Init
  224. ====================
  225. */
  226. void NET_Init (int port)
  227. {
  228. //
  229. // open the single socket to be used for all communications
  230. //
  231. net_socket = UDP_OpenSocket (port);
  232. //
  233. // init the message buffer
  234. //
  235. net_message.maxsize = sizeof(net_message_buffer);
  236. net_message.data = net_message_buffer;
  237. //
  238. // determine my name & address
  239. //
  240. NET_GetLocalAddress ();
  241. Con_Printf("UDP Initialized\n");
  242. }
  243. /*
  244. ====================
  245. NET_Shutdown
  246. ====================
  247. */
  248. void NET_Shutdown (void)
  249. {
  250. close (net_socket);
  251. }