net_main.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  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 "net_vcr.h"
  18. qsocket_t *net_activeSockets = NULL;
  19. qsocket_t *net_freeSockets = NULL;
  20. int net_numsockets = 0;
  21. qboolean serialAvailable = false;
  22. qboolean ipxAvailable = false;
  23. qboolean tcpipAvailable = false;
  24. int net_hostport;
  25. int DEFAULTnet_hostport = 26000;
  26. char my_ipx_address[NET_NAMELEN];
  27. char my_tcpip_address[NET_NAMELEN];
  28. void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem);
  29. void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem);
  30. void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
  31. void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
  32. static qboolean listening = false;
  33. qboolean slistInProgress = false;
  34. qboolean slistSilent = false;
  35. qboolean slistLocal = true;
  36. static double slistStartTime;
  37. static int slistLastShown;
  38. static void Slist_Send(void);
  39. static void Slist_Poll(void);
  40. PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send};
  41. PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll};
  42. sizebuf_t net_message;
  43. int net_activeconnections = 0;
  44. int messagesSent = 0;
  45. int messagesReceived = 0;
  46. int unreliableMessagesSent = 0;
  47. int unreliableMessagesReceived = 0;
  48. cvar_t net_messagetimeout = {"net_messagetimeout","300"};
  49. cvar_t hostname = {"hostname", "UNNAMED"};
  50. qboolean configRestored = false;
  51. cvar_t config_com_port = {"_config_com_port", "0x3f8", true};
  52. cvar_t config_com_irq = {"_config_com_irq", "4", true};
  53. cvar_t config_com_baud = {"_config_com_baud", "57600", true};
  54. cvar_t config_com_modem = {"_config_com_modem", "1", true};
  55. cvar_t config_modem_dialtype = {"_config_modem_dialtype", "T", true};
  56. cvar_t config_modem_clear = {"_config_modem_clear", "ATZ", true};
  57. cvar_t config_modem_init = {"_config_modem_init", "", true};
  58. cvar_t config_modem_hangup = {"_config_modem_hangup", "AT H", true};
  59. #ifdef IDGODS
  60. cvar_t idgods = {"idgods", "0"};
  61. #endif
  62. int vcrFile = -1;
  63. qboolean recording = false;
  64. // these two macros are to make the code more readable
  65. #define sfunc net_drivers[sock->driver]
  66. #define dfunc net_drivers[net_driverlevel]
  67. int net_driverlevel;
  68. double net_time;
  69. double SetNetTime(void)
  70. {
  71. net_time = Sys_FloatTime();
  72. return net_time;
  73. }
  74. /*
  75. ===================
  76. NET_NewQSocket
  77. Called by drivers when a new communications endpoint is required
  78. The sequence and buffer fields will be filled in properly
  79. ===================
  80. */
  81. qsocket_t *NET_NewQSocket (void)
  82. {
  83. qsocket_t *sock;
  84. if (net_freeSockets == NULL)
  85. return NULL;
  86. if (net_activeconnections >= svs.maxclients)
  87. return NULL;
  88. // get one from free list
  89. sock = net_freeSockets;
  90. net_freeSockets = sock->next;
  91. // add it to active list
  92. sock->next = net_activeSockets;
  93. net_activeSockets = sock;
  94. sock->disconnected = false;
  95. sock->connecttime = net_time;
  96. Q_strcpy (sock->address,"UNSET ADDRESS");
  97. sock->driver = net_driverlevel;
  98. sock->socket = 0;
  99. sock->driverdata = NULL;
  100. sock->canSend = true;
  101. sock->sendNext = false;
  102. sock->lastMessageTime = net_time;
  103. sock->ackSequence = 0;
  104. sock->sendSequence = 0;
  105. sock->unreliableSendSequence = 0;
  106. sock->sendMessageLength = 0;
  107. sock->receiveSequence = 0;
  108. sock->unreliableReceiveSequence = 0;
  109. sock->receiveMessageLength = 0;
  110. return sock;
  111. }
  112. void NET_FreeQSocket(qsocket_t *sock)
  113. {
  114. qsocket_t *s;
  115. // remove it from active list
  116. if (sock == net_activeSockets)
  117. net_activeSockets = net_activeSockets->next;
  118. else
  119. {
  120. for (s = net_activeSockets; s; s = s->next)
  121. if (s->next == sock)
  122. {
  123. s->next = sock->next;
  124. break;
  125. }
  126. if (!s)
  127. Sys_Error ("NET_FreeQSocket: not active\n");
  128. }
  129. // add it to free list
  130. sock->next = net_freeSockets;
  131. net_freeSockets = sock;
  132. sock->disconnected = true;
  133. }
  134. static void NET_Listen_f (void)
  135. {
  136. if (Cmd_Argc () != 2)
  137. {
  138. Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0);
  139. return;
  140. }
  141. listening = Q_atoi(Cmd_Argv(1)) ? true : false;
  142. for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
  143. {
  144. if (net_drivers[net_driverlevel].initialized == false)
  145. continue;
  146. dfunc.Listen (listening);
  147. }
  148. }
  149. static void MaxPlayers_f (void)
  150. {
  151. int n;
  152. if (Cmd_Argc () != 2)
  153. {
  154. Con_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients);
  155. return;
  156. }
  157. if (sv.active)
  158. {
  159. Con_Printf ("maxplayers can not be changed while a server is running.\n");
  160. return;
  161. }
  162. n = Q_atoi(Cmd_Argv(1));
  163. if (n < 1)
  164. n = 1;
  165. if (n > svs.maxclientslimit)
  166. {
  167. n = svs.maxclientslimit;
  168. Con_Printf ("\"maxplayers\" set to \"%u\"\n", n);
  169. }
  170. if ((n == 1) && listening)
  171. Cbuf_AddText ("listen 0\n");
  172. if ((n > 1) && (!listening))
  173. Cbuf_AddText ("listen 1\n");
  174. svs.maxclients = n;
  175. if (n == 1)
  176. Cvar_Set ("deathmatch", "0");
  177. else
  178. Cvar_Set ("deathmatch", "1");
  179. }
  180. static void NET_Port_f (void)
  181. {
  182. int n;
  183. if (Cmd_Argc () != 2)
  184. {
  185. Con_Printf ("\"port\" is \"%u\"\n", net_hostport);
  186. return;
  187. }
  188. n = Q_atoi(Cmd_Argv(1));
  189. if (n < 1 || n > 65534)
  190. {
  191. Con_Printf ("Bad value, must be between 1 and 65534\n");
  192. return;
  193. }
  194. DEFAULTnet_hostport = n;
  195. net_hostport = n;
  196. if (listening)
  197. {
  198. // force a change to the new port
  199. Cbuf_AddText ("listen 0\n");
  200. Cbuf_AddText ("listen 1\n");
  201. }
  202. }
  203. static void PrintSlistHeader(void)
  204. {
  205. Con_Printf("Server Map Users\n");
  206. Con_Printf("--------------- --------------- -----\n");
  207. slistLastShown = 0;
  208. }
  209. static void PrintSlist(void)
  210. {
  211. int n;
  212. for (n = slistLastShown; n < hostCacheCount; n++)
  213. {
  214. if (hostcache[n].maxusers)
  215. Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
  216. else
  217. Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
  218. }
  219. slistLastShown = n;
  220. }
  221. static void PrintSlistTrailer(void)
  222. {
  223. if (hostCacheCount)
  224. Con_Printf("== end list ==\n\n");
  225. else
  226. Con_Printf("No Quake servers found.\n\n");
  227. }
  228. void NET_Slist_f (void)
  229. {
  230. if (slistInProgress)
  231. return;
  232. if (! slistSilent)
  233. {
  234. Con_Printf("Looking for Quake servers...\n");
  235. PrintSlistHeader();
  236. }
  237. slistInProgress = true;
  238. slistStartTime = Sys_FloatTime();
  239. SchedulePollProcedure(&slistSendProcedure, 0.0);
  240. SchedulePollProcedure(&slistPollProcedure, 0.1);
  241. hostCacheCount = 0;
  242. }
  243. static void Slist_Send(void)
  244. {
  245. for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
  246. {
  247. if (!slistLocal && net_driverlevel == 0)
  248. continue;
  249. if (net_drivers[net_driverlevel].initialized == false)
  250. continue;
  251. dfunc.SearchForHosts (true);
  252. }
  253. if ((Sys_FloatTime() - slistStartTime) < 0.5)
  254. SchedulePollProcedure(&slistSendProcedure, 0.75);
  255. }
  256. static void Slist_Poll(void)
  257. {
  258. for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
  259. {
  260. if (!slistLocal && net_driverlevel == 0)
  261. continue;
  262. if (net_drivers[net_driverlevel].initialized == false)
  263. continue;
  264. dfunc.SearchForHosts (false);
  265. }
  266. if (! slistSilent)
  267. PrintSlist();
  268. if ((Sys_FloatTime() - slistStartTime) < 1.5)
  269. {
  270. SchedulePollProcedure(&slistPollProcedure, 0.1);
  271. return;
  272. }
  273. if (! slistSilent)
  274. PrintSlistTrailer();
  275. slistInProgress = false;
  276. slistSilent = false;
  277. slistLocal = true;
  278. }
  279. /*
  280. ===================
  281. NET_Connect
  282. ===================
  283. */
  284. int hostCacheCount = 0;
  285. hostcache_t hostcache[HOSTCACHESIZE];
  286. qsocket_t *NET_Connect (char *host)
  287. {
  288. qsocket_t *ret;
  289. int n;
  290. int numdrivers = net_numdrivers;
  291. SetNetTime();
  292. if (host && *host == 0)
  293. host = NULL;
  294. if (host)
  295. {
  296. if (Q_strcasecmp (host, "local") == 0)
  297. {
  298. numdrivers = 1;
  299. goto JustDoIt;
  300. }
  301. if (hostCacheCount)
  302. {
  303. for (n = 0; n < hostCacheCount; n++)
  304. if (Q_strcasecmp (host, hostcache[n].name) == 0)
  305. {
  306. host = hostcache[n].cname;
  307. break;
  308. }
  309. if (n < hostCacheCount)
  310. goto JustDoIt;
  311. }
  312. }
  313. slistSilent = host ? true : false;
  314. NET_Slist_f ();
  315. while(slistInProgress)
  316. NET_Poll();
  317. if (host == NULL)
  318. {
  319. if (hostCacheCount != 1)
  320. return NULL;
  321. host = hostcache[0].cname;
  322. Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host);
  323. }
  324. if (hostCacheCount)
  325. for (n = 0; n < hostCacheCount; n++)
  326. if (Q_strcasecmp (host, hostcache[n].name) == 0)
  327. {
  328. host = hostcache[n].cname;
  329. break;
  330. }
  331. JustDoIt:
  332. for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++)
  333. {
  334. if (net_drivers[net_driverlevel].initialized == false)
  335. continue;
  336. ret = dfunc.Connect (host);
  337. if (ret)
  338. return ret;
  339. }
  340. if (host)
  341. {
  342. Con_Printf("\n");
  343. PrintSlistHeader();
  344. PrintSlist();
  345. PrintSlistTrailer();
  346. }
  347. return NULL;
  348. }
  349. /*
  350. ===================
  351. NET_CheckNewConnections
  352. ===================
  353. */
  354. struct
  355. {
  356. double time;
  357. int op;
  358. long session;
  359. } vcrConnect;
  360. qsocket_t *NET_CheckNewConnections (void)
  361. {
  362. qsocket_t *ret;
  363. SetNetTime();
  364. for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
  365. {
  366. if (net_drivers[net_driverlevel].initialized == false)
  367. continue;
  368. if (net_driverlevel && listening == false)
  369. continue;
  370. ret = dfunc.CheckNewConnections ();
  371. if (ret)
  372. {
  373. if (recording)
  374. {
  375. vcrConnect.time = host_time;
  376. vcrConnect.op = VCR_OP_CONNECT;
  377. vcrConnect.session = (long)ret;
  378. Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
  379. Sys_FileWrite (vcrFile, ret->address, NET_NAMELEN);
  380. }
  381. return ret;
  382. }
  383. }
  384. if (recording)
  385. {
  386. vcrConnect.time = host_time;
  387. vcrConnect.op = VCR_OP_CONNECT;
  388. vcrConnect.session = 0;
  389. Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
  390. }
  391. return NULL;
  392. }
  393. /*
  394. ===================
  395. NET_Close
  396. ===================
  397. */
  398. void NET_Close (qsocket_t *sock)
  399. {
  400. if (!sock)
  401. return;
  402. if (sock->disconnected)
  403. return;
  404. SetNetTime();
  405. // call the driver_Close function
  406. sfunc.Close (sock);
  407. NET_FreeQSocket(sock);
  408. }
  409. /*
  410. =================
  411. NET_GetMessage
  412. If there is a complete message, return it in net_message
  413. returns 0 if no data is waiting
  414. returns 1 if a message was received
  415. returns -1 if connection is invalid
  416. =================
  417. */
  418. struct
  419. {
  420. double time;
  421. int op;
  422. long session;
  423. int ret;
  424. int len;
  425. } vcrGetMessage;
  426. extern void PrintStats(qsocket_t *s);
  427. int NET_GetMessage (qsocket_t *sock)
  428. {
  429. int ret;
  430. if (!sock)
  431. return -1;
  432. if (sock->disconnected)
  433. {
  434. Con_Printf("NET_GetMessage: disconnected socket\n");
  435. return -1;
  436. }
  437. SetNetTime();
  438. ret = sfunc.QGetMessage(sock);
  439. // see if this connection has timed out
  440. if (ret == 0 && sock->driver)
  441. {
  442. if (net_time - sock->lastMessageTime > net_messagetimeout.value)
  443. {
  444. NET_Close(sock);
  445. return -1;
  446. }
  447. }
  448. if (ret > 0)
  449. {
  450. if (sock->driver)
  451. {
  452. sock->lastMessageTime = net_time;
  453. if (ret == 1)
  454. messagesReceived++;
  455. else if (ret == 2)
  456. unreliableMessagesReceived++;
  457. }
  458. if (recording)
  459. {
  460. vcrGetMessage.time = host_time;
  461. vcrGetMessage.op = VCR_OP_GETMESSAGE;
  462. vcrGetMessage.session = (long)sock;
  463. vcrGetMessage.ret = ret;
  464. vcrGetMessage.len = net_message.cursize;
  465. Sys_FileWrite (vcrFile, &vcrGetMessage, 24);
  466. Sys_FileWrite (vcrFile, net_message.data, net_message.cursize);
  467. }
  468. }
  469. else
  470. {
  471. if (recording)
  472. {
  473. vcrGetMessage.time = host_time;
  474. vcrGetMessage.op = VCR_OP_GETMESSAGE;
  475. vcrGetMessage.session = (long)sock;
  476. vcrGetMessage.ret = ret;
  477. Sys_FileWrite (vcrFile, &vcrGetMessage, 20);
  478. }
  479. }
  480. return ret;
  481. }
  482. /*
  483. ==================
  484. NET_SendMessage
  485. Try to send a complete length+message unit over the reliable stream.
  486. returns 0 if the message cannot be delivered reliably, but the connection
  487. is still considered valid
  488. returns 1 if the message was sent properly
  489. returns -1 if the connection died
  490. ==================
  491. */
  492. struct
  493. {
  494. double time;
  495. int op;
  496. long session;
  497. int r;
  498. } vcrSendMessage;
  499. int NET_SendMessage (qsocket_t *sock, sizebuf_t *data)
  500. {
  501. int r;
  502. if (!sock)
  503. return -1;
  504. if (sock->disconnected)
  505. {
  506. Con_Printf("NET_SendMessage: disconnected socket\n");
  507. return -1;
  508. }
  509. SetNetTime();
  510. r = sfunc.QSendMessage(sock, data);
  511. if (r == 1 && sock->driver)
  512. messagesSent++;
  513. if (recording)
  514. {
  515. vcrSendMessage.time = host_time;
  516. vcrSendMessage.op = VCR_OP_SENDMESSAGE;
  517. vcrSendMessage.session = (long)sock;
  518. vcrSendMessage.r = r;
  519. Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  520. }
  521. return r;
  522. }
  523. int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
  524. {
  525. int r;
  526. if (!sock)
  527. return -1;
  528. if (sock->disconnected)
  529. {
  530. Con_Printf("NET_SendMessage: disconnected socket\n");
  531. return -1;
  532. }
  533. SetNetTime();
  534. r = sfunc.SendUnreliableMessage(sock, data);
  535. if (r == 1 && sock->driver)
  536. unreliableMessagesSent++;
  537. if (recording)
  538. {
  539. vcrSendMessage.time = host_time;
  540. vcrSendMessage.op = VCR_OP_SENDMESSAGE;
  541. vcrSendMessage.session = (long)sock;
  542. vcrSendMessage.r = r;
  543. Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  544. }
  545. return r;
  546. }
  547. /*
  548. ==================
  549. NET_CanSendMessage
  550. Returns true or false if the given qsocket can currently accept a
  551. message to be transmitted.
  552. ==================
  553. */
  554. qboolean NET_CanSendMessage (qsocket_t *sock)
  555. {
  556. int r;
  557. if (!sock)
  558. return false;
  559. if (sock->disconnected)
  560. return false;
  561. SetNetTime();
  562. r = sfunc.CanSendMessage(sock);
  563. if (recording)
  564. {
  565. vcrSendMessage.time = host_time;
  566. vcrSendMessage.op = VCR_OP_CANSENDMESSAGE;
  567. vcrSendMessage.session = (long)sock;
  568. vcrSendMessage.r = r;
  569. Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  570. }
  571. return r;
  572. }
  573. int NET_SendToAll(sizebuf_t *data, int blocktime)
  574. {
  575. double start;
  576. int i;
  577. int count = 0;
  578. qboolean state1 [MAX_SCOREBOARD];
  579. qboolean state2 [MAX_SCOREBOARD];
  580. for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
  581. {
  582. if (!host_client->netconnection)
  583. continue;
  584. if (host_client->active)
  585. {
  586. if (host_client->netconnection->driver == 0)
  587. {
  588. NET_SendMessage(host_client->netconnection, data);
  589. state1[i] = true;
  590. state2[i] = true;
  591. continue;
  592. }
  593. count++;
  594. state1[i] = false;
  595. state2[i] = false;
  596. }
  597. else
  598. {
  599. state1[i] = true;
  600. state2[i] = true;
  601. }
  602. }
  603. start = Sys_FloatTime();
  604. while (count)
  605. {
  606. count = 0;
  607. for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
  608. {
  609. if (! state1[i])
  610. {
  611. if (NET_CanSendMessage (host_client->netconnection))
  612. {
  613. state1[i] = true;
  614. NET_SendMessage(host_client->netconnection, data);
  615. }
  616. else
  617. {
  618. NET_GetMessage (host_client->netconnection);
  619. }
  620. count++;
  621. continue;
  622. }
  623. if (! state2[i])
  624. {
  625. if (NET_CanSendMessage (host_client->netconnection))
  626. {
  627. state2[i] = true;
  628. }
  629. else
  630. {
  631. NET_GetMessage (host_client->netconnection);
  632. }
  633. count++;
  634. continue;
  635. }
  636. }
  637. if ((Sys_FloatTime() - start) > blocktime)
  638. break;
  639. }
  640. return count;
  641. }
  642. //=============================================================================
  643. /*
  644. ====================
  645. NET_Init
  646. ====================
  647. */
  648. void NET_Init (void)
  649. {
  650. int i;
  651. int controlSocket;
  652. qsocket_t *s;
  653. if (COM_CheckParm("-playback"))
  654. {
  655. net_numdrivers = 1;
  656. net_drivers[0].Init = VCR_Init;
  657. }
  658. if (COM_CheckParm("-record"))
  659. recording = true;
  660. i = COM_CheckParm ("-port");
  661. if (!i)
  662. i = COM_CheckParm ("-udpport");
  663. if (!i)
  664. i = COM_CheckParm ("-ipxport");
  665. if (i)
  666. {
  667. if (i < com_argc-1)
  668. DEFAULTnet_hostport = Q_atoi (com_argv[i+1]);
  669. else
  670. Sys_Error ("NET_Init: you must specify a number after -port");
  671. }
  672. net_hostport = DEFAULTnet_hostport;
  673. if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
  674. listening = true;
  675. net_numsockets = svs.maxclientslimit;
  676. if (cls.state != ca_dedicated)
  677. net_numsockets++;
  678. SetNetTime();
  679. for (i = 0; i < net_numsockets; i++)
  680. {
  681. s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket");
  682. s->next = net_freeSockets;
  683. net_freeSockets = s;
  684. s->disconnected = true;
  685. }
  686. // allocate space for network message buffer
  687. SZ_Alloc (&net_message, NET_MAXMESSAGE);
  688. Cvar_RegisterVariable (&net_messagetimeout);
  689. Cvar_RegisterVariable (&hostname);
  690. Cvar_RegisterVariable (&config_com_port);
  691. Cvar_RegisterVariable (&config_com_irq);
  692. Cvar_RegisterVariable (&config_com_baud);
  693. Cvar_RegisterVariable (&config_com_modem);
  694. Cvar_RegisterVariable (&config_modem_dialtype);
  695. Cvar_RegisterVariable (&config_modem_clear);
  696. Cvar_RegisterVariable (&config_modem_init);
  697. Cvar_RegisterVariable (&config_modem_hangup);
  698. #ifdef IDGODS
  699. Cvar_RegisterVariable (&idgods);
  700. #endif
  701. Cmd_AddCommand ("slist", NET_Slist_f);
  702. Cmd_AddCommand ("listen", NET_Listen_f);
  703. Cmd_AddCommand ("maxplayers", MaxPlayers_f);
  704. Cmd_AddCommand ("port", NET_Port_f);
  705. // initialize all the drivers
  706. for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
  707. {
  708. controlSocket = net_drivers[net_driverlevel].Init();
  709. if (controlSocket == -1)
  710. continue;
  711. net_drivers[net_driverlevel].initialized = true;
  712. net_drivers[net_driverlevel].controlSock = controlSocket;
  713. if (listening)
  714. net_drivers[net_driverlevel].Listen (true);
  715. }
  716. if (*my_ipx_address)
  717. Con_DPrintf("IPX address %s\n", my_ipx_address);
  718. if (*my_tcpip_address)
  719. Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
  720. }
  721. /*
  722. ====================
  723. NET_Shutdown
  724. ====================
  725. */
  726. void NET_Shutdown (void)
  727. {
  728. qsocket_t *sock;
  729. SetNetTime();
  730. for (sock = net_activeSockets; sock; sock = sock->next)
  731. NET_Close(sock);
  732. //
  733. // shutdown the drivers
  734. //
  735. for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++)
  736. {
  737. if (net_drivers[net_driverlevel].initialized == true)
  738. {
  739. net_drivers[net_driverlevel].Shutdown ();
  740. net_drivers[net_driverlevel].initialized = false;
  741. }
  742. }
  743. if (vcrFile != -1)
  744. {
  745. Con_Printf ("Closing vcrfile.\n");
  746. Sys_FileClose(vcrFile);
  747. }
  748. }
  749. static PollProcedure *pollProcedureList = NULL;
  750. void NET_Poll(void)
  751. {
  752. PollProcedure *pp;
  753. qboolean useModem;
  754. if (!configRestored)
  755. {
  756. if (serialAvailable)
  757. {
  758. if (config_com_modem.value == 1.0)
  759. useModem = true;
  760. else
  761. useModem = false;
  762. SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem);
  763. SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string);
  764. }
  765. configRestored = true;
  766. }
  767. SetNetTime();
  768. for (pp = pollProcedureList; pp; pp = pp->next)
  769. {
  770. if (pp->nextTime > net_time)
  771. break;
  772. pollProcedureList = pp->next;
  773. pp->procedure(pp->arg);
  774. }
  775. }
  776. void SchedulePollProcedure(PollProcedure *proc, double timeOffset)
  777. {
  778. PollProcedure *pp, *prev;
  779. proc->nextTime = Sys_FloatTime() + timeOffset;
  780. for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next)
  781. {
  782. if (pp->nextTime >= proc->nextTime)
  783. break;
  784. prev = pp;
  785. }
  786. if (prev == NULL)
  787. {
  788. proc->next = pollProcedureList;
  789. pollProcedureList = proc;
  790. return;
  791. }
  792. proc->next = pp;
  793. prev->next = proc;
  794. }
  795. #ifdef IDGODS
  796. #define IDNET 0xc0f62800
  797. qboolean IsID(struct qsockaddr *addr)
  798. {
  799. if (idgods.value == 0.0)
  800. return false;
  801. if (addr->sa_family != 2)
  802. return false;
  803. if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET)
  804. return true;
  805. return false;
  806. }
  807. #endif