net_udp.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. // net_wins.c
  2. #include "../qcommon/qcommon.h"
  3. #include <unistd.h>
  4. #include <sys/socket.h>
  5. #include <sys/time.h>
  6. #include <netinet/in.h>
  7. #include <netdb.h>
  8. #include <sys/param.h>
  9. #include <sys/ioctl.h>
  10. #include <sys/uio.h>
  11. #include <errno.h>
  12. #ifdef NeXT
  13. #include <libc.h>
  14. #endif
  15. netadr_t net_local_adr;
  16. #define LOOPBACK 0x7f000001
  17. #define MAX_LOOPBACK 4
  18. typedef struct
  19. {
  20. byte data[MAX_MSGLEN];
  21. int datalen;
  22. } loopmsg_t;
  23. typedef struct
  24. {
  25. loopmsg_t msgs[MAX_LOOPBACK];
  26. int get, send;
  27. } loopback_t;
  28. loopback_t loopbacks[2];
  29. int ip_sockets[2];
  30. int ipx_sockets[2];
  31. int NET_Socket (char *net_interface, int port);
  32. char *NET_ErrorString (void);
  33. //=============================================================================
  34. void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
  35. {
  36. memset (s, 0, sizeof(*s));
  37. if (a->type == NA_BROADCAST)
  38. {
  39. s->sin_family = AF_INET;
  40. s->sin_port = a->port;
  41. *(int *)&s->sin_addr = -1;
  42. }
  43. else if (a->type == NA_IP)
  44. {
  45. s->sin_family = AF_INET;
  46. *(int *)&s->sin_addr = *(int *)&a->ip;
  47. s->sin_port = a->port;
  48. }
  49. }
  50. void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
  51. {
  52. *(int *)&a->ip = *(int *)&s->sin_addr;
  53. a->port = s->sin_port;
  54. a->type = NA_IP;
  55. }
  56. qboolean NET_CompareAdr (netadr_t a, netadr_t b)
  57. {
  58. 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)
  59. return true;
  60. return false;
  61. }
  62. /*
  63. ===================
  64. NET_CompareBaseAdr
  65. Compares without the port
  66. ===================
  67. */
  68. qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
  69. {
  70. if (a.type != b.type)
  71. return false;
  72. if (a.type == NA_LOOPBACK)
  73. return true;
  74. if (a.type == NA_IP)
  75. {
  76. 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])
  77. return true;
  78. return false;
  79. }
  80. if (a.type == NA_IPX)
  81. {
  82. if ((memcmp(a.ipx, b.ipx, 10) == 0))
  83. return true;
  84. return false;
  85. }
  86. }
  87. char *NET_AdrToString (netadr_t a)
  88. {
  89. static char s[64];
  90. Com_sprintf (s, sizeof(s), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
  91. return s;
  92. }
  93. char *NET_BaseAdrToString (netadr_t a)
  94. {
  95. static char s[64];
  96. Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
  97. return s;
  98. }
  99. /*
  100. =============
  101. NET_StringToAdr
  102. localhost
  103. idnewt
  104. idnewt:28000
  105. 192.246.40.70
  106. 192.246.40.70:28000
  107. =============
  108. */
  109. qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr)
  110. {
  111. struct hostent *h;
  112. char *colon;
  113. char copy[128];
  114. memset (sadr, 0, sizeof(*sadr));
  115. ((struct sockaddr_in *)sadr)->sin_family = AF_INET;
  116. ((struct sockaddr_in *)sadr)->sin_port = 0;
  117. strcpy (copy, s);
  118. // strip off a trailing :port if present
  119. for (colon = copy ; *colon ; colon++)
  120. if (*colon == ':')
  121. {
  122. *colon = 0;
  123. ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1));
  124. }
  125. if (copy[0] >= '0' && copy[0] <= '9')
  126. {
  127. *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy);
  128. }
  129. else
  130. {
  131. if (! (h = gethostbyname(copy)) )
  132. return 0;
  133. *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
  134. }
  135. return true;
  136. }
  137. /*
  138. =============
  139. NET_StringToAdr
  140. localhost
  141. idnewt
  142. idnewt:28000
  143. 192.246.40.70
  144. 192.246.40.70:28000
  145. =============
  146. */
  147. qboolean NET_StringToAdr (char *s, netadr_t *a)
  148. {
  149. struct sockaddr_in sadr;
  150. if (!strcmp (s, "localhost"))
  151. {
  152. memset (a, 0, sizeof(*a));
  153. a->type = NA_LOOPBACK;
  154. return true;
  155. }
  156. if (!NET_StringToSockaddr (s, (struct sockaddr *)&sadr))
  157. return false;
  158. SockadrToNetadr (&sadr, a);
  159. return true;
  160. }
  161. qboolean NET_IsLocalAddress (netadr_t adr)
  162. {
  163. return NET_CompareAdr (adr, net_local_adr);
  164. }
  165. /*
  166. =============================================================================
  167. LOOPBACK BUFFERS FOR LOCAL PLAYER
  168. =============================================================================
  169. */
  170. qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
  171. {
  172. int i;
  173. loopback_t *loop;
  174. loop = &loopbacks[sock];
  175. if (loop->send - loop->get > MAX_LOOPBACK)
  176. loop->get = loop->send - MAX_LOOPBACK;
  177. if (loop->get >= loop->send)
  178. return false;
  179. i = loop->get & (MAX_LOOPBACK-1);
  180. loop->get++;
  181. memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);
  182. net_message->cursize = loop->msgs[i].datalen;
  183. *net_from = net_local_adr;
  184. return true;
  185. }
  186. void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to)
  187. {
  188. int i;
  189. loopback_t *loop;
  190. loop = &loopbacks[sock^1];
  191. i = loop->send & (MAX_LOOPBACK-1);
  192. loop->send++;
  193. memcpy (loop->msgs[i].data, data, length);
  194. loop->msgs[i].datalen = length;
  195. }
  196. //=============================================================================
  197. qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
  198. {
  199. int ret;
  200. struct sockaddr_in from;
  201. int fromlen;
  202. int net_socket;
  203. int protocol;
  204. int err;
  205. if (NET_GetLoopPacket (sock, net_from, net_message))
  206. return true;
  207. for (protocol = 0 ; protocol < 2 ; protocol++)
  208. {
  209. if (protocol == 0)
  210. net_socket = ip_sockets[sock];
  211. else
  212. net_socket = ipx_sockets[sock];
  213. if (!net_socket)
  214. continue;
  215. fromlen = sizeof(from);
  216. ret = recvfrom (net_socket, net_message->data, net_message->maxsize
  217. , 0, (struct sockaddr *)&from, &fromlen);
  218. if (ret == -1)
  219. {
  220. err = errno;
  221. if (err == EWOULDBLOCK || err == ECONNREFUSED)
  222. continue;
  223. Com_Printf ("NET_GetPacket: %s", NET_ErrorString());
  224. continue;
  225. }
  226. if (ret == net_message->maxsize)
  227. {
  228. Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from));
  229. continue;
  230. }
  231. net_message->cursize = ret;
  232. SockadrToNetadr (&from, net_from);
  233. return true;
  234. }
  235. return false;
  236. }
  237. //=============================================================================
  238. void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
  239. {
  240. int ret;
  241. struct sockaddr_in addr;
  242. int net_socket;
  243. if ( to.type == NA_LOOPBACK )
  244. {
  245. NET_SendLoopPacket (sock, length, data, to);
  246. return;
  247. }
  248. if (to.type == NA_BROADCAST)
  249. {
  250. net_socket = ip_sockets[sock];
  251. if (!net_socket)
  252. return;
  253. }
  254. else if (to.type == NA_IP)
  255. {
  256. net_socket = ip_sockets[sock];
  257. if (!net_socket)
  258. return;
  259. }
  260. else if (to.type == NA_IPX)
  261. {
  262. net_socket = ipx_sockets[sock];
  263. if (!net_socket)
  264. return;
  265. }
  266. else if (to.type == NA_BROADCAST_IPX)
  267. {
  268. net_socket = ipx_sockets[sock];
  269. if (!net_socket)
  270. return;
  271. }
  272. else
  273. Com_Error (ERR_FATAL, "NET_SendPacket: bad address type");
  274. NetadrToSockadr (&to, &addr);
  275. ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
  276. if (ret == -1)
  277. {
  278. Com_Printf ("NET_SendPacket ERROR: %i\n", NET_ErrorString());
  279. }
  280. }
  281. //=============================================================================
  282. /*
  283. ====================
  284. NET_OpenIP
  285. ====================
  286. */
  287. void NET_OpenIP (void)
  288. {
  289. cvar_t *port, *ip;
  290. port = Cvar_Get ("port", va("%i", PORT_SERVER), CVAR_NOSET);
  291. ip = Cvar_Get ("ip", "localhost", CVAR_NOSET);
  292. if (!ip_sockets[NS_SERVER])
  293. ip_sockets[NS_SERVER] = NET_Socket (ip->string, port->value);
  294. if (!ip_sockets[NS_CLIENT])
  295. ip_sockets[NS_CLIENT] = NET_Socket (ip->string, PORT_ANY);
  296. }
  297. /*
  298. ====================
  299. NET_OpenIPX
  300. ====================
  301. */
  302. void NET_OpenIPX (void)
  303. {
  304. }
  305. /*
  306. ====================
  307. NET_Config
  308. A single player game will only use the loopback code
  309. ====================
  310. */
  311. void NET_Config (qboolean multiplayer)
  312. {
  313. int i;
  314. if (!multiplayer)
  315. { // shut down any existing sockets
  316. for (i=0 ; i<2 ; i++)
  317. {
  318. if (ip_sockets[i])
  319. {
  320. close (ip_sockets[i]);
  321. ip_sockets[i] = 0;
  322. }
  323. if (ipx_sockets[i])
  324. {
  325. close (ipx_sockets[i]);
  326. ipx_sockets[i] = 0;
  327. }
  328. }
  329. }
  330. else
  331. { // open sockets
  332. NET_OpenIP ();
  333. NET_OpenIPX ();
  334. }
  335. }
  336. //===================================================================
  337. /*
  338. ====================
  339. NET_Init
  340. ====================
  341. */
  342. void NET_Init (void)
  343. {
  344. }
  345. /*
  346. ====================
  347. NET_Socket
  348. ====================
  349. */
  350. int NET_Socket (char *net_interface, int port)
  351. {
  352. int newsocket;
  353. struct sockaddr_in address;
  354. qboolean _true = true;
  355. int i = 1;
  356. if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  357. {
  358. Com_Printf ("ERROR: UDP_OpenSocket: socket:", NET_ErrorString());
  359. return 0;
  360. }
  361. // make it non-blocking
  362. if (ioctl (newsocket, FIONBIO, &_true) == -1)
  363. {
  364. Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString());
  365. return 0;
  366. }
  367. // make it broadcast capable
  368. if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
  369. {
  370. Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString());
  371. return 0;
  372. }
  373. if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost"))
  374. address.sin_addr.s_addr = INADDR_ANY;
  375. else
  376. NET_StringToSockaddr (net_interface, (struct sockaddr *)&address);
  377. if (port == PORT_ANY)
  378. address.sin_port = 0;
  379. else
  380. address.sin_port = htons((short)port);
  381. address.sin_family = AF_INET;
  382. if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  383. {
  384. Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString());
  385. close (newsocket);
  386. return 0;
  387. }
  388. return newsocket;
  389. }
  390. /*
  391. ====================
  392. NET_Shutdown
  393. ====================
  394. */
  395. void NET_Shutdown (void)
  396. {
  397. NET_Config (false); // close sockets
  398. }
  399. /*
  400. ====================
  401. NET_ErrorString
  402. ====================
  403. */
  404. char *NET_ErrorString (void)
  405. {
  406. int code;
  407. code = errno;
  408. return strerror (code);
  409. }
  410. // sleeps msec or until net socket is ready
  411. void NET_Sleep(int msec)
  412. {
  413. struct timeval timeout;
  414. fd_set fdset;
  415. extern cvar_t *dedicated;
  416. extern qboolean stdin_active;
  417. if (!ip_sockets[NS_SERVER] || (dedicated && !dedicated->value))
  418. return; // we're not a server, just run full speed
  419. FD_ZERO(&fdset);
  420. if (stdin_active)
  421. FD_SET(0, &fdset); // stdin is processed too
  422. FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket
  423. timeout.tv_sec = msec/1000;
  424. timeout.tv_usec = (msec%1000)*1000;
  425. select(ip_sockets[NS_SERVER]+1, &fdset, NULL, NULL, &timeout);
  426. }