home *** CD-ROM | disk | FTP | other *** search
/ What PC? 1996 April / WHAT_PC_APR_96.ISO / internet / twinsock / src / packet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-20  |  20.7 KB  |  939 lines

  1. /*
  2.  *  TwinSock - "Troy's Windows Sockets"
  3.  *
  4.  *  Copyright (C) 1994-1995  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the license in the file LICENSE.TXT included
  8.  *  with the TwinSock distribution.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
  13.  */
  14.  
  15. #include <stdio.h>
  16. #ifdef __MSDOS__
  17. #include <winsock.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #else
  21. #include <sys/types.h>
  22. #include <netinet/in.h>
  23. #endif
  24. #include "packet.h"
  25. #include "twinsock.h"
  26.  
  27. #define    MAX_STREAMS    256
  28. #define    WINDOW_SIZE    4
  29.  
  30. short    nInSeq = 0;
  31. short    nOutSeq = 0;
  32.  
  33. long    nCRCErrors = 0;
  34. long    nRetransmits = 0;
  35. long    nTimeouts = 0;
  36. long    nInsane = 0;
  37. long    nIncomplete = 0;
  38.  
  39. enum Encoding eLine = E_6Bit;
  40.  
  41. extern    int    SendData(void    *pvData, int nBytes);
  42.  
  43. static    char    achEscaped[256];
  44. static    int    nEscaped = 0;
  45. static    char    achIgnored[256];
  46. static    int    nIgnored = 0;
  47. static    char    achBuffer[1024];
  48. static    int    nOffset = 0;
  49.  
  50. static unsigned long crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
  51. 0x00000000l, 0x77073096l, 0xee0e612cl, 0x990951bal, 0x076dc419l, 0x706af48fl, 0xe963a535l, 0x9e6495a3l,
  52. 0x0edb8832l, 0x79dcb8a4l, 0xe0d5e91el, 0x97d2d988l, 0x09b64c2bl, 0x7eb17cbdl, 0xe7b82d07l, 0x90bf1d91l,
  53. 0x1db71064l, 0x6ab020f2l, 0xf3b97148l, 0x84be41del, 0x1adad47dl, 0x6ddde4ebl, 0xf4d4b551l, 0x83d385c7l,
  54. 0x136c9856l, 0x646ba8c0l, 0xfd62f97al, 0x8a65c9ecl, 0x14015c4fl, 0x63066cd9l, 0xfa0f3d63l, 0x8d080df5l,
  55. 0x3b6e20c8l, 0x4c69105el, 0xd56041e4l, 0xa2677172l, 0x3c03e4d1l, 0x4b04d447l, 0xd20d85fdl, 0xa50ab56bl,
  56. 0x35b5a8fal, 0x42b2986cl, 0xdbbbc9d6l, 0xacbcf940l, 0x32d86ce3l, 0x45df5c75l, 0xdcd60dcfl, 0xabd13d59l,
  57. 0x26d930acl, 0x51de003al, 0xc8d75180l, 0xbfd06116l, 0x21b4f4b5l, 0x56b3c423l, 0xcfba9599l, 0xb8bda50fl,
  58. 0x2802b89el, 0x5f058808l, 0xc60cd9b2l, 0xb10be924l, 0x2f6f7c87l, 0x58684c11l, 0xc1611dabl, 0xb6662d3dl,
  59. 0x76dc4190l, 0x01db7106l, 0x98d220bcl, 0xefd5102al, 0x71b18589l, 0x06b6b51fl, 0x9fbfe4a5l, 0xe8b8d433l,
  60. 0x7807c9a2l, 0x0f00f934l, 0x9609a88el, 0xe10e9818l, 0x7f6a0dbbl, 0x086d3d2dl, 0x91646c97l, 0xe6635c01l,
  61. 0x6b6b51f4l, 0x1c6c6162l, 0x856530d8l, 0xf262004el, 0x6c0695edl, 0x1b01a57bl, 0x8208f4c1l, 0xf50fc457l,
  62. 0x65b0d9c6l, 0x12b7e950l, 0x8bbeb8eal, 0xfcb9887cl, 0x62dd1ddfl, 0x15da2d49l, 0x8cd37cf3l, 0xfbd44c65l,
  63. 0x4db26158l, 0x3ab551cel, 0xa3bc0074l, 0xd4bb30e2l, 0x4adfa541l, 0x3dd895d7l, 0xa4d1c46dl, 0xd3d6f4fbl,
  64. 0x4369e96al, 0x346ed9fcl, 0xad678846l, 0xda60b8d0l, 0x44042d73l, 0x33031de5l, 0xaa0a4c5fl, 0xdd0d7cc9l,
  65. 0x5005713cl, 0x270241aal, 0xbe0b1010l, 0xc90c2086l, 0x5768b525l, 0x206f85b3l, 0xb966d409l, 0xce61e49fl,
  66. 0x5edef90el, 0x29d9c998l, 0xb0d09822l, 0xc7d7a8b4l, 0x59b33d17l, 0x2eb40d81l, 0xb7bd5c3bl, 0xc0ba6cadl,
  67. 0xedb88320l, 0x9abfb3b6l, 0x03b6e20cl, 0x74b1d29al, 0xead54739l, 0x9dd277afl, 0x04db2615l, 0x73dc1683l,
  68. 0xe3630b12l, 0x94643b84l, 0x0d6d6a3el, 0x7a6a5aa8l, 0xe40ecf0bl, 0x9309ff9dl, 0x0a00ae27l, 0x7d079eb1l,
  69. 0xf00f9344l, 0x8708a3d2l, 0x1e01f268l, 0x6906c2fel, 0xf762575dl, 0x806567cbl, 0x196c3671l, 0x6e6b06e7l,
  70. 0xfed41b76l, 0x89d32be0l, 0x10da7a5al, 0x67dd4accl, 0xf9b9df6fl, 0x8ebeeff9l, 0x17b7be43l, 0x60b08ed5l,
  71. 0xd6d6a3e8l, 0xa1d1937el, 0x38d8c2c4l, 0x4fdff252l, 0xd1bb67f1l, 0xa6bc5767l, 0x3fb506ddl, 0x48b2364bl,
  72. 0xd80d2bdal, 0xaf0a1b4cl, 0x36034af6l, 0x41047a60l, 0xdf60efc3l, 0xa867df55l, 0x316e8eefl, 0x4669be79l,
  73. 0xcb61b38cl, 0xbc66831al, 0x256fd2a0l, 0x5268e236l, 0xcc0c7795l, 0xbb0b4703l, 0x220216b9l, 0x5505262fl,
  74. 0xc5ba3bbel, 0xb2bd0b28l, 0x2bb45a92l, 0x5cb36a04l, 0xc2d7ffa7l, 0xb5d0cf31l, 0x2cd99e8bl, 0x5bdeae1dl,
  75. 0x9b64c2b0l, 0xec63f226l, 0x756aa39cl, 0x026d930al, 0x9c0906a9l, 0xeb0e363fl, 0x72076785l, 0x05005713l,
  76. 0x95bf4a82l, 0xe2b87a14l, 0x7bb12bael, 0x0cb61b38l, 0x92d28e9bl, 0xe5d5be0dl, 0x7cdcefb7l, 0x0bdbdf21l,
  77. 0x86d3d2d4l, 0xf1d4e242l, 0x68ddb3f8l, 0x1fda836el, 0x81be16cdl, 0xf6b9265bl, 0x6fb077e1l, 0x18b74777l,
  78. 0x88085ae6l, 0xff0f6a70l, 0x66063bcal, 0x11010b5cl, 0x8f659effl, 0xf862ae69l, 0x616bffd3l, 0x166ccf45l,
  79. 0xa00ae278l, 0xd70dd2eel, 0x4e048354l, 0x3903b3c2l, 0xa7672661l, 0xd06016f7l, 0x4969474dl, 0x3e6e77dbl,
  80. 0xaed16a4al, 0xd9d65adcl, 0x40df0b66l, 0x37d83bf0l, 0xa9bcae53l, 0xdebb9ec5l, 0x47b2cf7fl, 0x30b5ffe9l,
  81. 0xbdbdf21cl, 0xcabac28al, 0x53b39330l, 0x24b4a3a6l, 0xbad03605l, 0xcdd70693l, 0x54de5729l, 0x23d967bfl,
  82. 0xb3667a2el, 0xc4614ab8l, 0x5d681b02l, 0x2a6f2b94l, 0xb40bbe37l, 0xc30c8ea1l, 0x5a05df1bl, 0x2d02ef8dl
  83. };
  84.  
  85. #define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
  86.  
  87. static    short
  88. CalcCRC(data, size)
  89. char *data;
  90. int size;
  91. {
  92.     unsigned long crc = 0xffff;
  93.  
  94.     while (size--)
  95.     {
  96.         crc = UPDC32(*data++, crc);
  97.     }
  98.     crc = ~crc;
  99.     return ((short)crc & 0xffff);
  100. }
  101.  
  102. struct    packet_queue
  103. {
  104.     int            idPacket;
  105.     int            iPacketLen;
  106.     int            iStream;
  107.     int            iFlags;
  108.     struct    packet        *pkt;
  109.     struct    packet_queue    *ppqNext;
  110. };
  111.  
  112. #define    PQF_LEADER    0x0001
  113. #define    PQF_TRAILER    0x0002
  114.  
  115. static    struct    packet_queue *ppqList = 0;
  116. static    int    iInitialised = 0;
  117. static    struct    packet_queue *appqStreams[MAX_STREAMS];
  118. static    struct    packet_queue *ppqSent = 0;
  119. static    int    nSent = 0;
  120. static    struct    packet_queue *ppqReceived = 0;
  121. static    char    aiStreams[MAX_STREAMS / 8];
  122.  
  123. #define    STREAM_BIT(x)    (1 << (((x) + 1) % 8))
  124. #define    STREAM_BYTE(x)    aiStreams[((x) + 1) / 8]
  125.  
  126. #define    SET_STREAM(x)    (STREAM_BYTE(x) |= STREAM_BIT(x))
  127. #define    CLR_STREAM(x)    (STREAM_BYTE(x) &= ~STREAM_BIT(x))
  128. #define    GET_STREAM(x)    ((STREAM_BYTE(x) & STREAM_BIT(x)) != 0)
  129.  
  130. static    char ach6bit[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./";
  131.  
  132. void    PoppedPacket(struct packet_queue *ppqPopped);
  133. void    PutInQueue(struct packet_queue *ppq, int iStream);
  134.  
  135. void    InsertInQueue(struct packet_queue **pppqNext, struct packet_queue *ppq)
  136. {
  137.     for (; *pppqNext; pppqNext = &((*pppqNext)->ppqNext));
  138.     *pppqNext = ppq;
  139. }
  140.  
  141. void    FlushQueue(struct packet_queue **pppq)
  142. {
  143.     struct    packet_queue *ppqPop;
  144.  
  145.     while ((ppqPop = *pppq) != 0)
  146.     {
  147.         *pppq = ppqPop->ppqNext;
  148.         free(ppqPop->pkt);
  149.         free(ppqPop);
  150.     }
  151. }
  152.  
  153.  
  154. int    TransmitData(void *pvData, int iDataLen)
  155. {
  156.     char    *pchDataIn;
  157.     char    *pchDataOut;
  158.     char    c;
  159.     int    iIn, iOut, iCheck;
  160.     int    nBits;
  161.     int    nBitsLeft;
  162.     int    nBitsNow;
  163.     int    nDataOut;
  164.     char    cNow, cTmp;
  165.     int    nBitsCode;
  166.  
  167.     pchDataIn = (char *) pvData;
  168.     pchDataOut = (char *) malloc(iDataLen * 2 + 1); /* Worst case */
  169.     nBits = nBitsLeft = 0;
  170.     cNow = 0;
  171.     switch(eLine)
  172.     {
  173.     case E_8NoHiCtrl:
  174.     case E_6Bit:
  175.         if (eLine == E_6Bit)
  176.         {
  177.             nBitsCode = 6;
  178.             nDataOut = iDataLen * 4 / 3 + 1;
  179.         }
  180.         else
  181.         {
  182.             nBitsCode = 7;
  183.             nDataOut = (int) ((long) iDataLen * 8 / 7 + 1);
  184.         }
  185.         if (iDataLen % nBitsCode)
  186.             nDataOut++;
  187.         pchDataOut[0] = '@';    /* Signals the receiving end to realign to bit 0 */
  188.         for (iIn = 0, iOut = 1; iOut < nDataOut;)
  189.         {
  190.             if (nBitsLeft)
  191.             {
  192.                 cTmp = c & ((1 << nBitsLeft) - 1);
  193.                 nBitsNow = nBitsCode - nBits;
  194.                 if (nBitsLeft < nBitsNow)
  195.                     nBitsNow = nBitsLeft;
  196.                 cNow <<= nBitsNow;
  197.                 cTmp >>= nBitsLeft - nBitsNow;
  198.                 cTmp &= ((1 << nBitsNow) - 1);
  199.                 cNow |= cTmp;
  200.                 nBits += nBitsNow;
  201.                 nBitsLeft -= nBitsNow;
  202.                 if (nBits == nBitsCode)
  203.                 {
  204.                     if (cNow >= 64)
  205.                     {
  206.                         pchDataOut[iOut] = ach6bit[cNow - 64];
  207.                         pchDataOut[iOut++] |= 0x80;
  208.                     }
  209.                     else
  210.                     {
  211.                         pchDataOut[iOut++] = ach6bit[cNow];
  212.                     }
  213.                     cNow = 0;
  214.                     nBits = 0;
  215.                 }
  216.             }
  217.             else
  218.             {
  219.                 if (iIn < iDataLen)
  220.                     c = pchDataIn[iIn++];
  221.                 else
  222.                     c = 0;
  223.                 nBitsLeft = 8;
  224.             }
  225.         }
  226.         break;
  227.  
  228.     case E_Explicit:
  229.         for (iIn = iOut = 0; iIn < iDataLen; iIn++)
  230.         {
  231.             c = pchDataIn[iIn];
  232.             if (c == '@')
  233.             {
  234.                 strcpy(pchDataOut + iOut, "@ ");
  235.                 iOut += 2;
  236.             }
  237.             else if (c == '\030')
  238.             {
  239.                 pchDataOut[iOut++] = '@';
  240.                 pchDataOut[iOut++] = c + nOffset;
  241.             }
  242.             else
  243.             {
  244.                 for (iCheck = 0; iCheck < nEscaped; iCheck++)
  245.                 {
  246.                     if (achEscaped[iCheck] == c)
  247.                     {
  248.                         pchDataOut[iOut++] = '@';
  249.                         pchDataOut[iOut++] = c + nOffset;
  250.                         break;
  251.                     }
  252.                 }
  253.                 if (iCheck == nEscaped)
  254.                 {
  255.                     pchDataOut[iOut++] = c;
  256.                 }
  257.             }
  258.         }
  259.         nDataOut = iOut;
  260.         break;
  261.  
  262.     case E_8Bit:
  263.     case E_8NoX:
  264.     case E_8NoCtrl:
  265.     case E_8NoHiX:
  266.         for (iIn = 0, iOut = 0; iIn < iDataLen; iIn++)
  267.         {
  268.             c = pchDataIn[iIn];
  269.             if (c == '@')
  270.             {
  271.                 strcpy(pchDataOut + iOut, "@ ");
  272.                 iOut += 2;
  273.             }
  274.             else if (c == '\030')
  275.             {
  276.                 strcpy(pchDataOut + iOut, "@X");
  277.                 iOut += 2;
  278.             }
  279.             else if (eLine == E_8NoX && c == '\023')
  280.             {
  281.                 strcpy(pchDataOut + iOut, "@S");
  282.                 iOut += 2;
  283.             }
  284.             else if (eLine == E_8NoX && c == '\021')
  285.             {
  286.                 strcpy(pchDataOut + iOut, "@Q");
  287.                 iOut += 2;
  288.             }
  289.             else if (eLine == E_8NoHiX && c == '\223')
  290.             {
  291.                 strcpy(pchDataOut + iOut, "@\323");
  292.                 iOut += 2;
  293.             }
  294.             else if (eLine == E_8NoHiX && c == '\221')
  295.             {
  296.                 strcpy(pchDataOut + iOut, "@\321");
  297.                 iOut += 2;
  298.             }
  299.             else if (eLine == E_8NoCtrl &&
  300.                  c >= 0 && c < '\040')
  301.             {
  302.                 pchDataOut[iOut++] = '@';
  303.                 pchDataOut[iOut++] = c + '@';
  304.             }
  305.             else
  306.             {
  307.                 pchDataOut[iOut++] = c;
  308.             }
  309.         }
  310.         nDataOut = iOut;
  311.         break;
  312.     }
  313.     nDataOut =  SendData(pchDataOut, nDataOut);
  314.     free(pchDataOut);
  315.     return nDataOut;
  316. }
  317.  
  318. static    void
  319. TransmitPacket(struct packet_queue *ppqList)
  320. {
  321.     TransmitData(ppqList->pkt, ppqList->iPacketLen);
  322.     SetTransmitTimeout();
  323. }
  324.  
  325. void
  326. InsertIntoIncoming(struct packet *pkt, int iLen)
  327. {
  328.     struct packet_queue *ppq;
  329.     struct packet_queue **pppq;
  330.     struct packet *pktNew;
  331.     int    iPacketID;
  332.  
  333.     iPacketID = ntohs(pkt->iPacketID);
  334.  
  335.     for (    pppq = &ppqReceived;
  336.         *pppq && (*pppq)->idPacket < iPacketID;
  337.         pppq = &(*pppq)->ppqNext);
  338.     if ((*pppq) && (*pppq)->idPacket == iPacketID)
  339.         return;
  340.     pktNew = (struct packet *) malloc(sizeof(struct packet));
  341.     *pktNew = *pkt;
  342.  
  343.     ppq = (struct packet_queue *) malloc(sizeof(struct packet_queue));
  344.     ppq->ppqNext = *pppq;
  345.     ppq->idPacket = iPacketID;
  346.     ppq->pkt = pktNew;
  347.     ppq->iPacketLen = iLen;
  348.     *pppq = ppq;
  349.  
  350.     while (ppqReceived && ppqReceived->idPacket == nInSeq)
  351.     {
  352.         nInSeq++;
  353.         DataReceived(ppqReceived->pkt->achData,
  354.                  ppqReceived->iPacketLen - sizeof(short) * 4);
  355.         ppq = ppqReceived;
  356.         ppqReceived = ppq->ppqNext;
  357.         free(ppq->pkt);
  358.         free(ppq);
  359.     }
  360. }
  361.  
  362.  
  363.  
  364. void    TimeoutReceived(void)
  365. {
  366.     struct    packet_queue *ppq;
  367.  
  368.     nTimeouts++;
  369.     for (ppq = ppqSent; ppq; ppq = ppq->ppqNext)
  370.     {
  371.         nRetransmits++;
  372.         TransmitPacket(ppq);
  373.     }
  374. }
  375.  
  376. void    InitHead()
  377. {
  378.     struct packet *pkt;
  379.     short    nCRC;
  380.  
  381.     ppqList->idPacket = nOutSeq;
  382.     pkt = ppqList->pkt;
  383.     pkt->iPacketID = htons(nOutSeq);
  384.     nCRC = CalcCRC(pkt, ppqList->iPacketLen);
  385.     pkt->nCRC = htons(nCRC);
  386.     nOutSeq++;
  387. }
  388.  
  389. void    TransmitHead(void)
  390. {
  391.     struct packet_queue *ppq;
  392.  
  393.     if (nSent < WINDOW_SIZE)
  394.     {
  395.         nSent++;
  396.         ppq = ppqList;
  397.         ppqList = ppq->ppqNext;
  398.         ppq->ppqNext = 0;
  399.         InsertInQueue(&ppqSent, ppq);
  400.         PoppedPacket(ppq);
  401.         TransmitPacket(ppq);
  402.     }
  403. }
  404.  
  405. static    void
  406. AckReceived(int id)
  407. {
  408.     struct packet_queue **pppq, *ppq, *ppqTemp;
  409.  
  410.     for (pppq = &ppqSent;
  411.          *pppq && (*pppq)->idPacket != id;
  412.          pppq = &(*pppq)->ppqNext);
  413.     ppq = *pppq;
  414.     if (ppq)
  415.     {
  416.         while (ppqSent != ppq)
  417.         {
  418.             ppqTemp = ppqSent;
  419.             ppqSent = ppqTemp->ppqNext;
  420.             ppqTemp->ppqNext = 0;
  421.             InsertInQueue(&ppqSent, ppqTemp);
  422.             TransmitPacket(ppqTemp);
  423.             nRetransmits++;
  424.         }
  425.         ppqTemp = ppqSent;
  426.         ppqSent = ppqTemp->ppqNext;
  427.         free(ppqTemp->pkt);
  428.         free(ppqTemp);
  429.         nSent--;
  430.         if (ppqList)
  431.             TransmitHead();
  432.         if (!ppqSent)
  433.             KillTransmitTimeout();
  434.     }
  435. }
  436.  
  437.  
  438. void    FlushStream(int    iStream)
  439. {
  440.     FlushQueue(appqStreams + iStream + 1);
  441. }
  442.  
  443. void    PutInQueue(struct packet_queue *ppq, int iStream)
  444. {
  445.     if (iStream == -2) /* Urgent */
  446.     {
  447.         InsertInQueue(&ppqList, ppq);
  448.     }
  449.     else if (GET_STREAM(iStream) && 
  450.          (appqStreams[iStream + 1] ||
  451.           (ppq->iFlags & PQF_LEADER)))
  452.     {
  453.         InsertInQueue(appqStreams + iStream + 1, ppq);
  454.     }
  455.     else
  456.     {
  457.         SET_STREAM(iStream);
  458.         InsertInQueue(&ppqList, ppq);
  459.     }
  460.     if (ppqList == ppq)
  461.     {
  462.         InitHead();
  463.         TransmitHead();
  464.     }
  465. }
  466.  
  467. void    PoppedPacket(struct packet_queue *ppqPopped)
  468. {
  469.     int    iStream, iFlags;
  470.     struct    packet_queue *ppqPop;
  471.  
  472.     iStream = ppqPopped->iStream;
  473.     iFlags = ppqPopped->iFlags;
  474.  
  475.     if (iStream != -2 && (iFlags & PQF_TRAILER))
  476.     {
  477.         if (appqStreams[iStream + 1])
  478.         {
  479.             do
  480.             {
  481.                 ppqPop = appqStreams[iStream + 1];
  482.                 appqStreams[iStream + 1] = ppqPop->ppqNext;
  483.                 ppqPop->ppqNext = 0;
  484.                 InsertInQueue(&ppqList, ppqPop);
  485.             } while (!(ppqPop->iFlags & PQF_TRAILER));
  486.         }
  487.         else
  488.         {
  489.             CLR_STREAM(iStream);
  490.         }
  491.     }
  492.  
  493.     if (ppqList)
  494.     {
  495.         InitHead();
  496.         TransmitHead();
  497.     }
  498. }
  499.  
  500. static    int
  501. CopyCharacters(    char    *c,
  502.         char    *achDest)
  503. {
  504.     char    cCurrent;
  505.     int    iTotal = 0;
  506.  
  507.         while (*c)
  508.     {
  509.         while (isspace(*c))
  510.             c++;
  511.         if (*c == '\\')
  512.         {
  513.             cCurrent =     ((int) (c[1] - '0')) * 64 +
  514.                     ((int) (c[2] - '0')) * 8 +
  515.                     ((int) (c[3] - '0'));
  516.             c += 4;
  517.             achDest[iTotal++] = cCurrent;
  518.         }
  519.         else if (*c == '^')
  520.         {
  521.             cCurrent = c[1] - 64;
  522.             c += 2;
  523.             if (*c == '!')
  524.             {
  525.                 cCurrent |= 0x80;
  526.                 c++;
  527.             }
  528.             achDest[iTotal++] = cCurrent;
  529.         }
  530.         while (!isspace(*c) && *c)
  531.             c++;
  532.     }
  533.     return iTotal;
  534. }
  535.  
  536. void
  537. InitProtocol(void)
  538. {
  539.     if (eLine == E_Explicit)
  540.     {
  541.         GetTwinSockSetting(    "Protocol",
  542.                     "Escaped",
  543.                     "",
  544.                     achBuffer,
  545.                     sizeof(achBuffer));
  546.         nEscaped = CopyCharacters(achBuffer, achEscaped);
  547.         GetTwinSockSetting(    "Protocol",
  548.                     "Ignored",
  549.                     "",
  550.                     achBuffer,
  551.                     sizeof(achBuffer));
  552.         nIgnored = CopyCharacters(achBuffer, achIgnored);
  553.         GetTwinSockSetting(    "Protocol",
  554.                     "Offset",
  555.                     "64",
  556.                     achBuffer,
  557.                     sizeof(achBuffer));
  558.         nOffset = atoi(achBuffer);
  559.     }
  560. }
  561.  
  562. void    SendPacket(void    *pvData, int iDataLen, int iStream, int iFlags)
  563. {
  564.     struct    packet    *pkt;
  565.     struct    packet_queue *ppq;
  566.  
  567.     if (!iInitialised)
  568.     {
  569.         iInitialised = 1;
  570.         memset(aiStreams, 0, sizeof(aiStreams));
  571.         memset(appqStreams, 0, sizeof(appqStreams));
  572.     }
  573.  
  574.     pkt = (struct packet *) malloc(sizeof(struct packet));
  575.     ppq = (struct packet_queue *) malloc(sizeof(struct packet_queue));
  576.  
  577.     ppq->iPacketLen = iDataLen + sizeof(short) * 4;
  578.     ppq->iStream = iStream;
  579.     ppq->pkt = pkt;
  580.     ppq->ppqNext = 0;
  581.     ppq->iFlags = iFlags;
  582.  
  583.     pkt->iPacketLen = htons(iDataLen);
  584.     pkt->nCRC = 0;
  585.     pkt->nType = htons((short) PT_Data);
  586.     memcpy(pkt->achData, pvData, iDataLen);
  587.  
  588.     PutInQueue(ppq, iStream);
  589. }
  590.  
  591. void    TransmitAck(short id)
  592. {
  593.     struct packet pkt;
  594.     int    nCRC;
  595.  
  596.     pkt.iPacketLen = 0;
  597.     pkt.nCRC = 0;
  598.     pkt.nType = htons((short) PT_Ack);
  599.     pkt.iPacketID = htons(id);
  600.     nCRC = CalcCRC(&pkt, sizeof(short) * 4);
  601.     pkt.nCRC = htons(nCRC);
  602.     TransmitData(&pkt, sizeof(short) * 4);
  603. }
  604.  
  605. void    ProcessData(void *pvData, int nDataLen)
  606. {
  607.     static    struct    packet    pkt;
  608.     static    int    nBytes = 0;
  609.     int        nToCopy;
  610.     enum packet_type pt;
  611.     short        iLen;
  612.     short        nCRC;
  613.     short        id;
  614.     short        iLocation;
  615.  
  616.     if (!pvData)    /* Receive timeout */
  617.     {
  618.         nIncomplete++;
  619.         nBytes = 0;
  620.         return;
  621.     }
  622.  
  623.     while (nDataLen)
  624.     {
  625.         if (nBytes < sizeof(short) * 4)
  626.         {
  627.             nToCopy = sizeof(short) * 4 - nBytes;
  628.             if (nToCopy > nDataLen)
  629.                 nToCopy = nDataLen;
  630.             memcpy((char *) &pkt + nBytes, pvData, nToCopy);
  631.             pvData = (char *) pvData + nToCopy;
  632.             nDataLen -= nToCopy;
  633.             nBytes += nToCopy;
  634.         }
  635.         if (nBytes < sizeof(short) * 4)
  636.             break;
  637.         pt = (enum packet_type) ntohs(pkt.nType);
  638.         iLen = ntohs(pkt.iPacketLen);
  639.         nCRC = ntohs(pkt.nCRC);
  640.         id = ntohs(pkt.iPacketID);
  641.         if (iLen > PACKET_MAX || iLen < 0) /* Sanity check */
  642.         {
  643.             nInsane++;
  644.             nBytes = 0;
  645.             nDataLen = 0;
  646.             KillReceiveTimeout();
  647.             if (ppqList)
  648.                 KillTransmitTimeout();
  649.             FlushInput();
  650.             if (ppqList)
  651.                 SetTransmitTimeout();
  652.             return;
  653.         }
  654.         if (nBytes < ((int) sizeof(short) * 4 + iLen))
  655.         {
  656.             nToCopy = sizeof(short) * 4 + iLen - nBytes;
  657.             if (nDataLen < nToCopy)
  658.                 nToCopy = nDataLen;
  659.             memcpy((char *) &pkt + nBytes, pvData, nToCopy);
  660.             pvData = (char *) pvData + nToCopy;
  661.             nDataLen -= nToCopy;
  662.             nBytes += nToCopy;
  663.         }
  664.         if (nBytes == ((int) sizeof(short) * 4 + iLen))
  665.         {
  666.             nBytes = 0;
  667.             pkt.nCRC = 0;
  668.             if (CalcCRC(&pkt, iLen + sizeof(short) * 4) == nCRC)
  669.             {
  670.                 switch(pt)
  671.                 {
  672.                 case PT_Data:
  673.                     iLocation = nInSeq - id;
  674.                     TransmitAck(id);
  675.                     if (iLocation <= 0)
  676.                         InsertIntoIncoming(&pkt, iLen + sizeof(short) * 4);
  677.                     break;
  678.  
  679.                 case PT_Nak:
  680.                     if (ppqList &&
  681.                         id == ppqList->idPacket)
  682.                         TransmitHead();
  683.                     break;
  684.  
  685.                 case PT_Ack:
  686.                     AckReceived(id);
  687.                     break;
  688.  
  689.                 case PT_Shutdown:
  690.                     Shutdown();
  691.                     break;
  692.                 }
  693.             }
  694.             else
  695.             {
  696.                 /* If we flush input we should also
  697.                  * reset any tranmit timeout, otherwise
  698.                  * we may resend the packet while flushing,
  699.                  * and flush the Ack. We also kill any
  700.                  * receive timeout because we have already
  701.                  * "flushed" any existing input.
  702.                  */
  703.                 nCRCErrors++;
  704.                 KillReceiveTimeout();
  705.                 if (ppqList)
  706.                     KillTransmitTimeout();
  707.                 FlushInput();
  708.                 if (ppqList)
  709.                     SetTransmitTimeout();
  710.                 return;
  711.             }
  712.         }
  713.     }
  714.     if (nBytes)
  715.         SetReceiveTimeout();
  716. }
  717.  
  718. void    PacketReceiveData(void *pvData, int nDataLen)
  719. {
  720.     static    int    nBits = 0;
  721.     static    char    c = 0;
  722.     static    int    nCtlX = 0;
  723.     char    cIn;
  724.     char    cTmp;
  725.     int    nBitsLeft = 0;
  726.     int    iOut = 0;
  727.     int    i;
  728.     int    nBitsNow;
  729.     char    *pchDataOut;
  730.     char    *pchDataIn;
  731.     int    nBitsCode;
  732.     int    iHighSet;
  733.  
  734.     if (!pvData)
  735.     {
  736.         ProcessData(0, nDataLen);
  737.         nBits = nBitsLeft = 0;
  738.         return;
  739.     }
  740.  
  741.     KillReceiveTimeout();
  742.  
  743.     pchDataIn = (char *) pvData;
  744.     pchDataOut = (char *) malloc(nDataLen);
  745.     switch(eLine)
  746.     {
  747.     case E_6Bit:
  748.     case E_8NoHiCtrl:
  749.         if (eLine == E_6Bit)
  750.             nBitsCode = 6;
  751.         else
  752.             nBitsCode = 7;
  753.         while (nDataLen || nBitsLeft)
  754.         {
  755.             if (nBitsLeft)
  756.             {
  757.                 nBitsNow = 8 - nBits;
  758.                 if (nBitsLeft < nBitsNow)
  759.                     nBitsNow = nBitsLeft;
  760.                 c <<= nBitsNow;
  761.                 cTmp = cIn >> (nBitsLeft - nBitsNow);
  762.                 cTmp &= ((1 << nBitsNow) - 1);
  763.                 c |= cTmp;
  764.                 nBits += nBitsNow;
  765.                 nBitsLeft -= nBitsNow;
  766.                 if (nBits == 8)
  767.                 {
  768.                     pchDataOut[iOut++] = c;
  769.                     nBits = 0;
  770.                 }
  771.             }
  772.             else
  773.             {
  774.                 cIn = *pchDataIn++;
  775.                 nDataLen--;
  776.                 if (cIn == '\030') /* ^X */
  777.                 {
  778.                     nCtlX++;
  779.                     if (nCtlX >= 5)
  780.                         Shutdown();
  781.                     continue;
  782.                 }
  783.                 else
  784.                 {
  785.                     nCtlX = 0;
  786.                 }
  787.                 if (cIn == '@')
  788.                 {
  789.                     cIn = c = 0;
  790.                     nBitsLeft = 0;
  791.                     nBits = 0;
  792.                 }
  793.                 else
  794.                 {
  795.                     if (cIn & 0x80)
  796.                     {
  797.                         iHighSet = 1;
  798.                         cIn &= 0x7f;
  799.                     }
  800.                     else
  801.                     {
  802.                         iHighSet = 0;
  803.                     }
  804.                     if (cIn >= 'A' && cIn <= 'Z')
  805.                         cIn -= 'A';
  806.                     else if (cIn >= 'a' && cIn <= 'z')
  807.                         cIn = cIn - 'a' + 26;
  808.                     else if (cIn >= '0' && cIn <= '9')
  809.                         cIn = cIn - '0' + 52;
  810.                     else if (cIn == '.')
  811.                         cIn = 62;
  812.                     else if (cIn == '/')
  813.                         cIn = 63;
  814.                     else
  815.                         continue;
  816.                     if (iHighSet)
  817.                         cIn += 64;
  818.                     nBitsLeft = nBitsCode;
  819.                 }
  820.             }
  821.         }
  822.         break;
  823.  
  824.     case E_Explicit:
  825.         while (nDataLen--)
  826.         {
  827.             cIn = *pchDataIn++;
  828.             if (cIn == '\030') /* ^X */
  829.             {
  830.                 nCtlX++;
  831.                 if (nCtlX >= 5)
  832.                     Shutdown();
  833.                 continue;
  834.             }
  835.             else
  836.             {
  837.                 nCtlX = 0;
  838.             }
  839.             for (i = 0; i < nIgnored; i++)
  840.                 if (achIgnored[i] == cIn)
  841.                     break;
  842.             if (i < nIgnored)
  843.                 continue;
  844.             if (nBits == 1)
  845.             {
  846.                 if (cIn == ' ')
  847.                     pchDataOut[iOut++] = '@';
  848.                 else
  849.                     pchDataOut[iOut++] = cIn - nOffset;
  850.                 nBits = 0;
  851.             }
  852.             else if (cIn == '@')
  853.             {
  854.                 nBits = 1;
  855.             }
  856.             else
  857.             {
  858.                 pchDataOut[iOut++] =cIn;
  859.             }
  860.         }
  861.         break;
  862.  
  863.     case E_8Bit:
  864.     case E_8NoX:
  865.     case E_8NoCtrl:
  866.     case E_8NoHiX:
  867.         while (nDataLen--)
  868.         {
  869.             cIn = *pchDataIn++;
  870.             if (cIn == '\030') /* ^X */
  871.             {
  872.                 nCtlX++;
  873.                 if (nCtlX >= 5)
  874.                     Shutdown();
  875.                 continue;
  876.             }
  877.             else
  878.             {
  879.                 nCtlX = 0;
  880.             }
  881.             if (nBits == 1)
  882.             {
  883.                 if (cIn == ' ')
  884.                     pchDataOut[iOut++] = '@';
  885.                 else
  886.                     pchDataOut[iOut++] = cIn - '@';
  887.                 nBits = 0;
  888.             }
  889.             else if (nBits == 2)
  890.             {
  891.                 pchDataOut[iOut++] = cIn | 0x80;
  892.             }
  893.             else if (nBits == 3)
  894.             {
  895.                 pchDataOut[iOut++] = (cIn - '@') | 0x80;
  896.             }
  897.             else if (cIn == '@')
  898.             {
  899.                 nBits = 1;
  900.             }
  901.             else
  902.             {
  903.                 pchDataOut[iOut++] = cIn;
  904.             }
  905.         }
  906.         break;
  907.     }
  908.     ProcessData(pchDataOut, iOut);
  909.     free(pchDataOut);
  910. }
  911.  
  912. void    PacketTransmitData(void *pvData, int iDataLen, int iStream)
  913. {
  914.     int    iFlags = PQF_LEADER;
  915.  
  916.     while (iDataLen > PACKET_MAX)
  917.     {
  918.         SendPacket(pvData, PACKET_MAX, iStream, iFlags);
  919.         pvData = (char *) pvData + PACKET_MAX;
  920.         iDataLen -= PACKET_MAX;
  921.         iFlags = 0;
  922.     }
  923.     iFlags |= PQF_TRAILER;
  924.     SendPacket(pvData, iDataLen, iStream, iFlags);
  925. }
  926.  
  927.  
  928. void
  929. ReInitPackets(void)
  930. {
  931.     int    i;
  932.  
  933.     nInSeq = nOutSeq = 0;
  934.     for (i = 0; i < MAX_STREAMS; i++)
  935.         FlushQueue(appqStreams + i);
  936.     FlushQueue(&ppqList);
  937.     memset(aiStreams, 0, sizeof(aiStreams));
  938. }
  939.