|
|
1.1 root 1: // net_ser.c
2:
3: #include "quakedef.h"
4: #include "net_ser.h"
5: #include "dosisms.h"
6: #include "crc.h"
7:
8: #include "net_comx.c"
9:
10: // serial protocol
11:
12: #define SERIAL_PROTOCOL_VERSION 3
13:
14: // The serial protocol is message oriented. The high level message format is
15: // a one byte message type (MTYPE_xxx), data, and a 16-bit checksum. All
16: // multi-byte fields are sent in network byte order. There are currently 4
17: // MTYPEs defined. Their formats are as follows:
18: //
19: // MTYPE_RELIABLE sequence data_length data checksum eom
20: // MTYPE_UNRELIABLE sequence data_length data checksum eom
21: // MTYPE_ACK sequence checksum eom
22: // MTYPE_CONTROL data_length data checksum eom
23: //
24: // sequence is an 8-bit unsigned value starting from 0
25: // data_length is a 16-bit unsigned value; it is the length of the data only
26: // the checksum is a 16-bit value. the CRC formula used is defined in crc.h.
27: // the checksum covers the entire messages, excluding itself
28: // eom is a special 2 byte sequence used to mark the End Of Message. This is
29: // needed for error recovery.
30: //
31: // A lot of behavior is based on knowledge of the upper level Quake network
32: // layer. For example, only one reliable message can be outstanding (pending
33: // reception of an MTYPE_ACK) at a time.
34: //
35: // The low level routines used to communicate with the modem are not part of
36: // this protocol.
37: //
38: // The CONTROL messages are only used for session establishment. They are
39: // not reliable or sequenced.
40:
41: #define MTYPE_RELIABLE 0x01
42: #define MTYPE_UNRELIABLE 0x02
43: #define MTYPE_CONTROL 0x03
44: #define MTYPE_ACK 0x04
45: #define MTYPE_CLIENT 0x80
46:
47: #define ESCAPE_COMMAND 0xe0
48: #define ESCAPE_EOM 0x19
49:
50: static qboolean listening = false;
51:
52:
53: typedef struct SerialLine_s
54: {
55: struct SerialLine_s *next;
56: qsocket_t *sock;
57: int lengthStated;
58: int lengthFound;
59: int tty;
60: qboolean connected;
61: qboolean connecting;
62: qboolean client;
63: double connect_time;
64: unsigned short crcStated;
65: unsigned short crcValue;
66: byte currState;
67: byte prevState;
68: byte mtype;
69: byte sequence;
70: } SerialLine;
71:
72: #define STATE_READY 0
73: #define STATE_SEQUENCE 1
74: #define STATE_LENGTH1 2
75: #define STATE_LENGTH2 3
76: #define STATE_DATA 4
77: #define STATE_CRC1 5
78: #define STATE_CRC2 6
79: #define STATE_EOM 7
80: #define STATE_ESCAPE 8
81: #define STATE_ABORT 9
82:
83: SerialLine serialLine[NUM_COM_PORTS];
84:
85: int myDriverLevel;
86:
87: static void Serial_SendACK (SerialLine *p, byte sequence);
88:
89:
90: static void ResetSerialLineProtocol (SerialLine *p)
91: {
92: p->connected = false;
93: p->connecting = false;
94: p->currState = STATE_READY;
95: p->prevState = STATE_READY;
96: p->lengthFound = 0;
97: }
98:
99:
100: static int ProcessInQueue(SerialLine *p)
101: {
102: int b;
103:
104: while (1)
105: {
106: b = TTY_ReadByte(p->tty);
107: if (b == ERR_TTY_NODATA)
108: break;
109:
110: if (b == ERR_TTY_LINE_STATUS)
111: {
112: p->currState = STATE_ABORT;
113: continue;
114: }
115: if (b == ERR_TTY_MODEM_STATUS)
116: {
117: p->currState = STATE_ABORT;
118: return -1;
119: }
120:
121: if (b == ESCAPE_COMMAND)
122: if (p->currState != STATE_ESCAPE)
123: {
124: p->prevState = p->currState;
125: p->currState = STATE_ESCAPE;
126: continue;
127: }
128:
129: if (p->currState == STATE_ESCAPE)
130: {
131: if (b == ESCAPE_EOM)
132: {
133: if (p->prevState == STATE_ABORT)
134: {
135: p->currState = STATE_READY;
136: p->lengthFound = 0;
137: continue;
138: }
139:
140: if (p->prevState != STATE_EOM)
141: {
142: p->currState = STATE_READY;
143: p->lengthFound = 0;
144: Con_DPrintf("Serial: premature EOM\n");
145: continue;
146: }
147:
148: switch (p->mtype)
149: {
150: case MTYPE_RELIABLE:
151: Con_DPrintf("Serial: sending ack %u\n", p->sequence);
152: Serial_SendACK (p, p->sequence);
153: if (p->sequence == p->sock->receiveSequence)
154: {
155: p->sock->receiveSequence = (p->sequence + 1) & 0xff;
156: p->sock->receiveMessageLength += p->lengthFound;
157: }
158: else
159: Con_DPrintf("Serial: reliable out of order; got %u wanted %u\n", p->sequence, p->sock->receiveSequence);
160: break;
161:
162: case MTYPE_UNRELIABLE:
163: p->sock->unreliableReceiveSequence = (p->sequence + 1) & 0xff;
164: p->sock->receiveMessageLength += p->lengthFound;
165: break;
166:
167: case MTYPE_ACK:
168: Con_DPrintf("Serial: got ack %u\n", p->sequence);
169: if (p->sequence == p->sock->sendSequence)
170: {
171: p->sock->sendSequence = (p->sock->sendSequence + 1) & 0xff;
172: p->sock->canSend = true;
173: }
174: else
175: Con_DPrintf("Serial: ack out of order; got %u wanted %u\n",p->sequence, p->sock->sendSequence);
176: break;
177:
178: case MTYPE_CONTROL:
179: p->sock->receiveMessageLength += p->lengthFound;
180: break;
181: }
182:
183: p->currState = STATE_READY;
184: p->lengthFound = 0;
185: continue;
186: }
187:
188:
189: if (b != ESCAPE_COMMAND)
190: {
191: p->currState = STATE_ABORT;
192: Con_DPrintf("Serial: Bad escape sequence\n");
193: continue;
194: }
195:
196: // b == ESCAPE_COMMAND
197: p->currState = p->prevState;
198: }
199:
200: p->prevState = p->currState;
201:
202: //DEBUG
203: if (p->sock->receiveMessageLength + p->lengthFound > NET_MAXMESSAGE)
204: {
205: Con_DPrintf("Serial blew out receive buffer: %u\n", p->sock->receiveMessageLength + p->lengthFound);
206: p->currState = STATE_ABORT;
207: }
208: if (p->sock->receiveMessageLength + p->lengthFound == NET_MAXMESSAGE)
209: {
210: Con_DPrintf("Serial hit receive buffer limit: %u\n", p->sock->receiveMessageLength + p->lengthFound);
211: p->currState = STATE_ABORT;
212: }
213: //end DEBUG
214:
215: switch (p->currState)
216: {
217: case STATE_READY:
218: CRC_Init(&p->crcValue);
219: CRC_ProcessByte(&p->crcValue, b);
220: if (p->client)
221: {
222: if ((b & MTYPE_CLIENT) != 0)
223: {
224: p->currState = STATE_ABORT;
225: Con_DPrintf("Serial: client got own message\n");
226: break;
227: }
228: }
229: else
230: {
231: if ((b & MTYPE_CLIENT) == 0)
232: {
233: p->currState = STATE_ABORT;
234: Con_DPrintf("Serial: server got own message\n");
235: break;
236: }
237: b &= 0x7f;
238: }
239: p->mtype = b;
240: if (b != MTYPE_CONTROL)
241: p->currState = STATE_SEQUENCE;
242: else
243: p->currState = STATE_LENGTH1;
244: if (p->mtype < MTYPE_ACK)
245: {
246: p->sock->receiveMessage[p->sock->receiveMessageLength] = b;
247: p->lengthFound++;
248: }
249: break;
250:
251: case STATE_SEQUENCE:
252: p->sequence = b;
253: CRC_ProcessByte(&p->crcValue, b);
254: if (p->mtype != MTYPE_ACK)
255: p->currState = STATE_LENGTH1;
256: else
257: p->currState = STATE_CRC1;
258: break;
259:
260: case STATE_LENGTH1:
261: p->lengthStated = b * 256;
262: CRC_ProcessByte(&p->crcValue, b);
263: p->currState = STATE_LENGTH2;
264: break;
265:
266: case STATE_LENGTH2:
267: p->lengthStated += b;
268: CRC_ProcessByte(&p->crcValue, b);
269: if (p->mtype == MTYPE_RELIABLE && p->lengthStated > MAX_MSGLEN)
270: {
271: p->currState = STATE_ABORT;
272: Con_DPrintf("Serial: bad reliable message length %u\n", p->lengthStated);
273: }
274: else if (p->mtype == MTYPE_UNRELIABLE && p->lengthStated > MAX_DATAGRAM)
275: {
276: p->currState = STATE_ABORT;
277: Con_DPrintf("Serial: bad unreliable message length %u\n", p->lengthStated);
278: }
279: else
280: {
281: p->currState = STATE_DATA;
282: if (p->mtype < MTYPE_ACK)
283: {
284: *(short *)&p->sock->receiveMessage [p->sock->receiveMessageLength + 1] = p->lengthStated;
285: p->lengthFound += 2;
286: }
287: }
288: break;
289:
290: case STATE_DATA:
291: p->sock->receiveMessage[p->sock->receiveMessageLength + p->lengthFound] = b;
292: p->lengthFound++;
293: CRC_ProcessByte(&p->crcValue, b);
294: if (p->lengthFound == p->lengthStated + 3)
295: p->currState = STATE_CRC1;
296: break;
297:
298: case STATE_CRC1:
299: p->crcStated = b * 256;
300: p->currState = STATE_CRC2;
301: break;
302:
303: case STATE_CRC2:
304: p->crcStated += b;
305: if (p->crcStated == CRC_Value(p->crcValue))
306: {
307: p->currState = STATE_EOM;
308: }
309: else
310: {
311: p->currState = STATE_ABORT;
312: Con_DPrintf("Serial: Bad crc\n");
313: }
314: break;
315:
316: case STATE_EOM:
317: p->currState = STATE_ABORT;
318: Con_DPrintf("Serial: Bad message format\n");
319: break;
320:
321: case STATE_ABORT:
322: break;
323: }
324: }
325: return 0;
326: }
327:
328:
329: int Serial_Init (void)
330: {
331: int n;
332:
333: if (COM_CheckParm("-nolan"))
334: return -1;
335: if (COM_CheckParm ("-noserial"))
336: return -1;
337:
338: myDriverLevel = net_driverlevel;
339:
340: if (TTY_Init())
341: return -1;
342:
343: for (n = 0; n < NUM_COM_PORTS; n++)
344: {
345: serialLine[n].tty = TTY_Open(n);
346: ResetSerialLineProtocol (&serialLine[n]);
347: }
348:
349: Con_Printf("Serial driver initialized\n");
350: serialAvailable = true;
351:
352: return 0;
353: }
354:
355:
356: void Serial_Shutdown (void)
357: {
358: int n;
359:
360: for (n = 0; n < NUM_COM_PORTS; n++)
361: {
362: if (serialLine[n].connected)
363: Serial_Close(serialLine[n].sock);
364: }
365:
366: TTY_Shutdown();
367: }
368:
369:
370: void Serial_Listen (qboolean state)
371: {
372: listening = state;
373: }
374:
375:
376: qboolean Serial_CanSendMessage (qsocket_t *sock)
377: {
378: return sock->canSend;
379: }
380:
381:
382: qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock)
383: {
384: return TTY_OutputQueueIsEmpty(((SerialLine *)sock->driverdata)->tty);
385: }
386:
387:
388: int Serial_SendMessage (qsocket_t *sock, sizebuf_t *message)
389: {
390: SerialLine *p;
391: int n;
392: unsigned short crc;
393: byte b;
394:
395: p = (SerialLine *)sock->driverdata;
396: CRC_Init (&crc);
397:
398: // message type
399: b = MTYPE_RELIABLE;
400: if (p->client)
401: b |= MTYPE_CLIENT;
402: TTY_WriteByte(p->tty, b);
403: CRC_ProcessByte (&crc, b);
404:
405: // sequence
406: b = p->sock->sendSequence;
407: TTY_WriteByte(p->tty, b);
408: if (b == ESCAPE_COMMAND)
409: TTY_WriteByte(p->tty, b);
410: CRC_ProcessByte (&crc, b);
411:
412: // data length
413: b = message->cursize >> 8;
414: TTY_WriteByte(p->tty, b);
415: if (b == ESCAPE_COMMAND)
416: TTY_WriteByte(p->tty, b);
417: CRC_ProcessByte (&crc, b);
418: b = message->cursize & 0xff;
419: TTY_WriteByte(p->tty, b);
420: if (b == ESCAPE_COMMAND)
421: TTY_WriteByte(p->tty, b);
422: CRC_ProcessByte (&crc, b);
423:
424: // data
425: for (n = 0; n < message->cursize; n++)
426: {
427: b = message->data[n];
428: TTY_WriteByte(p->tty, b);
429: if (b == ESCAPE_COMMAND)
430: TTY_WriteByte(p->tty, b);
431: CRC_ProcessByte (&crc, b);
432: }
433:
434: // checksum
435: b = CRC_Value (crc) >> 8;
436: TTY_WriteByte(p->tty, b);
437: if (b == ESCAPE_COMMAND)
438: TTY_WriteByte(p->tty, b);
439: b = CRC_Value (crc) & 0xff;
440: TTY_WriteByte(p->tty, b);
441: if (b == ESCAPE_COMMAND)
442: TTY_WriteByte(p->tty, b);
443:
444: // end of message
445: TTY_WriteByte(p->tty, ESCAPE_COMMAND);
446: TTY_WriteByte(p->tty, ESCAPE_EOM);
447:
448: TTY_Flush(p->tty);
449:
450: // mark sock as busy and save the message for possible retransmit
451: sock->canSend = false;
452: Q_memcpy(sock->sendMessage, message->data, message->cursize);
453: sock->sendMessageLength = message->cursize;
454: sock->lastSendTime = net_time;
455:
456: return 1;
457: }
458:
459:
460: static void ReSendMessage (qsocket_t *sock)
461: {
462: sizebuf_t temp;
463:
464: Con_DPrintf("Serial: re-sending reliable\n");
465: temp.data = sock->sendMessage;
466: temp.maxsize = sock->sendMessageLength;
467: temp.cursize = sock->sendMessageLength;
468: Serial_SendMessage (sock, &temp);
469: }
470:
471:
472: int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message)
473: {
474: SerialLine *p;
475: int n;
476: unsigned short crc;
477: byte b;
478:
479: p = (SerialLine *)sock->driverdata;
480:
481: if (!TTY_OutputQueueIsEmpty(p->tty))
482: {
483: TTY_Flush(p->tty);
484: return 1;
485: }
486:
487: CRC_Init (&crc);
488:
489: // message type
490: b = MTYPE_UNRELIABLE;
491: if (p->client)
492: b |= MTYPE_CLIENT;
493: TTY_WriteByte(p->tty, b);
494: CRC_ProcessByte (&crc, b);
495:
496: // sequence
497: b = p->sock->unreliableSendSequence;
498: p->sock->unreliableSendSequence = (b + 1) & 0xff;
499: TTY_WriteByte(p->tty, b);
500: if (b == ESCAPE_COMMAND)
501: TTY_WriteByte(p->tty, b);
502: CRC_ProcessByte (&crc, b);
503:
504: // data length
505: b = message->cursize >> 8;
506: TTY_WriteByte(p->tty, b);
507: if (b == ESCAPE_COMMAND)
508: TTY_WriteByte(p->tty, b);
509: CRC_ProcessByte (&crc, b);
510: b = message->cursize & 0xff;
511: TTY_WriteByte(p->tty, b);
512: if (b == ESCAPE_COMMAND)
513: TTY_WriteByte(p->tty, b);
514: CRC_ProcessByte (&crc, b);
515:
516: // data
517: for (n = 0; n < message->cursize; n++)
518: {
519: b = message->data[n];
520: TTY_WriteByte(p->tty, b);
521: if (b == ESCAPE_COMMAND)
522: TTY_WriteByte(p->tty, b);
523: CRC_ProcessByte (&crc, b);
524: }
525:
526: // checksum
527: b = CRC_Value (crc) >> 8;
528: TTY_WriteByte(p->tty, b);
529: if (b == ESCAPE_COMMAND)
530: TTY_WriteByte(p->tty, b);
531: b = CRC_Value (crc) & 0xff;
532: TTY_WriteByte(p->tty, b);
533: if (b == ESCAPE_COMMAND)
534: TTY_WriteByte(p->tty, b);
535:
536: // end of message
537: TTY_WriteByte(p->tty, ESCAPE_COMMAND);
538: TTY_WriteByte(p->tty, ESCAPE_EOM);
539:
540: TTY_Flush(p->tty);
541:
542: return 1;
543: }
544:
545:
546: static void Serial_SendACK (SerialLine *p, byte sequence)
547: {
548: unsigned short crc;
549: byte b;
550:
551: CRC_Init (&crc);
552:
553: // message type
554: b = MTYPE_ACK;
555: if (p->client)
556: b |= MTYPE_CLIENT;
557: TTY_WriteByte(p->tty, b);
558: CRC_ProcessByte (&crc, b);
559:
560: // sequence
561: b = sequence;
562: TTY_WriteByte(p->tty, b);
563: if (b == ESCAPE_COMMAND)
564: TTY_WriteByte(p->tty, b);
565: CRC_ProcessByte (&crc, b);
566:
567: // checksum
568: b = CRC_Value (crc) >> 8;
569: TTY_WriteByte(p->tty, b);
570: if (b == ESCAPE_COMMAND)
571: TTY_WriteByte(p->tty, b);
572: b = CRC_Value (crc) & 0xff;
573: TTY_WriteByte(p->tty, b);
574: if (b == ESCAPE_COMMAND)
575: TTY_WriteByte(p->tty, b);
576:
577: // end of message
578: TTY_WriteByte(p->tty, ESCAPE_COMMAND);
579: TTY_WriteByte(p->tty, ESCAPE_EOM);
580:
581: TTY_Flush(p->tty);
582: }
583:
584:
585: static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message)
586: {
587: unsigned short crc;
588: int n;
589: byte b;
590:
591: CRC_Init (&crc);
592:
593: // message type
594: b = MTYPE_CONTROL;
595: if (p->client)
596: b |= MTYPE_CLIENT;
597: TTY_WriteByte(p->tty, b);
598: CRC_ProcessByte (&crc, b);
599:
600: // data length
601: b = message->cursize >> 8;
602: TTY_WriteByte(p->tty, b);
603: if (b == ESCAPE_COMMAND)
604: TTY_WriteByte(p->tty, b);
605: CRC_ProcessByte (&crc, b);
606: b = message->cursize & 0xff;
607: TTY_WriteByte(p->tty, b);
608: if (b == ESCAPE_COMMAND)
609: TTY_WriteByte(p->tty, b);
610: CRC_ProcessByte (&crc, b);
611:
612: // data
613: for (n = 0; n < message->cursize; n++)
614: {
615: b = message->data[n];
616: TTY_WriteByte(p->tty, b);
617: if (b == ESCAPE_COMMAND)
618: TTY_WriteByte(p->tty, b);
619: CRC_ProcessByte (&crc, b);
620: }
621:
622: // checksum
623: b = CRC_Value (crc) >> 8;
624: TTY_WriteByte(p->tty, b);
625: if (b == ESCAPE_COMMAND)
626: TTY_WriteByte(p->tty, b);
627: b = CRC_Value (crc) & 0xff;
628: TTY_WriteByte(p->tty, b);
629: if (b == ESCAPE_COMMAND)
630: TTY_WriteByte(p->tty, b);
631:
632: // end of message
633: TTY_WriteByte(p->tty, ESCAPE_COMMAND);
634: TTY_WriteByte(p->tty, ESCAPE_EOM);
635:
636: TTY_Flush(p->tty);
637: }
638:
639:
640: static int _Serial_GetMessage (SerialLine *p)
641: {
642: byte ret;
643: short length;
644:
645: if (ProcessInQueue(p))
646: return -1;
647:
648: if (p->sock->receiveMessageLength == 0)
649: return 0;
650:
651: ret = p->sock->receiveMessage[0];
652: length = *(short *)&p->sock->receiveMessage[1];
653: if (ret == MTYPE_CONTROL)
654: ret = 1;
655:
656: SZ_Clear (&net_message);
657: SZ_Write (&net_message, &p->sock->receiveMessage[3], length);
658:
659: length += 3;
660: p->sock->receiveMessageLength -= length;
661:
662: if (p->sock->receiveMessageLength + p->lengthFound)
663: Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound);
664:
665: return ret;
666: }
667:
668: int Serial_GetMessage (qsocket_t *sock)
669: {
670: SerialLine *p;
671: int ret;
672:
673: p = (SerialLine *)sock->driverdata;
674:
675: ret = _Serial_GetMessage (p);
676:
677: if (ret == 1)
678: messagesReceived++;
679:
680: if (!sock->canSend)
681: if ((net_time - sock->lastSendTime) > 1.0)
682: {
683: ReSendMessage (sock);
684: sock->lastSendTime = net_time;
685: }
686:
687: return ret;
688: }
689:
690:
691: void Serial_Close (qsocket_t *sock)
692: {
693: SerialLine *p = (SerialLine *)sock->driverdata;
694: TTY_Close(p->tty);
695: ResetSerialLineProtocol (p);
696: }
697:
698:
699: char *com_types[] = {"direct", "modem"};
700: unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600};
701:
702: void Serial_SearchForHosts (qboolean xmit)
703: {
704: int n;
705: SerialLine *p;
706:
707: if (sv.active)
708: return;
709:
710: if (hostCacheCount == HOSTCACHESIZE)
711: return;
712:
713: // see if we've already answered
714: for (n = 0; n < hostCacheCount; n++)
715: if (Q_strcmp (hostcache[n].cname, "#") == 0)
716: return;
717:
718: for (n = 0; n < NUM_COM_PORTS; n++)
719: if (TTY_IsEnabled(n))
720: break;
721: if (n == NUM_COM_PORTS)
722: return;
723: p = &serialLine[n];
724:
725: if (TTY_IsModem(p->tty))
726: return;
727:
728: sprintf(hostcache[hostCacheCount].name, "COM%u", n+1);
729: Q_strcpy(hostcache[hostCacheCount].map, "");
730: hostcache[hostCacheCount].users = 0;
731: hostcache[hostCacheCount].maxusers = 0;
732: hostcache[hostCacheCount].driver = net_driverlevel;
733: Q_strcpy(hostcache[hostCacheCount].cname, "#");
734: hostCacheCount++;
735:
736: return;
737: }
738:
739:
740: static qsocket_t *_Serial_Connect (char *host, SerialLine *p)
741: {
742: int ret;
743: double start_time;
744: double last_time;
745:
746: p->client = true;
747: if (TTY_Connect(p->tty, host))
748: return NULL;
749:
750: p->sock = NET_NewQSocket ();
751: p->sock->driver = myDriverLevel;
752: if (p->sock == NULL)
753: {
754: Con_Printf("No sockets available\n");
755: return NULL;
756: }
757: p->sock->driverdata = p;
758:
759: // send the connection request
760: start_time = SetNetTime();
761: last_time = 0.0;
762:
763: SZ_Clear(&net_message);
764: MSG_WriteByte(&net_message, CCREQ_CONNECT);
765: MSG_WriteString(&net_message, "QUAKE");
766: do
767: {
768: SetNetTime();
769: if ((net_time - last_time) >= 1.0)
770: {
771: Serial_SendControlMessage (p, &net_message);
772: last_time = net_time;
773: Con_Printf("trying...\n"); SCR_UpdateScreen ();
774: }
775: ret = _Serial_GetMessage (p);
776: }
777: while (ret == 0 && (net_time - start_time) < 5.0);
778:
779: if (ret == 0)
780: {
781: Con_Printf("Unable to connect, no response\n");
782: goto ErrorReturn;
783: }
784:
785: if (ret == -1)
786: {
787: Con_Printf("Connection request error\n");
788: goto ErrorReturn;
789: }
790:
791: MSG_BeginReading ();
792: ret = MSG_ReadByte();
793: if (ret == CCREP_REJECT)
794: {
795: Con_Printf(MSG_ReadString());
796: goto ErrorReturn;
797: }
798: if (ret != CCREP_ACCEPT)
799: {
800: Con_Printf("Unknown connection response\n");
801: goto ErrorReturn;
802: }
803:
804: p->connected = true;
805: p->sock->lastMessageTime = net_time;
806:
807: Con_Printf ("Connection accepted\n");
808:
809: return p->sock;
810:
811: ErrorReturn:
812: TTY_Disconnect(p->tty);
813: return NULL;
814: }
815:
816: qsocket_t *Serial_Connect (char *host)
817: {
818: int n;
819: qsocket_t *ret = NULL;
820:
821: // see if this looks like a phone number
822: if (*host == '#')
823: host++;
824: for (n = 0; n < Q_strlen(host); n++)
825: if (host[n] == '.' || host[n] == ':')
826: return NULL;
827:
828: for (n = 0; n < NUM_COM_PORTS; n++)
829: if (TTY_IsEnabled(n) && !serialLine[n].connected)
830: if ((ret = _Serial_Connect (host, &serialLine[n])))
831: break;
832: return ret;
833: }
834:
835:
836: static qsocket_t *_Serial_CheckNewConnections (SerialLine *p)
837: {
838: int command;
839:
840: p->client = false;
841: if (!TTY_CheckForConnection(p->tty))
842: return NULL;
843:
844: if (TTY_IsModem(p->tty))
845: {
846: if (!p->connecting)
847: {
848: p->connecting = true;
849: p->connect_time = net_time;
850: }
851: else if ((net_time - p->connect_time) > 15.0)
852: {
853: p->connecting = false;
854: TTY_Disconnect(p->tty);
855: return NULL;
856: }
857: }
858:
859: p->sock = NET_NewQSocket ();
860: p->sock->driver = myDriverLevel;
861: if (p->sock == NULL)
862: {
863: Con_Printf("No sockets available\n");
864: return NULL;
865: }
866: p->sock->driverdata = p;
867:
868: SZ_Clear(&net_message);
869: if (_Serial_GetMessage(p) != 1)
870: {
871: NET_FreeQSocket(p->sock);
872: return NULL;
873: }
874:
875: MSG_BeginReading ();
876: command = MSG_ReadByte();
877:
878: if (command == CCREQ_SERVER_INFO)
879: {
880: if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
881: return NULL;
882:
883: if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION)
884: return NULL;
885:
886: SZ_Clear(&net_message);
887: MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
888: MSG_WriteString(&net_message, hostname.string);
889: MSG_WriteString(&net_message, sv.name);
890: MSG_WriteByte(&net_message, net_activeconnections);
891: MSG_WriteByte(&net_message, svs.maxclients);
892: Serial_SendControlMessage (p, &net_message);
893: SZ_Clear(&net_message);
894: return NULL;
895: }
896:
897: if (command != CCREQ_CONNECT)
898: return NULL;
899:
900: if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
901: return NULL;
902:
903: // send him back the info about the server connection he has been allocated
904: SZ_Clear(&net_message);
905: MSG_WriteByte(&net_message, CCREP_ACCEPT);
906: Serial_SendControlMessage (p, &net_message);
907: SZ_Clear(&net_message);
908:
909: p->connected = true;
910: p->connecting = false;
911: p->sock->lastMessageTime = net_time;
912: sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1));
913:
914: return p->sock;
915: }
916:
917: qsocket_t *Serial_CheckNewConnections (void)
918: {
919: int n;
920: qsocket_t *ret = NULL;
921:
922: for (n = 0; n < NUM_COM_PORTS; n++)
923: if (TTY_IsEnabled(n) && !serialLine[n].connected)
924: if ((ret = _Serial_CheckNewConnections (&serialLine[n])))
925: break;
926: return ret;
927: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.