Annotation of quake1/net_ser.c, revision 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.