Annotation of quake1/net_ser.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.