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