home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / twnsck10 / packet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  12.9 KB  |  532 lines

  1. /*
  2.  *  TwinSock - "Troy's Windows Sockets"
  3.  *
  4.  *  Copyright (C) 1994  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 GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #ifdef __MSDOS__
  23. #include <winsock.h>
  24. #include <stdlib.h>
  25. #else
  26. #include <sys/types.h>
  27. #include <netinet/in.h>
  28. #endif
  29. #include "packet.h"
  30.  
  31. #define    MAX_STREAMS    256
  32.  
  33. short    nInSeq = 0;
  34. short    nOutSeq = 0;
  35.  
  36. extern    int    SendData(void    *pvData, int nBytes);
  37.  
  38. static unsigned long crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
  39. 0x00000000l, 0x77073096l, 0xee0e612cl, 0x990951bal, 0x076dc419l, 0x706af48fl, 0xe963a535l, 0x9e6495a3l,
  40. 0x0edb8832l, 0x79dcb8a4l, 0xe0d5e91el, 0x97d2d988l, 0x09b64c2bl, 0x7eb17cbdl, 0xe7b82d07l, 0x90bf1d91l,
  41. 0x1db71064l, 0x6ab020f2l, 0xf3b97148l, 0x84be41del, 0x1adad47dl, 0x6ddde4ebl, 0xf4d4b551l, 0x83d385c7l,
  42. 0x136c9856l, 0x646ba8c0l, 0xfd62f97al, 0x8a65c9ecl, 0x14015c4fl, 0x63066cd9l, 0xfa0f3d63l, 0x8d080df5l,
  43. 0x3b6e20c8l, 0x4c69105el, 0xd56041e4l, 0xa2677172l, 0x3c03e4d1l, 0x4b04d447l, 0xd20d85fdl, 0xa50ab56bl,
  44. 0x35b5a8fal, 0x42b2986cl, 0xdbbbc9d6l, 0xacbcf940l, 0x32d86ce3l, 0x45df5c75l, 0xdcd60dcfl, 0xabd13d59l,
  45. 0x26d930acl, 0x51de003al, 0xc8d75180l, 0xbfd06116l, 0x21b4f4b5l, 0x56b3c423l, 0xcfba9599l, 0xb8bda50fl,
  46. 0x2802b89el, 0x5f058808l, 0xc60cd9b2l, 0xb10be924l, 0x2f6f7c87l, 0x58684c11l, 0xc1611dabl, 0xb6662d3dl,
  47. 0x76dc4190l, 0x01db7106l, 0x98d220bcl, 0xefd5102al, 0x71b18589l, 0x06b6b51fl, 0x9fbfe4a5l, 0xe8b8d433l,
  48. 0x7807c9a2l, 0x0f00f934l, 0x9609a88el, 0xe10e9818l, 0x7f6a0dbbl, 0x086d3d2dl, 0x91646c97l, 0xe6635c01l,
  49. 0x6b6b51f4l, 0x1c6c6162l, 0x856530d8l, 0xf262004el, 0x6c0695edl, 0x1b01a57bl, 0x8208f4c1l, 0xf50fc457l,
  50. 0x65b0d9c6l, 0x12b7e950l, 0x8bbeb8eal, 0xfcb9887cl, 0x62dd1ddfl, 0x15da2d49l, 0x8cd37cf3l, 0xfbd44c65l,
  51. 0x4db26158l, 0x3ab551cel, 0xa3bc0074l, 0xd4bb30e2l, 0x4adfa541l, 0x3dd895d7l, 0xa4d1c46dl, 0xd3d6f4fbl,
  52. 0x4369e96al, 0x346ed9fcl, 0xad678846l, 0xda60b8d0l, 0x44042d73l, 0x33031de5l, 0xaa0a4c5fl, 0xdd0d7cc9l,
  53. 0x5005713cl, 0x270241aal, 0xbe0b1010l, 0xc90c2086l, 0x5768b525l, 0x206f85b3l, 0xb966d409l, 0xce61e49fl,
  54. 0x5edef90el, 0x29d9c998l, 0xb0d09822l, 0xc7d7a8b4l, 0x59b33d17l, 0x2eb40d81l, 0xb7bd5c3bl, 0xc0ba6cadl,
  55. 0xedb88320l, 0x9abfb3b6l, 0x03b6e20cl, 0x74b1d29al, 0xead54739l, 0x9dd277afl, 0x04db2615l, 0x73dc1683l,
  56. 0xe3630b12l, 0x94643b84l, 0x0d6d6a3el, 0x7a6a5aa8l, 0xe40ecf0bl, 0x9309ff9dl, 0x0a00ae27l, 0x7d079eb1l,
  57. 0xf00f9344l, 0x8708a3d2l, 0x1e01f268l, 0x6906c2fel, 0xf762575dl, 0x806567cbl, 0x196c3671l, 0x6e6b06e7l,
  58. 0xfed41b76l, 0x89d32be0l, 0x10da7a5al, 0x67dd4accl, 0xf9b9df6fl, 0x8ebeeff9l, 0x17b7be43l, 0x60b08ed5l,
  59. 0xd6d6a3e8l, 0xa1d1937el, 0x38d8c2c4l, 0x4fdff252l, 0xd1bb67f1l, 0xa6bc5767l, 0x3fb506ddl, 0x48b2364bl,
  60. 0xd80d2bdal, 0xaf0a1b4cl, 0x36034af6l, 0x41047a60l, 0xdf60efc3l, 0xa867df55l, 0x316e8eefl, 0x4669be79l,
  61. 0xcb61b38cl, 0xbc66831al, 0x256fd2a0l, 0x5268e236l, 0xcc0c7795l, 0xbb0b4703l, 0x220216b9l, 0x5505262fl,
  62. 0xc5ba3bbel, 0xb2bd0b28l, 0x2bb45a92l, 0x5cb36a04l, 0xc2d7ffa7l, 0xb5d0cf31l, 0x2cd99e8bl, 0x5bdeae1dl,
  63. 0x9b64c2b0l, 0xec63f226l, 0x756aa39cl, 0x026d930al, 0x9c0906a9l, 0xeb0e363fl, 0x72076785l, 0x05005713l,
  64. 0x95bf4a82l, 0xe2b87a14l, 0x7bb12bael, 0x0cb61b38l, 0x92d28e9bl, 0xe5d5be0dl, 0x7cdcefb7l, 0x0bdbdf21l,
  65. 0x86d3d2d4l, 0xf1d4e242l, 0x68ddb3f8l, 0x1fda836el, 0x81be16cdl, 0xf6b9265bl, 0x6fb077e1l, 0x18b74777l,
  66. 0x88085ae6l, 0xff0f6a70l, 0x66063bcal, 0x11010b5cl, 0x8f659effl, 0xf862ae69l, 0x616bffd3l, 0x166ccf45l,
  67. 0xa00ae278l, 0xd70dd2eel, 0x4e048354l, 0x3903b3c2l, 0xa7672661l, 0xd06016f7l, 0x4969474dl, 0x3e6e77dbl,
  68. 0xaed16a4al, 0xd9d65adcl, 0x40df0b66l, 0x37d83bf0l, 0xa9bcae53l, 0xdebb9ec5l, 0x47b2cf7fl, 0x30b5ffe9l,
  69. 0xbdbdf21cl, 0xcabac28al, 0x53b39330l, 0x24b4a3a6l, 0xbad03605l, 0xcdd70693l, 0x54de5729l, 0x23d967bfl,
  70. 0xb3667a2el, 0xc4614ab8l, 0x5d681b02l, 0x2a6f2b94l, 0xb40bbe37l, 0xc30c8ea1l, 0x5a05df1bl, 0x2d02ef8dl
  71. };
  72.  
  73. #define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
  74.  
  75. static    short
  76. CalcCRC(data, size)
  77. char *data;
  78. int size;
  79. {
  80.     unsigned long crc = 0xffff;
  81.  
  82.     while (size--)
  83.     {
  84.         crc = UPDC32(*data++, crc);
  85.     }
  86.     crc = ~crc;
  87.     return (crc & 0xffff);
  88. }
  89.  
  90. struct    packet_queue
  91. {
  92.     int            idPacket;
  93.     int            iPacketLen;
  94.     int            iStream;
  95.     struct    packet        *pkt;
  96.     struct    packet_queue    *ppqNext;
  97. };
  98.  
  99. struct    packet_queue *ppqList = 0;
  100. int    iInitialised = 0;
  101. struct    packet_queue *appqStreams[MAX_STREAMS];
  102. char    aiStreams[MAX_STREAMS / 8];
  103.  
  104. #define    STREAM_BIT(x)    (1 << (((x) + 1) % 8))
  105. #define    STREAM_BYTE(x)    aiStreams[((x) + 1) / 8]
  106.  
  107. #define    SET_STREAM(x)    (STREAM_BYTE(x) |= STREAM_BIT(x))
  108. #define    CLR_STREAM(x)    (STREAM_BYTE(x) &= ~STREAM_BIT(x))
  109. #define    GET_STREAM(x)    ((STREAM_BYTE(x) & STREAM_BIT(x)) != 0)
  110.  
  111. static    char ach6bit[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./";
  112.  
  113. int    TransmitData(void *pvData, int iDataLen)
  114. {
  115.     char    *pchDataIn;
  116.     char    *pchDataOut;
  117.     char    c;
  118.     int    iIn, iOut;
  119.     int    nBits;
  120.     int    nBitsLeft;
  121.     int    nBitsNow;
  122.     int    nDataOut;
  123.     char    cNow, cTmp;
  124.  
  125.     nDataOut = iDataLen * 4 / 3 + 1;
  126.     if (iDataLen % 6)
  127.         nDataOut++;
  128.     pchDataIn = (char *) pvData;
  129.     pchDataOut = (char *) malloc(nDataOut);
  130.     nBits = nBitsLeft = 0;
  131.     cNow = 0;
  132.     pchDataOut[0] = '@';    /* Signals the receiving end to realign to bit 0 */
  133.     for (iIn = 0, iOut = 1; iOut < nDataOut;)
  134.     {
  135.         if (nBitsLeft)
  136.         {
  137.             cTmp = c & ((1 << nBitsLeft) - 1);
  138.             nBitsNow = 6 - nBits;
  139.             if (nBitsLeft < nBitsNow)
  140.                 nBitsNow = nBitsLeft;
  141.             cNow <<= nBitsNow;
  142.             cTmp >>= nBitsLeft - nBitsNow;
  143.             cTmp &= ((1 << nBitsNow) - 1);
  144.             cNow |= cTmp;
  145.             nBits += nBitsNow;
  146.             nBitsLeft -= nBitsNow;
  147.             if (nBits == 6)
  148.             {
  149.                 pchDataOut[iOut++] = ach6bit[cNow];
  150.                 cNow = 0;
  151.                 nBits = 0;
  152.             }
  153.         }
  154.         else
  155.         {
  156.             if (iIn < iDataLen)
  157.                 c = pchDataIn[iIn++];
  158.             else
  159.                 c = 0;
  160.             nBitsLeft = 8;
  161.         }
  162.     }
  163.     nDataOut =  SendData(pchDataOut, nDataOut);
  164.     free(pchDataOut);
  165.     return nDataOut;
  166. }
  167.  
  168. void    TransmitHead(void)
  169. {
  170.     TransmitData(ppqList->pkt, ppqList->iPacketLen);
  171.     SetTransmitTimeout();
  172. }
  173.  
  174. void    TimeoutReceived(void)
  175. {
  176.     TransmitHead();
  177. }
  178.  
  179. void    InitHead()
  180. {
  181.     struct packet *pkt;
  182.     short    nCRC;
  183.  
  184.     ppqList->idPacket = nOutSeq;
  185.     pkt = ppqList->pkt;
  186.     pkt->iPacketID = htons(nOutSeq);
  187.     nCRC = CalcCRC(pkt, ppqList->iPacketLen);
  188.     pkt->nCRC = htons(nCRC);
  189.     nOutSeq++;
  190. }
  191.  
  192. void    InsertInQueue(struct packet_queue **pppqNext, struct packet_queue *ppq)
  193. {
  194.     for (; *pppqNext; pppqNext = &((*pppqNext)->ppqNext));
  195.     *pppqNext = ppq;
  196. }
  197.  
  198. void    FlushStream(int    iStream)
  199. {
  200.     struct    packet_queue *ppqPop;
  201.  
  202.     while ((ppqPop = appqStreams[iStream + 1]) != 0)
  203.     {
  204.         appqStreams[iStream + 1] = ppqPop->ppqNext;
  205.         free(ppqPop->pkt);
  206.         free(ppqPop);
  207.     }
  208. }
  209.  
  210. void    PutInQueue(struct packet_queue *ppq, int iStream)
  211. {
  212.     if (iStream == -2) /* Urgent */
  213.     {
  214.         InsertInQueue(&ppqList, ppq);
  215.     }
  216.     else if (GET_STREAM(iStream))
  217.     {
  218.         InsertInQueue(appqStreams + iStream + 1, ppq);
  219.     }
  220.     else
  221.     {
  222.         SET_STREAM(iStream);
  223.         InsertInQueue(&ppqList, ppq);
  224.     }
  225.     if (ppqList == ppq)
  226.     {
  227.         InitHead();
  228.         TransmitHead();
  229.     }
  230. }
  231.  
  232. void    PopListHead(void)
  233. {
  234.     int iStream;
  235.     struct packet_queue *ppqNext, *ppqPop;
  236.  
  237.     iStream = ppqList->iStream;
  238.     ppqNext = ppqList->ppqNext;
  239.     free(ppqList->pkt);
  240.     free(ppqList);
  241.     ppqList = ppqNext;
  242.  
  243.     if (iStream != -2)
  244.     {
  245.         if (appqStreams[iStream + 1])
  246.         {
  247.             ppqPop = appqStreams[iStream + 1];
  248.             appqStreams[iStream + 1] = ppqPop->ppqNext;
  249.             ppqPop->ppqNext = 0;
  250.             InsertInQueue(&ppqList, ppqPop);
  251.         }
  252.         else
  253.         {
  254.             CLR_STREAM(iStream);
  255.         }
  256.     }
  257.  
  258.     if (ppqList)
  259.     {
  260.         InitHead();
  261.         TransmitHead();
  262.     }
  263. }
  264.  
  265. void    SendPacket(void    *pvData, int iDataLen, int iStream)
  266. {
  267.     struct    packet    *pkt;
  268.     struct    packet_queue *ppq;
  269.     short    nCRC;
  270.  
  271.     if (!iInitialised)
  272.     {
  273.         iInitialised = 1;
  274.         memset(aiStreams, 0, sizeof(aiStreams));
  275.         memset(appqStreams, 0, sizeof(appqStreams));
  276.     }
  277.  
  278.     pkt = (struct packet *) malloc(sizeof(struct packet));
  279.     ppq = (struct packet_queue *) malloc(sizeof(struct packet_queue));
  280.  
  281.     ppq->iPacketLen = iDataLen + sizeof(short) * 4;
  282.     ppq->iStream = iStream;
  283.     ppq->pkt = pkt;
  284.     ppq->ppqNext = 0;
  285.  
  286.     pkt->iPacketLen = htons(iDataLen);
  287.     pkt->nCRC = 0;
  288.     pkt->nType = htons((short) PT_Data);
  289.     memcpy(pkt->achData, pvData, iDataLen);
  290.  
  291.     PutInQueue(ppq, iStream);
  292. }
  293.  
  294. void    TransmitAck(short id)
  295. {
  296.     struct packet pkt;
  297.     int    nCRC;
  298.  
  299.     pkt.iPacketLen = 0;
  300.     pkt.nCRC = 0;
  301.     pkt.nType = htons((short) PT_Ack);
  302.     pkt.iPacketID = htons(id);
  303.     nCRC = CalcCRC(&pkt, sizeof(short) * 4);
  304.     pkt.nCRC = htons(nCRC);
  305.     TransmitData(&pkt, sizeof(short) * 4);
  306. }
  307.  
  308. void    ProcessData(void *pvData, int nDataLen)
  309. {
  310.     static    struct    packet    pkt;
  311.     static    int    nBytes = 0;
  312.     int        nToCopy;
  313.     int        nData;
  314.     enum packet_type pt;
  315.     short        iLen;
  316.     short        nCRC;
  317.     short        id;
  318.     short        iLocation;
  319.  
  320.     if (!pvData)    /* Receive timeout */
  321.     {
  322.         nBytes = 0;
  323.         return;
  324.     }
  325.  
  326.     while (nDataLen)
  327.     {
  328.         if (nBytes < sizeof(short) * 4)
  329.         {
  330.             nToCopy = sizeof(short) * 4 - nBytes;
  331.             if (nToCopy > nDataLen)
  332.                 nToCopy = nDataLen;
  333.             memcpy((char *) &pkt + nBytes, pvData, nToCopy);
  334.             pvData = (char *) pvData + nToCopy;
  335.             nDataLen -= nToCopy;
  336.             nBytes += nToCopy;
  337.         }
  338.         if (nBytes < sizeof(short) * 4)
  339.             break;
  340.         pt = (enum packet_type) ntohs(pkt.nType);
  341.         iLen = ntohs(pkt.iPacketLen);
  342.         nCRC = ntohs(pkt.nCRC);
  343.         id = ntohs(pkt.iPacketID);
  344.         if (iLen > PACKET_MAX || iLen < 0) /* Sanity check */
  345.         {
  346.             nBytes = 0;
  347.             nDataLen = 0;
  348.             KillReceiveTimeout();
  349.             if (ppqList)
  350.                 KillTransmitTimeout();
  351.             FlushInput();
  352.             if (ppqList)
  353.                 SetTransmitTimeout();
  354.             return;
  355.         }
  356.         if (nBytes < sizeof(short) * 4 + iLen)
  357.         {
  358.             nToCopy = sizeof(short) * 4 + iLen - nBytes;
  359.             if (nDataLen < nToCopy)
  360.                 nToCopy = nDataLen;
  361.             memcpy((char *) &pkt + nBytes, pvData, nToCopy);
  362.             pvData = (char *) pvData + nToCopy;
  363.             nDataLen -= nToCopy;
  364.             nBytes += nToCopy;
  365.         }
  366.         if (nBytes == sizeof(short) * 4 + iLen)
  367.         {
  368.             nBytes = 0;
  369.             pkt.nCRC = 0;
  370.             if (CalcCRC(&pkt, iLen + sizeof(short) * 4) == nCRC)
  371.             {
  372.                 switch(pt)
  373.                 {
  374.                 case PT_Data:
  375.                     iLocation = nInSeq - id;
  376.                     if (iLocation & 0x8000)
  377.                     {
  378.                         /* We're in trouble */
  379.                         Shutdown();
  380.                     }
  381.                     else
  382.                     {
  383.                         TransmitAck(id);
  384.                         if (!iLocation)
  385.                         {
  386.                             nInSeq++;
  387.                             DataReceived(pkt.achData, iLen);
  388.                         }
  389.                     }
  390.                     break;
  391.  
  392.                 case PT_Nak:
  393.                     if (ppqList &&
  394.                         id == ppqList->idPacket)
  395.                         TransmitHead();
  396.                     break;
  397.  
  398.                 case PT_Ack:
  399.                     if (ppqList &&
  400.                         id == ppqList->idPacket)
  401.                     {
  402.                         KillTransmitTimeout();
  403.                         PopListHead();
  404.                     }
  405.                     break;
  406.  
  407.                 case PT_Shutdown:
  408.                     Shutdown(0);
  409.                     break;
  410.                 }
  411.             }
  412.             else
  413.             {
  414.                 /* If we flush input we should also
  415.                  * reset any tranmit timeout, otherwise
  416.                  * we may resend the packet while flushing,
  417.                  * and flush the Ack. We also kill any
  418.                  * receive timeout because we have already
  419.                  * "flushed" any existing input.
  420.                  */
  421.                 KillReceiveTimeout();
  422.                 if (ppqList)
  423.                     KillTransmitTimeout();
  424.                 FlushInput();
  425.                 if (ppqList)
  426.                     SetTransmitTimeout();
  427.                 return;
  428.             }
  429.         }
  430.     }
  431.     if (nBytes)
  432.         SetReceiveTimeout();
  433. }
  434.  
  435. void    PacketReceiveData(void *pvData, int nDataLen)
  436. {
  437.     static    int    nBits = 0;
  438.     static    char    c = 0;
  439.     static    int    nCtlX = 0;
  440.     char    cIn;
  441.     char    cTmp;
  442.     int    nBitsLeft = 0;
  443.     int    iOut = 0;
  444.     int    nBitsNow;
  445.     char    *pchDataOut;
  446.     char    *pchDataIn;
  447.  
  448.     if (!pvData)
  449.     {
  450.         ProcessData(0, nDataLen);
  451.         nBits = nBitsLeft = 0;
  452.         return;
  453.     }
  454.  
  455.     KillReceiveTimeout();
  456.  
  457.     pchDataIn = (char *) pvData;
  458.     pchDataOut = (char *) malloc(nDataLen);
  459.     while (nDataLen || nBitsLeft)
  460.     {
  461.         if (nBitsLeft)
  462.         {
  463.             nBitsNow = 8 - nBits;
  464.             if (nBitsLeft < nBitsNow)
  465.                 nBitsNow = nBitsLeft;
  466.             c <<= nBitsNow;
  467.             cTmp = cIn >> (nBitsLeft - nBitsNow);
  468.             cTmp &= ((1 << nBitsNow) - 1);
  469.             c |= cTmp;
  470.             nBits += nBitsNow;
  471.             nBitsLeft -= nBitsNow;
  472.             if (nBits == 8)
  473.             {
  474.                 pchDataOut[iOut++] = c;
  475.                 nBits = 0;
  476.             }
  477.         }
  478.         else
  479.         {
  480.             cIn = *pchDataIn++;
  481.             nDataLen--;
  482.             if (cIn == '\030') /* ^X */
  483.             {
  484.                 nCtlX++;
  485.                 if (nCtlX >= 5)
  486.                     Shutdown();
  487.                 continue;
  488.             }
  489.             else
  490.             {
  491.                 nCtlX = 0;
  492.             }
  493.             if (cIn == '@')
  494.             {
  495.                 cIn = c = 0;
  496.                 nBitsLeft = 0;
  497.                 nBits = 0;
  498.             }
  499.             else
  500.             {
  501.                 if (cIn >= 'A' && cIn <= 'Z')
  502.                     cIn -= 'A';
  503.                 else if (cIn >= 'a' && cIn <= 'z')
  504.                     cIn = cIn - 'a' + 26;
  505.                 else if (cIn >= '0' && cIn <= '9')
  506.                     cIn = cIn - '0' + 52;
  507.                 else if (cIn == '.')
  508.                     cIn = 62;
  509.                 else if (cIn == '/')
  510.                     cIn = 63;
  511.                 else
  512.                     continue;
  513.                 nBitsLeft = 6;
  514.             }
  515.         }
  516.     }
  517.     ProcessData(pchDataOut, iOut);
  518.     free(pchDataOut);
  519. }
  520.  
  521. void    PacketTransmitData(void *pvData, int iDataLen, int iStream)
  522. {
  523.     iStream = -2;
  524.     while (iDataLen > PACKET_MAX)
  525.     {
  526.         SendPacket(pvData, PACKET_MAX, iStream);
  527.         pvData = (char *) pvData + PACKET_MAX;
  528.         iDataLen -= PACKET_MAX;
  529.     }
  530.     SendPacket(pvData, iDataLen, iStream);
  531. }
  532.