Annotation of quake1/net_ser.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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