net_wins.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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_wins.c
  16. #include "quakedef.h"
  17. #include "winquake.h"
  18. netadr_t net_local_adr;
  19. netadr_t net_from;
  20. sizebuf_t net_message;
  21. int net_socket;
  22. #define MAX_UDP_PACKET (MAX_MSGLEN*2) // one more than msg + header
  23. byte net_message_buffer[MAX_UDP_PACKET];
  24. WSADATA winsockdata;
  25. //=============================================================================
  26. void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
  27. {
  28. memset (s, 0, sizeof(*s));
  29. s->sin_family = AF_INET;
  30. *(int *)&s->sin_addr = *(int *)&a->ip;
  31. s->sin_port = a->port;
  32. }
  33. void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
  34. {
  35. *(int *)&a->ip = *(int *)&s->sin_addr;
  36. a->port = s->sin_port;
  37. }
  38. qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
  39. {
  40. 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])
  41. return true;
  42. return false;
  43. }
  44. qboolean NET_CompareAdr (netadr_t a, netadr_t b)
  45. {
  46. 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)
  47. return true;
  48. return false;
  49. }
  50. char *NET_AdrToString (netadr_t a)
  51. {
  52. static char s[64];
  53. sprintf (s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
  54. return s;
  55. }
  56. char *NET_BaseAdrToString (netadr_t a)
  57. {
  58. static char s[64];
  59. sprintf (s, "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
  60. return s;
  61. }
  62. /*
  63. =============
  64. NET_StringToAdr
  65. idnewt
  66. idnewt:28000
  67. 192.246.40.70
  68. 192.246.40.70:28000
  69. =============
  70. */
  71. qboolean NET_StringToAdr (char *s, netadr_t *a)
  72. {
  73. struct hostent *h;
  74. struct sockaddr_in sadr;
  75. char *colon;
  76. char copy[128];
  77. memset (&sadr, 0, sizeof(sadr));
  78. sadr.sin_family = AF_INET;
  79. sadr.sin_port = 0;
  80. strcpy (copy, s);
  81. // strip off a trailing :port if present
  82. for (colon = copy ; *colon ; colon++)
  83. if (*colon == ':')
  84. {
  85. *colon = 0;
  86. sadr.sin_port = htons((short)atoi(colon+1));
  87. }
  88. if (copy[0] >= '0' && copy[0] <= '9')
  89. {
  90. *(int *)&sadr.sin_addr = inet_addr(copy);
  91. }
  92. else
  93. {
  94. if ((h = gethostbyname(copy)) == 0)
  95. return 0;
  96. *(int *)&sadr.sin_addr = *(int *)h->h_addr_list[0];
  97. }
  98. SockadrToNetadr (&sadr, a);
  99. return true;
  100. }
  101. // Returns true if we can't bind the address locally--in other words,
  102. // the IP is NOT one of our interfaces.
  103. qboolean NET_IsClientLegal(netadr_t *adr)
  104. {
  105. struct sockaddr_in sadr;
  106. int newsocket;
  107. #if 0
  108. if (adr->ip[0] == 127)
  109. return false; // no local connections period
  110. NetadrToSockadr (adr, &sadr);
  111. if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  112. Sys_Error ("NET_IsClientLegal: socket:", strerror(errno));
  113. sadr.sin_port = 0;
  114. if( bind (newsocket, (void *)&sadr, sizeof(sadr)) == -1)
  115. {
  116. // It is not a local address
  117. close(newsocket);
  118. return true;
  119. }
  120. close(newsocket);
  121. return false;
  122. #else
  123. return true;
  124. #endif
  125. }
  126. //=============================================================================
  127. qboolean NET_GetPacket (void)
  128. {
  129. int ret;
  130. struct sockaddr_in from;
  131. int fromlen;
  132. fromlen = sizeof(from);
  133. ret = recvfrom (net_socket, (char *)net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr *)&from, &fromlen);
  134. SockadrToNetadr (&from, &net_from);
  135. if (ret == -1)
  136. {
  137. int errno = WSAGetLastError();
  138. if (errno == WSAEWOULDBLOCK)
  139. return false;
  140. if (errno == WSAEMSGSIZE) {
  141. Con_Printf ("Warning: Oversize packet from %s\n",
  142. NET_AdrToString (net_from));
  143. return false;
  144. }
  145. Sys_Error ("NET_GetPacket: %s", strerror(errno));
  146. }
  147. net_message.cursize = ret;
  148. if (ret == sizeof(net_message_buffer) )
  149. {
  150. Con_Printf ("Oversize packet from %s\n", NET_AdrToString (net_from));
  151. return false;
  152. }
  153. return ret;
  154. }
  155. //=============================================================================
  156. void NET_SendPacket (int length, void *data, netadr_t to)
  157. {
  158. int ret;
  159. struct sockaddr_in addr;
  160. NetadrToSockadr (&to, &addr);
  161. ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
  162. if (ret == -1)
  163. {
  164. int err = WSAGetLastError();
  165. // wouldblock is silent
  166. if (err == WSAEWOULDBLOCK)
  167. return;
  168. #ifndef SERVERONLY
  169. if (err == WSAEADDRNOTAVAIL)
  170. Con_DPrintf("NET_SendPacket Warning: %i\n", err);
  171. else
  172. #endif
  173. Con_Printf ("NET_SendPacket ERROR: %i\n", errno);
  174. }
  175. }
  176. //=============================================================================
  177. int UDP_OpenSocket (int port)
  178. {
  179. int newsocket;
  180. struct sockaddr_in address;
  181. unsigned long _true = true;
  182. int i;
  183. if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  184. Sys_Error ("UDP_OpenSocket: socket:", strerror(errno));
  185. if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
  186. Sys_Error ("UDP_OpenSocket: ioctl FIONBIO:", strerror(errno));
  187. address.sin_family = AF_INET;
  188. //ZOID -- check for interface binding option
  189. if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) {
  190. address.sin_addr.s_addr = inet_addr(com_argv[i+1]);
  191. Con_Printf("Binding to IP Interface Address of %s\n",
  192. inet_ntoa(address.sin_addr));
  193. } else
  194. address.sin_addr.s_addr = INADDR_ANY;
  195. if (port == PORT_ANY)
  196. address.sin_port = 0;
  197. else
  198. address.sin_port = htons((short)port);
  199. if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  200. Sys_Error ("UDP_OpenSocket: bind: %s", strerror(errno));
  201. return newsocket;
  202. }
  203. void NET_GetLocalAddress (void)
  204. {
  205. char buff[512];
  206. struct sockaddr_in address;
  207. int namelen;
  208. gethostname(buff, 512);
  209. buff[512-1] = 0;
  210. NET_StringToAdr (buff, &net_local_adr);
  211. namelen = sizeof(address);
  212. if (getsockname (net_socket, (struct sockaddr *)&address, &namelen) == -1)
  213. Sys_Error ("NET_Init: getsockname:", strerror(errno));
  214. net_local_adr.port = address.sin_port;
  215. Con_Printf("IP address %s\n", NET_AdrToString (net_local_adr) );
  216. }
  217. /*
  218. ====================
  219. NET_Init
  220. ====================
  221. */
  222. void NET_Init (int port)
  223. {
  224. WORD wVersionRequested;
  225. int r;
  226. wVersionRequested = MAKEWORD(1, 1);
  227. r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
  228. if (r)
  229. Sys_Error ("Winsock initialization failed.");
  230. //
  231. // open the single socket to be used for all communications
  232. //
  233. net_socket = UDP_OpenSocket (port);
  234. //
  235. // init the message buffer
  236. //
  237. net_message.maxsize = sizeof(net_message_buffer);
  238. net_message.data = net_message_buffer;
  239. //
  240. // determine my name & address
  241. //
  242. NET_GetLocalAddress ();
  243. Con_Printf("UDP Initialized\n");
  244. }
  245. /*
  246. ====================
  247. NET_Shutdown
  248. ====================
  249. */
  250. void NET_Shutdown (void)
  251. {
  252. closesocket (net_socket);
  253. WSACleanup ();
  254. }