unix_net.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. // unix_net.c
  2. #include "../game/q_shared.h"
  3. #include "../qcommon/qcommon.h"
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <sys/time.h>
  7. #include <netinet/in.h>
  8. #include <netdb.h>
  9. #include <sys/param.h>
  10. #include <sys/ioctl.h>
  11. #include <sys/uio.h>
  12. #include <errno.h>
  13. #ifdef NeXT
  14. #include <libc.h>
  15. #endif
  16. static cvar_t *noudp;
  17. netadr_t net_local_adr;
  18. int ip_socket;
  19. int ipx_socket;
  20. #define MAX_IPS 16
  21. static int numIP;
  22. static byte localIP[MAX_IPS][4];
  23. int NET_Socket (char *net_interface, int port);
  24. char *NET_ErrorString (void);
  25. //=============================================================================
  26. void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
  27. {
  28. memset (s, 0, sizeof(*s));
  29. if (a->type == NA_BROADCAST)
  30. {
  31. s->sin_family = AF_INET;
  32. s->sin_port = a->port;
  33. *(int *)&s->sin_addr = -1;
  34. }
  35. else if (a->type == NA_IP)
  36. {
  37. s->sin_family = AF_INET;
  38. *(int *)&s->sin_addr = *(int *)&a->ip;
  39. s->sin_port = a->port;
  40. }
  41. }
  42. void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
  43. {
  44. *(int *)&a->ip = *(int *)&s->sin_addr;
  45. a->port = s->sin_port;
  46. a->type = NA_IP;
  47. }
  48. char *NET_BaseAdrToString (netadr_t a)
  49. {
  50. static char s[64];
  51. Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
  52. return s;
  53. }
  54. /*
  55. =============
  56. Sys_StringToAdr
  57. idnewt
  58. 192.246.40.70
  59. =============
  60. */
  61. qboolean Sys_StringToSockaddr (const char *s, struct sockaddr *sadr)
  62. {
  63. struct hostent *h;
  64. char *colon;
  65. memset (sadr, 0, sizeof(*sadr));
  66. ((struct sockaddr_in *)sadr)->sin_family = AF_INET;
  67. ((struct sockaddr_in *)sadr)->sin_port = 0;
  68. if ( s[0] >= '0' && s[0] <= '9')
  69. {
  70. *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s);
  71. }
  72. else
  73. {
  74. if (! (h = gethostbyname(s)) )
  75. return qfalse;
  76. *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
  77. }
  78. return qtrue;
  79. }
  80. /*
  81. =============
  82. Sys_StringToAdr
  83. localhost
  84. idnewt
  85. idnewt:28000
  86. 192.246.40.70
  87. 192.246.40.70:28000
  88. =============
  89. */
  90. qboolean Sys_StringToAdr (const char *s, netadr_t *a)
  91. {
  92. struct sockaddr_in sadr;
  93. if (!Sys_StringToSockaddr (s, (struct sockaddr *)&sadr))
  94. return qfalse;
  95. SockadrToNetadr (&sadr, a);
  96. return qtrue;
  97. }
  98. //=============================================================================
  99. qboolean Sys_GetPacket (netadr_t *net_from, msg_t *net_message)
  100. {
  101. int ret;
  102. struct sockaddr_in from;
  103. int fromlen;
  104. int net_socket;
  105. int protocol;
  106. int err;
  107. for (protocol = 0 ; protocol < 2 ; protocol++)
  108. {
  109. if (protocol == 0)
  110. net_socket = ip_socket;
  111. else
  112. net_socket = ipx_socket;
  113. if (!net_socket)
  114. continue;
  115. fromlen = sizeof(from);
  116. ret = recvfrom (net_socket, net_message->data, net_message->maxsize
  117. , 0, (struct sockaddr *)&from, &fromlen);
  118. SockadrToNetadr (&from, net_from);
  119. if (ret == -1)
  120. {
  121. err = errno;
  122. if (err == EWOULDBLOCK || err == ECONNREFUSED)
  123. continue;
  124. Com_Printf ("NET_GetPacket: %s from %s\n", NET_ErrorString(),
  125. NET_AdrToString(*net_from));
  126. continue;
  127. }
  128. if (ret == net_message->maxsize)
  129. {
  130. Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from));
  131. continue;
  132. }
  133. net_message->cursize = ret;
  134. return qtrue;
  135. }
  136. return qfalse;
  137. }
  138. //=============================================================================
  139. void Sys_SendPacket( int length, const void *data, netadr_t to )
  140. {
  141. int ret;
  142. struct sockaddr_in addr;
  143. int net_socket;
  144. if (to.type == NA_BROADCAST)
  145. {
  146. net_socket = ip_socket;
  147. }
  148. else if (to.type == NA_IP)
  149. {
  150. net_socket = ip_socket;
  151. }
  152. else if (to.type == NA_IPX)
  153. {
  154. net_socket = ipx_socket;
  155. }
  156. else if (to.type == NA_BROADCAST_IPX)
  157. {
  158. net_socket = ipx_socket;
  159. }
  160. else {
  161. Com_Error (ERR_FATAL, "NET_SendPacket: bad address type");
  162. return;
  163. }
  164. if (!net_socket)
  165. return;
  166. NetadrToSockadr (&to, &addr);
  167. ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
  168. if (ret == -1)
  169. {
  170. Com_Printf ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(),
  171. NET_AdrToString (to));
  172. }
  173. }
  174. //=============================================================================
  175. /*
  176. ==================
  177. Sys_IsLANAddress
  178. LAN clients will have their rate var ignored
  179. ==================
  180. */
  181. qboolean Sys_IsLANAddress (netadr_t adr) {
  182. int i;
  183. if ( adr.type == NA_LOOPBACK ) {
  184. return qtrue;
  185. }
  186. // FIXME: ipx?
  187. if ( adr.type == NA_IP ) {
  188. for ( i = 0 ; i < numIP ; i++ ) {
  189. // assuming a class C network, which may not be smart...
  190. if ( adr.ip[0] == localIP[i][0]
  191. && adr.ip[1] == localIP[i][1]
  192. && adr.ip[2] == localIP[i][2] ) {
  193. return qtrue;
  194. }
  195. }
  196. }
  197. return qfalse;
  198. }
  199. /*
  200. =====================
  201. NET_GetLocalAddress
  202. =====================
  203. */
  204. void NET_GetLocalAddress( void ) {
  205. char hostname[256];
  206. struct hostent *hostInfo;
  207. int error;
  208. char *p;
  209. int ip;
  210. int n;
  211. if ( gethostname( hostname, 256 ) == -1 ) {
  212. return;
  213. }
  214. hostInfo = gethostbyname( hostname );
  215. if ( !hostInfo ) {
  216. return;
  217. }
  218. Com_Printf( "Hostname: %s\n", hostInfo->h_name );
  219. n = 0;
  220. while( ( p = hostInfo->h_aliases[n++] ) != NULL ) {
  221. Com_Printf( "Alias: %s\n", p );
  222. }
  223. if ( hostInfo->h_addrtype != AF_INET ) {
  224. return;
  225. }
  226. numIP = 0;
  227. while( ( p = hostInfo->h_addr_list[numIP++] ) != NULL && numIP < MAX_IPS ) {
  228. ip = ntohl( *(int *)p );
  229. localIP[ numIP ][0] = p[0];
  230. localIP[ numIP ][1] = p[1];
  231. localIP[ numIP ][2] = p[2];
  232. localIP[ numIP ][3] = p[3];
  233. Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff );
  234. }
  235. }
  236. /*
  237. ====================
  238. NET_OpenIP
  239. ====================
  240. */
  241. void NET_OpenIP (void)
  242. {
  243. cvar_t *ip;
  244. int port;
  245. int i;
  246. ip = Cvar_Get ("net_ip", "localhost", 0);
  247. port = Cvar_Get("net_port", va("%i", PORT_SERVER), 0)->value;
  248. for ( i = 0 ; i < 10 ; i++ ) {
  249. ip_socket = NET_IPSocket (ip->string, port + i);
  250. if ( ip_socket ) {
  251. Cvar_SetValue( "net_port", port + i );
  252. NET_GetLocalAddress();
  253. return;
  254. }
  255. }
  256. Com_Error (ERR_FATAL, "Couldn't allocate IP port");
  257. }
  258. /*
  259. ====================
  260. NET_Init
  261. ====================
  262. */
  263. void NET_Init (void)
  264. {
  265. noudp = Cvar_Get ("net_noudp", "0", 0);
  266. // open sockets
  267. if (! noudp->value) {
  268. NET_OpenIP ();
  269. }
  270. }
  271. /*
  272. ====================
  273. NET_Socket
  274. ====================
  275. */
  276. int NET_IPSocket (char *net_interface, int port)
  277. {
  278. int newsocket;
  279. struct sockaddr_in address;
  280. qboolean _qtrue = qtrue;
  281. int i = 1;
  282. if ( net_interface ) {
  283. Com_Printf("Opening IP socket: %s:%i\n", net_interface, port );
  284. } else {
  285. Com_Printf("Opening IP socket: localhost:%i\n", port );
  286. }
  287. if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  288. {
  289. Com_Printf ("ERROR: UDP_OpenSocket: socket: %s", NET_ErrorString());
  290. return 0;
  291. }
  292. // make it non-blocking
  293. if (ioctl (newsocket, FIONBIO, &_qtrue) == -1)
  294. {
  295. Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString());
  296. return 0;
  297. }
  298. // make it broadcast capable
  299. if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
  300. {
  301. Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString());
  302. return 0;
  303. }
  304. if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost"))
  305. address.sin_addr.s_addr = INADDR_ANY;
  306. else
  307. Sys_StringToSockaddr (net_interface, (struct sockaddr *)&address);
  308. if (port == PORT_ANY)
  309. address.sin_port = 0;
  310. else
  311. address.sin_port = htons((short)port);
  312. address.sin_family = AF_INET;
  313. if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  314. {
  315. Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString());
  316. close (newsocket);
  317. return 0;
  318. }
  319. return newsocket;
  320. }
  321. /*
  322. ====================
  323. NET_Shutdown
  324. ====================
  325. */
  326. void NET_Shutdown (void)
  327. {
  328. if (ip_socket) {
  329. close(ip_socket);
  330. ip_socket = 0;
  331. }
  332. }
  333. /*
  334. ====================
  335. NET_ErrorString
  336. ====================
  337. */
  338. char *NET_ErrorString (void)
  339. {
  340. int code;
  341. code = errno;
  342. return strerror (code);
  343. }
  344. // sleeps msec or until net socket is ready
  345. void NET_Sleep(int msec)
  346. {
  347. struct timeval timeout;
  348. fd_set fdset;
  349. extern qboolean stdin_active;
  350. if (!ip_socket || !com_dedicated->integer)
  351. return; // we're not a server, just run full speed
  352. FD_ZERO(&fdset);
  353. if (stdin_active)
  354. FD_SET(0, &fdset); // stdin is processed too
  355. FD_SET(ip_socket, &fdset); // network socket
  356. timeout.tv_sec = msec/1000;
  357. timeout.tv_usec = (msec%1000)*1000;
  358. select(ip_socket+1, &fdset, NULL, NULL, &timeout);
  359. }