net_wins.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. /*
  2. Copyright (C) 1997-2001 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 "winsock.h"
  17. #include "wsipx.h"
  18. #include "../qcommon/qcommon.h"
  19. #define MAX_LOOPBACK 4
  20. typedef struct
  21. {
  22. byte data[MAX_MSGLEN];
  23. int datalen;
  24. } loopmsg_t;
  25. typedef struct
  26. {
  27. loopmsg_t msgs[MAX_LOOPBACK];
  28. int get, send;
  29. } loopback_t;
  30. cvar_t *net_shownet;
  31. static cvar_t *noudp;
  32. static cvar_t *noipx;
  33. loopback_t loopbacks[2];
  34. int ip_sockets[2];
  35. int ipx_sockets[2];
  36. char *NET_ErrorString (void);
  37. //=============================================================================
  38. void NetadrToSockadr (netadr_t *a, struct sockaddr *s)
  39. {
  40. memset (s, 0, sizeof(*s));
  41. if (a->type == NA_BROADCAST)
  42. {
  43. ((struct sockaddr_in *)s)->sin_family = AF_INET;
  44. ((struct sockaddr_in *)s)->sin_port = a->port;
  45. ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
  46. }
  47. else if (a->type == NA_IP)
  48. {
  49. ((struct sockaddr_in *)s)->sin_family = AF_INET;
  50. ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
  51. ((struct sockaddr_in *)s)->sin_port = a->port;
  52. }
  53. else if (a->type == NA_IPX)
  54. {
  55. ((struct sockaddr_ipx *)s)->sa_family = AF_IPX;
  56. memcpy(((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4);
  57. memcpy(((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6);
  58. ((struct sockaddr_ipx *)s)->sa_socket = a->port;
  59. }
  60. else if (a->type == NA_BROADCAST_IPX)
  61. {
  62. ((struct sockaddr_ipx *)s)->sa_family = AF_IPX;
  63. memset(((struct sockaddr_ipx *)s)->sa_netnum, 0, 4);
  64. memset(((struct sockaddr_ipx *)s)->sa_nodenum, 0xff, 6);
  65. ((struct sockaddr_ipx *)s)->sa_socket = a->port;
  66. }
  67. }
  68. void SockadrToNetadr (struct sockaddr *s, netadr_t *a)
  69. {
  70. if (s->sa_family == AF_INET)
  71. {
  72. a->type = NA_IP;
  73. *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
  74. a->port = ((struct sockaddr_in *)s)->sin_port;
  75. }
  76. else if (s->sa_family == AF_IPX)
  77. {
  78. a->type = NA_IPX;
  79. memcpy(&a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4);
  80. memcpy(&a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6);
  81. a->port = ((struct sockaddr_ipx *)s)->sa_socket;
  82. }
  83. }
  84. qboolean NET_CompareAdr (netadr_t a, netadr_t b)
  85. {
  86. if (a.type != b.type)
  87. return false;
  88. if (a.type == NA_LOOPBACK)
  89. return TRUE;
  90. if (a.type == NA_IP)
  91. {
  92. 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)
  93. return true;
  94. return false;
  95. }
  96. if (a.type == NA_IPX)
  97. {
  98. if ((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port)
  99. return true;
  100. return false;
  101. }
  102. }
  103. /*
  104. ===================
  105. NET_CompareBaseAdr
  106. Compares without the port
  107. ===================
  108. */
  109. qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
  110. {
  111. if (a.type != b.type)
  112. return false;
  113. if (a.type == NA_LOOPBACK)
  114. return TRUE;
  115. if (a.type == NA_IP)
  116. {
  117. 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])
  118. return true;
  119. return false;
  120. }
  121. if (a.type == NA_IPX)
  122. {
  123. if ((memcmp(a.ipx, b.ipx, 10) == 0))
  124. return true;
  125. return false;
  126. }
  127. }
  128. char *NET_AdrToString (netadr_t a)
  129. {
  130. static char s[64];
  131. if (a.type == NA_LOOPBACK)
  132. Com_sprintf (s, sizeof(s), "loopback");
  133. else if (a.type == NA_IP)
  134. 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));
  135. else
  136. Com_sprintf (s, sizeof(s), "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%i", a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9], ntohs(a.port));
  137. return s;
  138. }
  139. /*
  140. =============
  141. NET_StringToAdr
  142. localhost
  143. idnewt
  144. idnewt:28000
  145. 192.246.40.70
  146. 192.246.40.70:28000
  147. =============
  148. */
  149. #define DO(src,dest) \
  150. copy[0] = s[src]; \
  151. copy[1] = s[src + 1]; \
  152. sscanf (copy, "%x", &val); \
  153. ((struct sockaddr_ipx *)sadr)->dest = val
  154. qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr)
  155. {
  156. struct hostent *h;
  157. char *colon;
  158. int val;
  159. char copy[128];
  160. memset (sadr, 0, sizeof(*sadr));
  161. if ((strlen(s) >= 23) && (s[8] == ':') && (s[21] == ':')) // check for an IPX address
  162. {
  163. ((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX;
  164. copy[2] = 0;
  165. DO(0, sa_netnum[0]);
  166. DO(2, sa_netnum[1]);
  167. DO(4, sa_netnum[2]);
  168. DO(6, sa_netnum[3]);
  169. DO(9, sa_nodenum[0]);
  170. DO(11, sa_nodenum[1]);
  171. DO(13, sa_nodenum[2]);
  172. DO(15, sa_nodenum[3]);
  173. DO(17, sa_nodenum[4]);
  174. DO(19, sa_nodenum[5]);
  175. sscanf (&s[22], "%u", &val);
  176. ((struct sockaddr_ipx *)sadr)->sa_socket = htons((unsigned short)val);
  177. }
  178. else
  179. {
  180. ((struct sockaddr_in *)sadr)->sin_family = AF_INET;
  181. ((struct sockaddr_in *)sadr)->sin_port = 0;
  182. strcpy (copy, s);
  183. // strip off a trailing :port if present
  184. for (colon = copy ; *colon ; colon++)
  185. if (*colon == ':')
  186. {
  187. *colon = 0;
  188. ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1));
  189. }
  190. if (copy[0] >= '0' && copy[0] <= '9')
  191. {
  192. *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy);
  193. }
  194. else
  195. {
  196. if (! (h = gethostbyname(copy)) )
  197. return 0;
  198. *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
  199. }
  200. }
  201. return true;
  202. }
  203. #undef DO
  204. /*
  205. =============
  206. NET_StringToAdr
  207. localhost
  208. idnewt
  209. idnewt:28000
  210. 192.246.40.70
  211. 192.246.40.70:28000
  212. =============
  213. */
  214. qboolean NET_StringToAdr (char *s, netadr_t *a)
  215. {
  216. struct sockaddr sadr;
  217. if (!strcmp (s, "localhost"))
  218. {
  219. memset (a, 0, sizeof(*a));
  220. a->type = NA_LOOPBACK;
  221. return true;
  222. }
  223. if (!NET_StringToSockaddr (s, &sadr))
  224. return false;
  225. SockadrToNetadr (&sadr, a);
  226. return true;
  227. }
  228. qboolean NET_IsLocalAddress (netadr_t adr)
  229. {
  230. return adr.type == NA_LOOPBACK;
  231. }
  232. /*
  233. =============================================================================
  234. LOOPBACK BUFFERS FOR LOCAL PLAYER
  235. =============================================================================
  236. */
  237. qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
  238. {
  239. int i;
  240. loopback_t *loop;
  241. loop = &loopbacks[sock];
  242. if (loop->send - loop->get > MAX_LOOPBACK)
  243. loop->get = loop->send - MAX_LOOPBACK;
  244. if (loop->get >= loop->send)
  245. return false;
  246. i = loop->get & (MAX_LOOPBACK-1);
  247. loop->get++;
  248. memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);
  249. net_message->cursize = loop->msgs[i].datalen;
  250. memset (net_from, 0, sizeof(*net_from));
  251. net_from->type = NA_LOOPBACK;
  252. return true;
  253. }
  254. void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to)
  255. {
  256. int i;
  257. loopback_t *loop;
  258. loop = &loopbacks[sock^1];
  259. i = loop->send & (MAX_LOOPBACK-1);
  260. loop->send++;
  261. memcpy (loop->msgs[i].data, data, length);
  262. loop->msgs[i].datalen = length;
  263. }
  264. //=============================================================================
  265. qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
  266. {
  267. int ret;
  268. struct sockaddr from;
  269. int fromlen;
  270. int net_socket;
  271. int protocol;
  272. int err;
  273. if (NET_GetLoopPacket (sock, net_from, net_message))
  274. return true;
  275. for (protocol = 0 ; protocol < 2 ; protocol++)
  276. {
  277. if (protocol == 0)
  278. net_socket = ip_sockets[sock];
  279. else
  280. net_socket = ipx_sockets[sock];
  281. if (!net_socket)
  282. continue;
  283. fromlen = sizeof(from);
  284. ret = recvfrom (net_socket, net_message->data, net_message->maxsize
  285. , 0, (struct sockaddr *)&from, &fromlen);
  286. if (ret == -1)
  287. {
  288. err = WSAGetLastError();
  289. if (err == WSAEWOULDBLOCK)
  290. continue;
  291. if (dedicated->value) // let dedicated servers continue after errors
  292. Com_Printf ("NET_GetPacket: %s", NET_ErrorString());
  293. else
  294. Com_Error (ERR_DROP, "NET_GetPacket: %s", NET_ErrorString());
  295. continue;
  296. }
  297. SockadrToNetadr (&from, net_from);
  298. if (ret == net_message->maxsize)
  299. {
  300. Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from));
  301. continue;
  302. }
  303. net_message->cursize = ret;
  304. return true;
  305. }
  306. return false;
  307. }
  308. //=============================================================================
  309. void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
  310. {
  311. int ret;
  312. struct sockaddr addr;
  313. int net_socket;
  314. if ( to.type == NA_LOOPBACK )
  315. {
  316. NET_SendLoopPacket (sock, length, data, to);
  317. return;
  318. }
  319. if (to.type == NA_BROADCAST)
  320. {
  321. net_socket = ip_sockets[sock];
  322. if (!net_socket)
  323. return;
  324. }
  325. else if (to.type == NA_IP)
  326. {
  327. net_socket = ip_sockets[sock];
  328. if (!net_socket)
  329. return;
  330. }
  331. else if (to.type == NA_IPX)
  332. {
  333. net_socket = ipx_sockets[sock];
  334. if (!net_socket)
  335. return;
  336. }
  337. else if (to.type == NA_BROADCAST_IPX)
  338. {
  339. net_socket = ipx_sockets[sock];
  340. if (!net_socket)
  341. return;
  342. }
  343. else
  344. Com_Error (ERR_FATAL, "NET_SendPacket: bad address type");
  345. NetadrToSockadr (&to, &addr);
  346. ret = sendto (net_socket, data, length, 0, &addr, sizeof(addr) );
  347. if (ret == -1)
  348. {
  349. int err = WSAGetLastError();
  350. // wouldblock is silent
  351. if (err == WSAEWOULDBLOCK)
  352. return;
  353. // some PPP links dont allow broadcasts
  354. if ((err == WSAEADDRNOTAVAIL) && ((to.type == NA_BROADCAST) || (to.type == NA_BROADCAST_IPX)))
  355. return;
  356. if (dedicated->value) // let dedicated servers continue after errors
  357. {
  358. Com_Printf ("NET_SendPacket ERROR: %s\n", NET_ErrorString());
  359. }
  360. else
  361. {
  362. if (err == WSAEADDRNOTAVAIL)
  363. {
  364. Com_DPrintf ("NET_SendPacket Warning: %s : %s\n", NET_ErrorString(), NET_AdrToString (to));
  365. }
  366. else
  367. {
  368. Com_Error (ERR_DROP, "NET_SendPacket ERROR: %s\n", NET_ErrorString());
  369. }
  370. }
  371. }
  372. }
  373. //=============================================================================
  374. /*
  375. ====================
  376. NET_Socket
  377. ====================
  378. */
  379. int NET_IPSocket (char *net_interface, int port)
  380. {
  381. int newsocket;
  382. struct sockaddr_in address;
  383. qboolean _true = true;
  384. int i = 1;
  385. int err;
  386. if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  387. {
  388. err = WSAGetLastError();
  389. if (err != WSAEAFNOSUPPORT)
  390. Com_Printf ("WARNING: UDP_OpenSocket: socket: %s", NET_ErrorString());
  391. return 0;
  392. }
  393. // make it non-blocking
  394. if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
  395. {
  396. Com_Printf ("WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString());
  397. return 0;
  398. }
  399. // make it broadcast capable
  400. if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
  401. {
  402. Com_Printf ("WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString());
  403. return 0;
  404. }
  405. if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost"))
  406. address.sin_addr.s_addr = INADDR_ANY;
  407. else
  408. NET_StringToSockaddr (net_interface, (struct sockaddr *)&address);
  409. if (port == PORT_ANY)
  410. address.sin_port = 0;
  411. else
  412. address.sin_port = htons((short)port);
  413. address.sin_family = AF_INET;
  414. if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  415. {
  416. Com_Printf ("WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString());
  417. closesocket (newsocket);
  418. return 0;
  419. }
  420. return newsocket;
  421. }
  422. /*
  423. ====================
  424. NET_OpenIP
  425. ====================
  426. */
  427. void NET_OpenIP (void)
  428. {
  429. cvar_t *ip;
  430. int port;
  431. int dedicated;
  432. ip = Cvar_Get ("ip", "localhost", CVAR_NOSET);
  433. dedicated = Cvar_VariableValue ("dedicated");
  434. if (!ip_sockets[NS_SERVER])
  435. {
  436. port = Cvar_Get("ip_hostport", "0", CVAR_NOSET)->value;
  437. if (!port)
  438. {
  439. port = Cvar_Get("hostport", "0", CVAR_NOSET)->value;
  440. if (!port)
  441. {
  442. port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET)->value;
  443. }
  444. }
  445. ip_sockets[NS_SERVER] = NET_IPSocket (ip->string, port);
  446. if (!ip_sockets[NS_SERVER] && dedicated)
  447. Com_Error (ERR_FATAL, "Couldn't allocate dedicated server IP port");
  448. }
  449. // dedicated servers don't need client ports
  450. if (dedicated)
  451. return;
  452. if (!ip_sockets[NS_CLIENT])
  453. {
  454. port = Cvar_Get("ip_clientport", "0", CVAR_NOSET)->value;
  455. if (!port)
  456. {
  457. port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_NOSET)->value;
  458. if (!port)
  459. port = PORT_ANY;
  460. }
  461. ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, port);
  462. if (!ip_sockets[NS_CLIENT])
  463. ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, PORT_ANY);
  464. }
  465. }
  466. /*
  467. ====================
  468. IPX_Socket
  469. ====================
  470. */
  471. int NET_IPXSocket (int port)
  472. {
  473. int newsocket;
  474. struct sockaddr_ipx address;
  475. int _true = 1;
  476. int err;
  477. if ((newsocket = socket (PF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == -1)
  478. {
  479. err = WSAGetLastError();
  480. if (err != WSAEAFNOSUPPORT)
  481. Com_Printf ("WARNING: IPX_Socket: socket: %s\n", NET_ErrorString());
  482. return 0;
  483. }
  484. // make it non-blocking
  485. if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
  486. {
  487. Com_Printf ("WARNING: IPX_Socket: ioctl FIONBIO: %s\n", NET_ErrorString());
  488. return 0;
  489. }
  490. // make it broadcast capable
  491. if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) == -1)
  492. {
  493. Com_Printf ("WARNING: IPX_Socket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString());
  494. return 0;
  495. }
  496. address.sa_family = AF_IPX;
  497. memset (address.sa_netnum, 0, 4);
  498. memset (address.sa_nodenum, 0, 6);
  499. if (port == PORT_ANY)
  500. address.sa_socket = 0;
  501. else
  502. address.sa_socket = htons((short)port);
  503. if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  504. {
  505. Com_Printf ("WARNING: IPX_Socket: bind: %s\n", NET_ErrorString());
  506. closesocket (newsocket);
  507. return 0;
  508. }
  509. return newsocket;
  510. }
  511. /*
  512. ====================
  513. NET_OpenIPX
  514. ====================
  515. */
  516. void NET_OpenIPX (void)
  517. {
  518. int port;
  519. int dedicated;
  520. dedicated = Cvar_VariableValue ("dedicated");
  521. if (!ipx_sockets[NS_SERVER])
  522. {
  523. port = Cvar_Get("ipx_hostport", "0", CVAR_NOSET)->value;
  524. if (!port)
  525. {
  526. port = Cvar_Get("hostport", "0", CVAR_NOSET)->value;
  527. if (!port)
  528. {
  529. port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET)->value;
  530. }
  531. }
  532. ipx_sockets[NS_SERVER] = NET_IPXSocket (port);
  533. }
  534. // dedicated servers don't need client ports
  535. if (dedicated)
  536. return;
  537. if (!ipx_sockets[NS_CLIENT])
  538. {
  539. port = Cvar_Get("ipx_clientport", "0", CVAR_NOSET)->value;
  540. if (!port)
  541. {
  542. port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_NOSET)->value;
  543. if (!port)
  544. port = PORT_ANY;
  545. }
  546. ipx_sockets[NS_CLIENT] = NET_IPXSocket (port);
  547. if (!ipx_sockets[NS_CLIENT])
  548. ipx_sockets[NS_CLIENT] = NET_IPXSocket (PORT_ANY);
  549. }
  550. }
  551. /*
  552. ====================
  553. NET_Config
  554. A single player game will only use the loopback code
  555. ====================
  556. */
  557. void NET_Config (qboolean multiplayer)
  558. {
  559. int i;
  560. static qboolean old_config;
  561. if (old_config == multiplayer)
  562. return;
  563. old_config = multiplayer;
  564. if (!multiplayer)
  565. { // shut down any existing sockets
  566. for (i=0 ; i<2 ; i++)
  567. {
  568. if (ip_sockets[i])
  569. {
  570. closesocket (ip_sockets[i]);
  571. ip_sockets[i] = 0;
  572. }
  573. if (ipx_sockets[i])
  574. {
  575. closesocket (ipx_sockets[i]);
  576. ipx_sockets[i] = 0;
  577. }
  578. }
  579. }
  580. else
  581. { // open sockets
  582. if (! noudp->value)
  583. NET_OpenIP ();
  584. if (! noipx->value)
  585. NET_OpenIPX ();
  586. }
  587. }
  588. // sleeps msec or until net socket is ready
  589. void NET_Sleep(int msec)
  590. {
  591. struct timeval timeout;
  592. fd_set fdset;
  593. extern cvar_t *dedicated;
  594. int i;
  595. if (!dedicated || !dedicated->value)
  596. return; // we're not a server, just run full speed
  597. FD_ZERO(&fdset);
  598. i = 0;
  599. if (ip_sockets[NS_SERVER]) {
  600. FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket
  601. i = ip_sockets[NS_SERVER];
  602. }
  603. if (ipx_sockets[NS_SERVER]) {
  604. FD_SET(ipx_sockets[NS_SERVER], &fdset); // network socket
  605. if (ipx_sockets[NS_SERVER] > i)
  606. i = ipx_sockets[NS_SERVER];
  607. }
  608. timeout.tv_sec = msec/1000;
  609. timeout.tv_usec = (msec%1000)*1000;
  610. select(i+1, &fdset, NULL, NULL, &timeout);
  611. }
  612. //===================================================================
  613. static WSADATA winsockdata;
  614. /*
  615. ====================
  616. NET_Init
  617. ====================
  618. */
  619. void NET_Init (void)
  620. {
  621. WORD wVersionRequested;
  622. int r;
  623. wVersionRequested = MAKEWORD(1, 1);
  624. r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
  625. if (r)
  626. Com_Error (ERR_FATAL,"Winsock initialization failed.");
  627. Com_Printf("Winsock Initialized\n");
  628. noudp = Cvar_Get ("noudp", "0", CVAR_NOSET);
  629. noipx = Cvar_Get ("noipx", "0", CVAR_NOSET);
  630. net_shownet = Cvar_Get ("net_shownet", "0", 0);
  631. }
  632. /*
  633. ====================
  634. NET_Shutdown
  635. ====================
  636. */
  637. void NET_Shutdown (void)
  638. {
  639. NET_Config (false); // close sockets
  640. WSACleanup ();
  641. }
  642. /*
  643. ====================
  644. NET_ErrorString
  645. ====================
  646. */
  647. char *NET_ErrorString (void)
  648. {
  649. int code;
  650. code = WSAGetLastError ();
  651. switch (code)
  652. {
  653. case WSAEINTR: return "WSAEINTR";
  654. case WSAEBADF: return "WSAEBADF";
  655. case WSAEACCES: return "WSAEACCES";
  656. case WSAEDISCON: return "WSAEDISCON";
  657. case WSAEFAULT: return "WSAEFAULT";
  658. case WSAEINVAL: return "WSAEINVAL";
  659. case WSAEMFILE: return "WSAEMFILE";
  660. case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
  661. case WSAEINPROGRESS: return "WSAEINPROGRESS";
  662. case WSAEALREADY: return "WSAEALREADY";
  663. case WSAENOTSOCK: return "WSAENOTSOCK";
  664. case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
  665. case WSAEMSGSIZE: return "WSAEMSGSIZE";
  666. case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
  667. case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
  668. case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
  669. case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
  670. case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
  671. case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
  672. case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
  673. case WSAEADDRINUSE: return "WSAEADDRINUSE";
  674. case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
  675. case WSAENETDOWN: return "WSAENETDOWN";
  676. case WSAENETUNREACH: return "WSAENETUNREACH";
  677. case WSAENETRESET: return "WSAENETRESET";
  678. case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
  679. case WSAECONNRESET: return "WSAECONNRESET";
  680. case WSAENOBUFS: return "WSAENOBUFS";
  681. case WSAEISCONN: return "WSAEISCONN";
  682. case WSAENOTCONN: return "WSAENOTCONN";
  683. case WSAESHUTDOWN: return "WSAESHUTDOWN";
  684. case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
  685. case WSAETIMEDOUT: return "WSAETIMEDOUT";
  686. case WSAECONNREFUSED: return "WSAECONNREFUSED";
  687. case WSAELOOP: return "WSAELOOP";
  688. case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
  689. case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
  690. case WSASYSNOTREADY: return "WSASYSNOTREADY";
  691. case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
  692. case WSANOTINITIALISED: return "WSANOTINITIALISED";
  693. case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
  694. case WSATRY_AGAIN: return "WSATRY_AGAIN";
  695. case WSANO_RECOVERY: return "WSANO_RECOVERY";
  696. case WSANO_DATA: return "WSANO_DATA";
  697. default: return "NO ERROR";
  698. }
  699. }