diff options
Diffstat (limited to 'WinQuake/net_ser.c')
| -rw-r--r-- | WinQuake/net_ser.c | 951 |
1 files changed, 951 insertions, 0 deletions
diff --git a/WinQuake/net_ser.c b/WinQuake/net_ser.c new file mode 100644 index 0000000..f582f54 --- /dev/null +++ b/WinQuake/net_ser.c @@ -0,0 +1,951 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_ser.c + +#include "quakedef.h" +#include "net_ser.h" +#include "dosisms.h" +#include "crc.h" + +#include "net_comx.c" + +// serial protocol + +#define SERIAL_PROTOCOL_VERSION 3 + +// The serial protocol is message oriented. The high level message format is +// a one byte message type (MTYPE_xxx), data, and a 16-bit checksum. All +// multi-byte fields are sent in network byte order. There are currently 4 +// MTYPEs defined. Their formats are as follows: +// +// MTYPE_RELIABLE sequence data_length data checksum eom +// MTYPE_UNRELIABLE sequence data_length data checksum eom +// MTYPE_ACK sequence checksum eom +// MTYPE_CONTROL data_length data checksum eom +// +// sequence is an 8-bit unsigned value starting from 0 +// data_length is a 16-bit unsigned value; it is the length of the data only +// the checksum is a 16-bit value. the CRC formula used is defined in crc.h. +// the checksum covers the entire messages, excluding itself +// eom is a special 2 byte sequence used to mark the End Of Message. This is +// needed for error recovery. +// +// A lot of behavior is based on knowledge of the upper level Quake network +// layer. For example, only one reliable message can be outstanding (pending +// reception of an MTYPE_ACK) at a time. +// +// The low level routines used to communicate with the modem are not part of +// this protocol. +// +// The CONTROL messages are only used for session establishment. They are +// not reliable or sequenced. + +#define MTYPE_RELIABLE 0x01 +#define MTYPE_UNRELIABLE 0x02 +#define MTYPE_CONTROL 0x03 +#define MTYPE_ACK 0x04 +#define MTYPE_CLIENT 0x80 + +#define ESCAPE_COMMAND 0xe0 +#define ESCAPE_EOM 0x19 + +static qboolean listening = false; + + +typedef struct SerialLine_s +{ + struct SerialLine_s *next; + qsocket_t *sock; + int lengthStated; + int lengthFound; + int tty; + qboolean connected; + qboolean connecting; + qboolean client; + double connect_time; + unsigned short crcStated; + unsigned short crcValue; + byte currState; + byte prevState; + byte mtype; + byte sequence; +} SerialLine; + +#define STATE_READY 0 +#define STATE_SEQUENCE 1 +#define STATE_LENGTH1 2 +#define STATE_LENGTH2 3 +#define STATE_DATA 4 +#define STATE_CRC1 5 +#define STATE_CRC2 6 +#define STATE_EOM 7 +#define STATE_ESCAPE 8 +#define STATE_ABORT 9 + +SerialLine serialLine[NUM_COM_PORTS]; + +int myDriverLevel; + +static void Serial_SendACK (SerialLine *p, byte sequence); + + +static void ResetSerialLineProtocol (SerialLine *p) +{ + p->connected = false; + p->connecting = false; + p->currState = STATE_READY; + p->prevState = STATE_READY; + p->lengthFound = 0; +} + + +static int ProcessInQueue(SerialLine *p) +{ + int b; + + while (1) + { + b = TTY_ReadByte(p->tty); + if (b == ERR_TTY_NODATA) + break; + + if (b == ERR_TTY_LINE_STATUS) + { + p->currState = STATE_ABORT; + continue; + } + if (b == ERR_TTY_MODEM_STATUS) + { + p->currState = STATE_ABORT; + return -1; + } + + if (b == ESCAPE_COMMAND) + if (p->currState != STATE_ESCAPE) + { + p->prevState = p->currState; + p->currState = STATE_ESCAPE; + continue; + } + + if (p->currState == STATE_ESCAPE) + { + if (b == ESCAPE_EOM) + { + if (p->prevState == STATE_ABORT) + { + p->currState = STATE_READY; + p->lengthFound = 0; + continue; + } + + if (p->prevState != STATE_EOM) + { + p->currState = STATE_READY; + p->lengthFound = 0; + Con_DPrintf("Serial: premature EOM\n"); + continue; + } + + switch (p->mtype) + { + case MTYPE_RELIABLE: + Con_DPrintf("Serial: sending ack %u\n", p->sequence); + Serial_SendACK (p, p->sequence); + if (p->sequence == p->sock->receiveSequence) + { + p->sock->receiveSequence = (p->sequence + 1) & 0xff; + p->sock->receiveMessageLength += p->lengthFound; + } + else + Con_DPrintf("Serial: reliable out of order; got %u wanted %u\n", p->sequence, p->sock->receiveSequence); + break; + + case MTYPE_UNRELIABLE: + p->sock->unreliableReceiveSequence = (p->sequence + 1) & 0xff; + p->sock->receiveMessageLength += p->lengthFound; + break; + + case MTYPE_ACK: + Con_DPrintf("Serial: got ack %u\n", p->sequence); + if (p->sequence == p->sock->sendSequence) + { + p->sock->sendSequence = (p->sock->sendSequence + 1) & 0xff; + p->sock->canSend = true; + } + else + Con_DPrintf("Serial: ack out of order; got %u wanted %u\n",p->sequence, p->sock->sendSequence); + break; + + case MTYPE_CONTROL: + p->sock->receiveMessageLength += p->lengthFound; + break; + } + + p->currState = STATE_READY; + p->lengthFound = 0; + continue; + } + + + if (b != ESCAPE_COMMAND) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: Bad escape sequence\n"); + continue; + } + + // b == ESCAPE_COMMAND + p->currState = p->prevState; + } + + p->prevState = p->currState; + +//DEBUG + if (p->sock->receiveMessageLength + p->lengthFound > NET_MAXMESSAGE) + { + Con_DPrintf("Serial blew out receive buffer: %u\n", p->sock->receiveMessageLength + p->lengthFound); + p->currState = STATE_ABORT; + } + if (p->sock->receiveMessageLength + p->lengthFound == NET_MAXMESSAGE) + { + Con_DPrintf("Serial hit receive buffer limit: %u\n", p->sock->receiveMessageLength + p->lengthFound); + p->currState = STATE_ABORT; + } +//end DEBUG + + switch (p->currState) + { + case STATE_READY: + CRC_Init(&p->crcValue); + CRC_ProcessByte(&p->crcValue, b); + if (p->client) + { + if ((b & MTYPE_CLIENT) != 0) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: client got own message\n"); + break; + } + } + else + { + if ((b & MTYPE_CLIENT) == 0) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: server got own message\n"); + break; + } + b &= 0x7f; + } + p->mtype = b; + if (b != MTYPE_CONTROL) + p->currState = STATE_SEQUENCE; + else + p->currState = STATE_LENGTH1; + if (p->mtype < MTYPE_ACK) + { + p->sock->receiveMessage[p->sock->receiveMessageLength] = b; + p->lengthFound++; + } + break; + + case STATE_SEQUENCE: + p->sequence = b; + CRC_ProcessByte(&p->crcValue, b); + if (p->mtype != MTYPE_ACK) + p->currState = STATE_LENGTH1; + else + p->currState = STATE_CRC1; + break; + + case STATE_LENGTH1: + p->lengthStated = b * 256; + CRC_ProcessByte(&p->crcValue, b); + p->currState = STATE_LENGTH2; + break; + + case STATE_LENGTH2: + p->lengthStated += b; + CRC_ProcessByte(&p->crcValue, b); + if (p->mtype == MTYPE_RELIABLE && p->lengthStated > MAX_MSGLEN) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: bad reliable message length %u\n", p->lengthStated); + } + else if (p->mtype == MTYPE_UNRELIABLE && p->lengthStated > MAX_DATAGRAM) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: bad unreliable message length %u\n", p->lengthStated); + } + else + { + p->currState = STATE_DATA; + if (p->mtype < MTYPE_ACK) + { + *(short *)&p->sock->receiveMessage [p->sock->receiveMessageLength + 1] = p->lengthStated; + p->lengthFound += 2; + } + } + break; + + case STATE_DATA: + p->sock->receiveMessage[p->sock->receiveMessageLength + p->lengthFound] = b; + p->lengthFound++; + CRC_ProcessByte(&p->crcValue, b); + if (p->lengthFound == p->lengthStated + 3) + p->currState = STATE_CRC1; + break; + + case STATE_CRC1: + p->crcStated = b * 256; + p->currState = STATE_CRC2; + break; + + case STATE_CRC2: + p->crcStated += b; + if (p->crcStated == CRC_Value(p->crcValue)) + { + p->currState = STATE_EOM; + } + else + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: Bad crc\n"); + } + break; + + case STATE_EOM: + p->currState = STATE_ABORT; + Con_DPrintf("Serial: Bad message format\n"); + break; + + case STATE_ABORT: + break; + } + } + return 0; +} + + +int Serial_Init (void) +{ + int n; + +// LATER do Win32 serial support +#ifdef _WIN32 + return -1; +#endif + + if (COM_CheckParm("-nolan")) + return -1; + if (COM_CheckParm ("-noserial")) + return -1; + + myDriverLevel = net_driverlevel; + + if (TTY_Init()) + return -1; + + for (n = 0; n < NUM_COM_PORTS; n++) + { + serialLine[n].tty = TTY_Open(n); + ResetSerialLineProtocol (&serialLine[n]); + } + + Con_Printf("Serial driver initialized\n"); + serialAvailable = true; + + return 0; +} + + +void Serial_Shutdown (void) +{ + int n; + + for (n = 0; n < NUM_COM_PORTS; n++) + { + if (serialLine[n].connected) + Serial_Close(serialLine[n].sock); + } + + TTY_Shutdown(); +} + + +void Serial_Listen (qboolean state) +{ + listening = state; +} + + +qboolean Serial_CanSendMessage (qsocket_t *sock) +{ + return sock->canSend; +} + + +qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock) +{ + return TTY_OutputQueueIsEmpty(((SerialLine *)sock->driverdata)->tty); +} + + +int Serial_SendMessage (qsocket_t *sock, sizebuf_t *message) +{ + SerialLine *p; + int n; + unsigned short crc; + byte b; + + p = (SerialLine *)sock->driverdata; + CRC_Init (&crc); + + // message type + b = MTYPE_RELIABLE; + if (p->client) + b |= MTYPE_CLIENT; + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // sequence + b = p->sock->sendSequence; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data length + b = message->cursize >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + b = message->cursize & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data + for (n = 0; n < message->cursize; n++) + { + b = message->data[n]; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + } + + // checksum + b = CRC_Value (crc) >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + b = CRC_Value (crc) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + + // end of message + TTY_WriteByte(p->tty, ESCAPE_COMMAND); + TTY_WriteByte(p->tty, ESCAPE_EOM); + + TTY_Flush(p->tty); + + // mark sock as busy and save the message for possible retransmit + sock->canSend = false; + Q_memcpy(sock->sendMessage, message->data, message->cursize); + sock->sendMessageLength = message->cursize; + sock->lastSendTime = net_time; + + return 1; +} + + +static void ReSendMessage (qsocket_t *sock) +{ + sizebuf_t temp; + + Con_DPrintf("Serial: re-sending reliable\n"); + temp.data = sock->sendMessage; + temp.maxsize = sock->sendMessageLength; + temp.cursize = sock->sendMessageLength; + Serial_SendMessage (sock, &temp); +} + + +int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message) +{ + SerialLine *p; + int n; + unsigned short crc; + byte b; + + p = (SerialLine *)sock->driverdata; + + if (!TTY_OutputQueueIsEmpty(p->tty)) + { + TTY_Flush(p->tty); + return 1; + } + + CRC_Init (&crc); + + // message type + b = MTYPE_UNRELIABLE; + if (p->client) + b |= MTYPE_CLIENT; + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // sequence + b = p->sock->unreliableSendSequence; + p->sock->unreliableSendSequence = (b + 1) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data length + b = message->cursize >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + b = message->cursize & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data + for (n = 0; n < message->cursize; n++) + { + b = message->data[n]; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + } + + // checksum + b = CRC_Value (crc) >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + b = CRC_Value (crc) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + + // end of message + TTY_WriteByte(p->tty, ESCAPE_COMMAND); + TTY_WriteByte(p->tty, ESCAPE_EOM); + + TTY_Flush(p->tty); + + return 1; +} + + +static void Serial_SendACK (SerialLine *p, byte sequence) +{ + unsigned short crc; + byte b; + + CRC_Init (&crc); + + // message type + b = MTYPE_ACK; + if (p->client) + b |= MTYPE_CLIENT; + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // sequence + b = sequence; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // checksum + b = CRC_Value (crc) >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + b = CRC_Value (crc) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + + // end of message + TTY_WriteByte(p->tty, ESCAPE_COMMAND); + TTY_WriteByte(p->tty, ESCAPE_EOM); + + TTY_Flush(p->tty); +} + + +static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message) +{ + unsigned short crc; + int n; + byte b; + + CRC_Init (&crc); + + // message type + b = MTYPE_CONTROL; + if (p->client) + b |= MTYPE_CLIENT; + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data length + b = message->cursize >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + b = message->cursize & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data + for (n = 0; n < message->cursize; n++) + { + b = message->data[n]; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + } + + // checksum + b = CRC_Value (crc) >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + b = CRC_Value (crc) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + + // end of message + TTY_WriteByte(p->tty, ESCAPE_COMMAND); + TTY_WriteByte(p->tty, ESCAPE_EOM); + + TTY_Flush(p->tty); +} + + +static int _Serial_GetMessage (SerialLine *p) +{ + byte ret; + short length; + + if (ProcessInQueue(p)) + return -1; + + if (p->sock->receiveMessageLength == 0) + return 0; + + ret = p->sock->receiveMessage[0]; + length = *(short *)&p->sock->receiveMessage[1]; + if (ret == MTYPE_CONTROL) + ret = 1; + + SZ_Clear (&net_message); + SZ_Write (&net_message, &p->sock->receiveMessage[3], length); + + length += 3; + p->sock->receiveMessageLength -= length; + + if (p->sock->receiveMessageLength + p->lengthFound) + Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound); + + return ret; +} + +int Serial_GetMessage (qsocket_t *sock) +{ + SerialLine *p; + int ret; + + p = (SerialLine *)sock->driverdata; + + ret = _Serial_GetMessage (p); + + if (ret == 1) + messagesReceived++; + + if (!sock->canSend) + if ((net_time - sock->lastSendTime) > 1.0) + { + ReSendMessage (sock); + sock->lastSendTime = net_time; + } + + return ret; +} + + +void Serial_Close (qsocket_t *sock) +{ + SerialLine *p = (SerialLine *)sock->driverdata; + TTY_Close(p->tty); + ResetSerialLineProtocol (p); +} + + +char *com_types[] = {"direct", "modem"}; +unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600}; + +void Serial_SearchForHosts (qboolean xmit) +{ + int n; + SerialLine *p; + + if (sv.active) + return; + + if (hostCacheCount == HOSTCACHESIZE) + return; + + // see if we've already answered + for (n = 0; n < hostCacheCount; n++) + if (Q_strcmp (hostcache[n].cname, "#") == 0) + return; + + for (n = 0; n < NUM_COM_PORTS; n++) + if (TTY_IsEnabled(n)) + break; + if (n == NUM_COM_PORTS) + return; + p = &serialLine[n]; + + if (TTY_IsModem(p->tty)) + return; + + sprintf(hostcache[hostCacheCount].name, "COM%u", n+1); + Q_strcpy(hostcache[hostCacheCount].map, ""); + hostcache[hostCacheCount].users = 0; + hostcache[hostCacheCount].maxusers = 0; + hostcache[hostCacheCount].driver = net_driverlevel; + Q_strcpy(hostcache[hostCacheCount].cname, "#"); + hostCacheCount++; + + return; +} + + +static qsocket_t *_Serial_Connect (char *host, SerialLine *p) +{ + int ret; + double start_time; + double last_time; + + p->client = true; + if (TTY_Connect(p->tty, host)) + return NULL; + + p->sock = NET_NewQSocket (); + p->sock->driver = myDriverLevel; + if (p->sock == NULL) + { + Con_Printf("No sockets available\n"); + return NULL; + } + p->sock->driverdata = p; + + // send the connection request + start_time = SetNetTime(); + last_time = 0.0; + + SZ_Clear(&net_message); + MSG_WriteByte(&net_message, CCREQ_CONNECT); + MSG_WriteString(&net_message, "QUAKE"); + do + { + SetNetTime(); + if ((net_time - last_time) >= 1.0) + { + Serial_SendControlMessage (p, &net_message); + last_time = net_time; + Con_Printf("trying...\n"); SCR_UpdateScreen (); + } + ret = _Serial_GetMessage (p); + } + while (ret == 0 && (net_time - start_time) < 5.0); + + if (ret == 0) + { + Con_Printf("Unable to connect, no response\n"); + goto ErrorReturn; + } + + if (ret == -1) + { + Con_Printf("Connection request error\n"); + goto ErrorReturn; + } + + MSG_BeginReading (); + ret = MSG_ReadByte(); + if (ret == CCREP_REJECT) + { + Con_Printf(MSG_ReadString()); + goto ErrorReturn; + } + if (ret != CCREP_ACCEPT) + { + Con_Printf("Unknown connection response\n"); + goto ErrorReturn; + } + + p->connected = true; + p->sock->lastMessageTime = net_time; + + Con_Printf ("Connection accepted\n"); + + return p->sock; + +ErrorReturn: + TTY_Disconnect(p->tty); + return NULL; +} + +qsocket_t *Serial_Connect (char *host) +{ + int n; + qsocket_t *ret = NULL; + + // see if this looks like a phone number + if (*host == '#') + host++; + for (n = 0; n < Q_strlen(host); n++) + if (host[n] == '.' || host[n] == ':') + return NULL; + + for (n = 0; n < NUM_COM_PORTS; n++) + if (TTY_IsEnabled(n) && !serialLine[n].connected) + if ((ret = _Serial_Connect (host, &serialLine[n]))) + break; + return ret; +} + + +static qsocket_t *_Serial_CheckNewConnections (SerialLine *p) +{ + int command; + + p->client = false; + if (!TTY_CheckForConnection(p->tty)) + return NULL; + + if (TTY_IsModem(p->tty)) + { + if (!p->connecting) + { + p->connecting = true; + p->connect_time = net_time; + } + else if ((net_time - p->connect_time) > 15.0) + { + p->connecting = false; + TTY_Disconnect(p->tty); + return NULL; + } + } + + p->sock = NET_NewQSocket (); + p->sock->driver = myDriverLevel; + if (p->sock == NULL) + { + Con_Printf("No sockets available\n"); + return NULL; + } + p->sock->driverdata = p; + + SZ_Clear(&net_message); + if (_Serial_GetMessage(p) != 1) + { + NET_FreeQSocket(p->sock); + return NULL; + } + + MSG_BeginReading (); + command = MSG_ReadByte(); + + if (command == CCREQ_SERVER_INFO) + { + if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) + return NULL; + + if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION) + return NULL; + + SZ_Clear(&net_message); + MSG_WriteByte(&net_message, CCREP_SERVER_INFO); + MSG_WriteString(&net_message, hostname.string); + MSG_WriteString(&net_message, sv.name); + MSG_WriteByte(&net_message, net_activeconnections); + MSG_WriteByte(&net_message, svs.maxclients); + Serial_SendControlMessage (p, &net_message); + SZ_Clear(&net_message); + return NULL; + } + + if (command != CCREQ_CONNECT) + return NULL; + + if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) + return NULL; + + // send him back the info about the server connection he has been allocated + SZ_Clear(&net_message); + MSG_WriteByte(&net_message, CCREP_ACCEPT); + Serial_SendControlMessage (p, &net_message); + SZ_Clear(&net_message); + + p->connected = true; + p->connecting = false; + p->sock->lastMessageTime = net_time; + sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1)); + + return p->sock; +} + +qsocket_t *Serial_CheckNewConnections (void) +{ + int n; + qsocket_t *ret = NULL; + + for (n = 0; n < NUM_COM_PORTS; n++) + if (TTY_IsEnabled(n) && !serialLine[n].connected) + if ((ret = _Serial_CheckNewConnections (&serialLine[n]))) + break; + return ret; +} |
