|
|
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:
1.1.1.2 ! root 333: // LATER do Win32 serial support
! 334: #ifdef _WIN32
! 335: return -1;
! 336: #endif
! 337:
1.1 root 338: if (COM_CheckParm("-nolan"))
339: return -1;
340: if (COM_CheckParm ("-noserial"))
341: return -1;
342:
343: myDriverLevel = net_driverlevel;
344:
345: if (TTY_Init())
346: return -1;
347:
348: for (n = 0; n < NUM_COM_PORTS; n++)
349: {
350: serialLine[n].tty = TTY_Open(n);
351: ResetSerialLineProtocol (&serialLine[n]);
352: }
353:
354: Con_Printf("Serial driver initialized\n");
355: serialAvailable = true;
356:
357: return 0;
358: }
359:
360:
361: void Serial_Shutdown (void)
362: {
363: int n;
364:
365: for (n = 0; n < NUM_COM_PORTS; n++)
366: {
367: if (serialLine[n].connected)
368: Serial_Close(serialLine[n].sock);
369: }
370:
371: TTY_Shutdown();
372: }
373:
374:
375: void Serial_Listen (qboolean state)
376: {
377: listening = state;
378: }
379:
380:
381: qboolean Serial_CanSendMessage (qsocket_t *sock)
382: {
383: return sock->canSend;
384: }
385:
386:
387: qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock)
388: {
389: return TTY_OutputQueueIsEmpty(((SerialLine *)sock->driverdata)->tty);
390: }
391:
392:
393: int Serial_SendMessage (qsocket_t *sock, sizebuf_t *message)
394: {
395: SerialLine *p;
396: int n;
397: unsigned short crc;
398: byte b;
399:
400: p = (SerialLine *)sock->driverdata;
401: CRC_Init (&crc);
402:
403: // message type
404: b = MTYPE_RELIABLE;
405: if (p->client)
406: b |= MTYPE_CLIENT;
407: TTY_WriteByte(p->tty, b);
408: CRC_ProcessByte (&crc, b);
409:
410: // sequence
411: b = p->sock->sendSequence;
412: TTY_WriteByte(p->tty, b);
413: if (b == ESCAPE_COMMAND)
414: TTY_WriteByte(p->tty, b);
415: CRC_ProcessByte (&crc, b);
416:
417: // data length
418: b = message->cursize >> 8;
419: TTY_WriteByte(p->tty, b);
420: if (b == ESCAPE_COMMAND)
421: TTY_WriteByte(p->tty, b);
422: CRC_ProcessByte (&crc, b);
423: b = message->cursize & 0xff;
424: TTY_WriteByte(p->tty, b);
425: if (b == ESCAPE_COMMAND)
426: TTY_WriteByte(p->tty, b);
427: CRC_ProcessByte (&crc, b);
428:
429: // data
430: for (n = 0; n < message->cursize; n++)
431: {
432: b = message->data[n];
433: TTY_WriteByte(p->tty, b);
434: if (b == ESCAPE_COMMAND)
435: TTY_WriteByte(p->tty, b);
436: CRC_ProcessByte (&crc, b);
437: }
438:
439: // checksum
440: b = CRC_Value (crc) >> 8;
441: TTY_WriteByte(p->tty, b);
442: if (b == ESCAPE_COMMAND)
443: TTY_WriteByte(p->tty, b);
444: b = CRC_Value (crc) & 0xff;
445: TTY_WriteByte(p->tty, b);
446: if (b == ESCAPE_COMMAND)
447: TTY_WriteByte(p->tty, b);
448:
449: // end of message
450: TTY_WriteByte(p->tty, ESCAPE_COMMAND);
451: TTY_WriteByte(p->tty, ESCAPE_EOM);
452:
453: TTY_Flush(p->tty);
454:
455: // mark sock as busy and save the message for possible retransmit
456: sock->canSend = false;
457: Q_memcpy(sock->sendMessage, message->data, message->cursize);
458: sock->sendMessageLength = message->cursize;
459: sock->lastSendTime = net_time;
460:
461: return 1;
462: }
463:
464:
465: static void ReSendMessage (qsocket_t *sock)
466: {
467: sizebuf_t temp;
468:
469: Con_DPrintf("Serial: re-sending reliable\n");
470: temp.data = sock->sendMessage;
471: temp.maxsize = sock->sendMessageLength;
472: temp.cursize = sock->sendMessageLength;
473: Serial_SendMessage (sock, &temp);
474: }
475:
476:
477: int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message)
478: {
479: SerialLine *p;
480: int n;
481: unsigned short crc;
482: byte b;
483:
484: p = (SerialLine *)sock->driverdata;
485:
486: if (!TTY_OutputQueueIsEmpty(p->tty))
487: {
488: TTY_Flush(p->tty);
489: return 1;
490: }
491:
492: CRC_Init (&crc);
493:
494: // message type
495: b = MTYPE_UNRELIABLE;
496: if (p->client)
497: b |= MTYPE_CLIENT;
498: TTY_WriteByte(p->tty, b);
499: CRC_ProcessByte (&crc, b);
500:
501: // sequence
502: b = p->sock->unreliableSendSequence;
503: p->sock->unreliableSendSequence = (b + 1) & 0xff;
504: TTY_WriteByte(p->tty, b);
505: if (b == ESCAPE_COMMAND)
506: TTY_WriteByte(p->tty, b);
507: CRC_ProcessByte (&crc, b);
508:
509: // data length
510: b = message->cursize >> 8;
511: TTY_WriteByte(p->tty, b);
512: if (b == ESCAPE_COMMAND)
513: TTY_WriteByte(p->tty, b);
514: CRC_ProcessByte (&crc, b);
515: b = message->cursize & 0xff;
516: TTY_WriteByte(p->tty, b);
517: if (b == ESCAPE_COMMAND)
518: TTY_WriteByte(p->tty, b);
519: CRC_ProcessByte (&crc, b);
520:
521: // data
522: for (n = 0; n < message->cursize; n++)
523: {
524: b = message->data[n];
525: TTY_WriteByte(p->tty, b);
526: if (b == ESCAPE_COMMAND)
527: TTY_WriteByte(p->tty, b);
528: CRC_ProcessByte (&crc, b);
529: }
530:
531: // checksum
532: b = CRC_Value (crc) >> 8;
533: TTY_WriteByte(p->tty, b);
534: if (b == ESCAPE_COMMAND)
535: TTY_WriteByte(p->tty, b);
536: b = CRC_Value (crc) & 0xff;
537: TTY_WriteByte(p->tty, b);
538: if (b == ESCAPE_COMMAND)
539: TTY_WriteByte(p->tty, b);
540:
541: // end of message
542: TTY_WriteByte(p->tty, ESCAPE_COMMAND);
543: TTY_WriteByte(p->tty, ESCAPE_EOM);
544:
545: TTY_Flush(p->tty);
546:
547: return 1;
548: }
549:
550:
551: static void Serial_SendACK (SerialLine *p, byte sequence)
552: {
553: unsigned short crc;
554: byte b;
555:
556: CRC_Init (&crc);
557:
558: // message type
559: b = MTYPE_ACK;
560: if (p->client)
561: b |= MTYPE_CLIENT;
562: TTY_WriteByte(p->tty, b);
563: CRC_ProcessByte (&crc, b);
564:
565: // sequence
566: b = sequence;
567: TTY_WriteByte(p->tty, b);
568: if (b == ESCAPE_COMMAND)
569: TTY_WriteByte(p->tty, b);
570: CRC_ProcessByte (&crc, b);
571:
572: // checksum
573: b = CRC_Value (crc) >> 8;
574: TTY_WriteByte(p->tty, b);
575: if (b == ESCAPE_COMMAND)
576: TTY_WriteByte(p->tty, b);
577: b = CRC_Value (crc) & 0xff;
578: TTY_WriteByte(p->tty, b);
579: if (b == ESCAPE_COMMAND)
580: TTY_WriteByte(p->tty, b);
581:
582: // end of message
583: TTY_WriteByte(p->tty, ESCAPE_COMMAND);
584: TTY_WriteByte(p->tty, ESCAPE_EOM);
585:
586: TTY_Flush(p->tty);
587: }
588:
589:
590: static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message)
591: {
592: unsigned short crc;
593: int n;
594: byte b;
595:
596: CRC_Init (&crc);
597:
598: // message type
599: b = MTYPE_CONTROL;
600: if (p->client)
601: b |= MTYPE_CLIENT;
602: TTY_WriteByte(p->tty, b);
603: CRC_ProcessByte (&crc, b);
604:
605: // data length
606: b = message->cursize >> 8;
607: TTY_WriteByte(p->tty, b);
608: if (b == ESCAPE_COMMAND)
609: TTY_WriteByte(p->tty, b);
610: CRC_ProcessByte (&crc, b);
611: b = message->cursize & 0xff;
612: TTY_WriteByte(p->tty, b);
613: if (b == ESCAPE_COMMAND)
614: TTY_WriteByte(p->tty, b);
615: CRC_ProcessByte (&crc, b);
616:
617: // data
618: for (n = 0; n < message->cursize; n++)
619: {
620: b = message->data[n];
621: TTY_WriteByte(p->tty, b);
622: if (b == ESCAPE_COMMAND)
623: TTY_WriteByte(p->tty, b);
624: CRC_ProcessByte (&crc, b);
625: }
626:
627: // checksum
628: b = CRC_Value (crc) >> 8;
629: TTY_WriteByte(p->tty, b);
630: if (b == ESCAPE_COMMAND)
631: TTY_WriteByte(p->tty, b);
632: b = CRC_Value (crc) & 0xff;
633: TTY_WriteByte(p->tty, b);
634: if (b == ESCAPE_COMMAND)
635: TTY_WriteByte(p->tty, b);
636:
637: // end of message
638: TTY_WriteByte(p->tty, ESCAPE_COMMAND);
639: TTY_WriteByte(p->tty, ESCAPE_EOM);
640:
641: TTY_Flush(p->tty);
642: }
643:
644:
645: static int _Serial_GetMessage (SerialLine *p)
646: {
647: byte ret;
648: short length;
649:
650: if (ProcessInQueue(p))
651: return -1;
652:
653: if (p->sock->receiveMessageLength == 0)
654: return 0;
655:
656: ret = p->sock->receiveMessage[0];
657: length = *(short *)&p->sock->receiveMessage[1];
658: if (ret == MTYPE_CONTROL)
659: ret = 1;
660:
661: SZ_Clear (&net_message);
662: SZ_Write (&net_message, &p->sock->receiveMessage[3], length);
663:
664: length += 3;
665: p->sock->receiveMessageLength -= length;
666:
667: if (p->sock->receiveMessageLength + p->lengthFound)
668: Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound);
669:
670: return ret;
671: }
672:
673: int Serial_GetMessage (qsocket_t *sock)
674: {
675: SerialLine *p;
676: int ret;
677:
678: p = (SerialLine *)sock->driverdata;
679:
680: ret = _Serial_GetMessage (p);
681:
682: if (ret == 1)
683: messagesReceived++;
684:
685: if (!sock->canSend)
686: if ((net_time - sock->lastSendTime) > 1.0)
687: {
688: ReSendMessage (sock);
689: sock->lastSendTime = net_time;
690: }
691:
692: return ret;
693: }
694:
695:
696: void Serial_Close (qsocket_t *sock)
697: {
698: SerialLine *p = (SerialLine *)sock->driverdata;
699: TTY_Close(p->tty);
700: ResetSerialLineProtocol (p);
701: }
702:
703:
704: char *com_types[] = {"direct", "modem"};
705: unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600};
706:
707: void Serial_SearchForHosts (qboolean xmit)
708: {
709: int n;
710: SerialLine *p;
711:
712: if (sv.active)
713: return;
714:
715: if (hostCacheCount == HOSTCACHESIZE)
716: return;
717:
718: // see if we've already answered
719: for (n = 0; n < hostCacheCount; n++)
720: if (Q_strcmp (hostcache[n].cname, "#") == 0)
721: return;
722:
723: for (n = 0; n < NUM_COM_PORTS; n++)
724: if (TTY_IsEnabled(n))
725: break;
726: if (n == NUM_COM_PORTS)
727: return;
728: p = &serialLine[n];
729:
730: if (TTY_IsModem(p->tty))
731: return;
732:
733: sprintf(hostcache[hostCacheCount].name, "COM%u", n+1);
734: Q_strcpy(hostcache[hostCacheCount].map, "");
735: hostcache[hostCacheCount].users = 0;
736: hostcache[hostCacheCount].maxusers = 0;
737: hostcache[hostCacheCount].driver = net_driverlevel;
738: Q_strcpy(hostcache[hostCacheCount].cname, "#");
739: hostCacheCount++;
740:
741: return;
742: }
743:
744:
745: static qsocket_t *_Serial_Connect (char *host, SerialLine *p)
746: {
747: int ret;
748: double start_time;
749: double last_time;
750:
751: p->client = true;
752: if (TTY_Connect(p->tty, host))
753: return NULL;
754:
755: p->sock = NET_NewQSocket ();
756: p->sock->driver = myDriverLevel;
757: if (p->sock == NULL)
758: {
759: Con_Printf("No sockets available\n");
760: return NULL;
761: }
762: p->sock->driverdata = p;
763:
764: // send the connection request
765: start_time = SetNetTime();
766: last_time = 0.0;
767:
768: SZ_Clear(&net_message);
769: MSG_WriteByte(&net_message, CCREQ_CONNECT);
770: MSG_WriteString(&net_message, "QUAKE");
771: do
772: {
773: SetNetTime();
774: if ((net_time - last_time) >= 1.0)
775: {
776: Serial_SendControlMessage (p, &net_message);
777: last_time = net_time;
778: Con_Printf("trying...\n"); SCR_UpdateScreen ();
779: }
780: ret = _Serial_GetMessage (p);
781: }
782: while (ret == 0 && (net_time - start_time) < 5.0);
783:
784: if (ret == 0)
785: {
786: Con_Printf("Unable to connect, no response\n");
787: goto ErrorReturn;
788: }
789:
790: if (ret == -1)
791: {
792: Con_Printf("Connection request error\n");
793: goto ErrorReturn;
794: }
795:
796: MSG_BeginReading ();
797: ret = MSG_ReadByte();
798: if (ret == CCREP_REJECT)
799: {
800: Con_Printf(MSG_ReadString());
801: goto ErrorReturn;
802: }
803: if (ret != CCREP_ACCEPT)
804: {
805: Con_Printf("Unknown connection response\n");
806: goto ErrorReturn;
807: }
808:
809: p->connected = true;
810: p->sock->lastMessageTime = net_time;
811:
812: Con_Printf ("Connection accepted\n");
813:
814: return p->sock;
815:
816: ErrorReturn:
817: TTY_Disconnect(p->tty);
818: return NULL;
819: }
820:
821: qsocket_t *Serial_Connect (char *host)
822: {
823: int n;
824: qsocket_t *ret = NULL;
825:
826: // see if this looks like a phone number
827: if (*host == '#')
828: host++;
829: for (n = 0; n < Q_strlen(host); n++)
830: if (host[n] == '.' || host[n] == ':')
831: return NULL;
832:
833: for (n = 0; n < NUM_COM_PORTS; n++)
834: if (TTY_IsEnabled(n) && !serialLine[n].connected)
835: if ((ret = _Serial_Connect (host, &serialLine[n])))
836: break;
837: return ret;
838: }
839:
840:
841: static qsocket_t *_Serial_CheckNewConnections (SerialLine *p)
842: {
843: int command;
844:
845: p->client = false;
846: if (!TTY_CheckForConnection(p->tty))
847: return NULL;
848:
849: if (TTY_IsModem(p->tty))
850: {
851: if (!p->connecting)
852: {
853: p->connecting = true;
854: p->connect_time = net_time;
855: }
856: else if ((net_time - p->connect_time) > 15.0)
857: {
858: p->connecting = false;
859: TTY_Disconnect(p->tty);
860: return NULL;
861: }
862: }
863:
864: p->sock = NET_NewQSocket ();
865: p->sock->driver = myDriverLevel;
866: if (p->sock == NULL)
867: {
868: Con_Printf("No sockets available\n");
869: return NULL;
870: }
871: p->sock->driverdata = p;
872:
873: SZ_Clear(&net_message);
874: if (_Serial_GetMessage(p) != 1)
875: {
876: NET_FreeQSocket(p->sock);
877: return NULL;
878: }
879:
880: MSG_BeginReading ();
881: command = MSG_ReadByte();
882:
883: if (command == CCREQ_SERVER_INFO)
884: {
885: if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
886: return NULL;
887:
888: if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION)
889: return NULL;
890:
891: SZ_Clear(&net_message);
892: MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
893: MSG_WriteString(&net_message, hostname.string);
894: MSG_WriteString(&net_message, sv.name);
895: MSG_WriteByte(&net_message, net_activeconnections);
896: MSG_WriteByte(&net_message, svs.maxclients);
897: Serial_SendControlMessage (p, &net_message);
898: SZ_Clear(&net_message);
899: return NULL;
900: }
901:
902: if (command != CCREQ_CONNECT)
903: return NULL;
904:
905: if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
906: return NULL;
907:
908: // send him back the info about the server connection he has been allocated
909: SZ_Clear(&net_message);
910: MSG_WriteByte(&net_message, CCREP_ACCEPT);
911: Serial_SendControlMessage (p, &net_message);
912: SZ_Clear(&net_message);
913:
914: p->connected = true;
915: p->connecting = false;
916: p->sock->lastMessageTime = net_time;
917: sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1));
918:
919: return p->sock;
920: }
921:
922: qsocket_t *Serial_CheckNewConnections (void)
923: {
924: int n;
925: qsocket_t *ret = NULL;
926:
927: for (n = 0; n < NUM_COM_PORTS; n++)
928: if (TTY_IsEnabled(n) && !serialLine[n].connected)
929: if ((ret = _Serial_CheckNewConnections (&serialLine[n])))
930: break;
931: return ret;
932: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.