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