home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / net_ser.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  21.4 KB  |  952 lines

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