123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952 |
- /*
- 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;
- }
|