home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / lora299s.zip / JANUS.CPP < prev    next >
C/C++ Source or Header  |  1998-05-12  |  26KB  |  869 lines

  1.  
  2. // LoraBBS Version 2.99 Free Edition
  3. // Copyright (C) 1987-98 Marco Maccaferri
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2 of the License, or
  8. // (at your option) any later version.
  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.  See the
  13. // 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., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include "_ldefs.h"
  20. #include "ftrans.h"
  21.  
  22. #define DLE         0x10
  23.  
  24. /* Protocol capability flags */
  25. #define CANCRC32 0x80
  26. #define CANFREQ  0x40
  27.  
  28. /* File Transmission States */
  29. #define XDONE        0       /* All done, no more files to transmit          */
  30. #define XSENDFNAME   1       /* Send filename packet                         */
  31. #define XRCVFNACK    2       /* Wait for filename packet ACK                 */
  32. #define XSENDBLK     3       /* Send next block of file data                 */
  33. #define XRCVEOFACK   4       /* Wait for EOF packet ACK                      */
  34. #define XSENDFREQNAK 5       /* Send file request NAK (no matches found)     */
  35. #define XRCVFRNAKACK 6       /* Wait for ACK to file request NAK             */
  36.  
  37. /* File Reception States */
  38. #define RDONE      0         /* All done, nothing more to receive            */
  39. #define RRCVFNAME  1         /* Wait for filename packet                     */
  40. #define RRCVBLK    2         /* Wait for next block of file data             */
  41.  
  42. /* Packet Types */
  43. #define NOPKT        0       /* No packet received yet; try again later      */
  44. #define BADPKT      '@'      /* Bad packet received; CRC error, overrun, etc.*/
  45. #define FNAMEPKT    'A'      /* Filename info packet                         */
  46. #define FNACKPKT    'B'      /* Filename packet ACK                          */
  47. #define BLKPKT      'C'      /* File data block packet                       */
  48. #define RPOSPKT     'D'      /* Transmitter reposition packet                */
  49. #define EOFACKPKT   'E'      /* EOF packet ACK                               */
  50. #define HALTPKT     'F'      /* Immediate screeching halt packet             */
  51. #define HALTACKPKT  'G'      /* Halt packet ACK for ending batch             */
  52. #define FREQPKT     'H'      /* File request packet                          */
  53. #define FREQNAKPKT  'I'      /* File request NAK (no matches for your req)   */
  54. #define FRNAKACKPKT 'J'      /* ACK to file request NAK                      */
  55.  
  56. /* Non-byte values returned by rcvbyte() */
  57. #define BUFEMPTY  (-1)
  58. #define PKTSTRT   (-2)
  59. #define PKTEND    (-3)
  60. #define NOCARRIER (-4)
  61. #define PKTSTRT32 (-5)
  62.  
  63. /* Bytes we need to watch for */
  64. #define PKTSTRTCHR   'a'
  65. #define PKTENDCHR    'b'
  66. #define PKTSTRTCHR32 'c'
  67.  
  68. TJanus::TJanus (void)
  69. {
  70.    Com = NULL;
  71.    Log = NULL;
  72.    LastSent = 0;
  73.    CanCrc32 = TRUE;
  74.    Rxbufptr = NULL;
  75.    Rxbufmax = (UCHAR *)(RxBuffer + BUFMAX + 8);
  76.    WaitFlag = FALSE;
  77.    RxPktCrc32 = 0L;
  78.    RxPktCrc16 = 0;
  79.    RxCrc32 = FALSE;
  80.    IsOutbound = FALSE;
  81.    LastPktName = 0L;
  82.    RxTempSize = 0;
  83.    MakeRequests = TRUE;
  84.    AllowRequests = TRUE;
  85.  
  86.    TimeoutSecs = 10;
  87.    Speed = 19200L;
  88.    RxPath[0] = '\0';
  89.    TxQueue = RxQueue = NULL;
  90.    Outbound = NULL;
  91. }
  92.  
  93. TJanus::~TJanus (void)
  94. {
  95. }
  96.  
  97. SHORT TJanus::GetByte (VOID)
  98. {
  99.    SHORT c, w;
  100.  
  101.    if ((c = GetRawByte ()) == DLE) {
  102.       w = WaitFlag;
  103.       WaitFlag = TRUE;
  104.       if ((c = GetRawByte ()) >= 0) {
  105.          switch (c ^= 0x40) {
  106.             case PKTSTRTCHR:
  107.                c = PKTSTRT;
  108.                break;
  109.             case PKTSTRTCHR32:
  110.                c = PKTSTRT32;
  111.                break;
  112.             case PKTENDCHR:
  113.                c = PKTEND;
  114.                break;
  115.          }
  116.       }
  117.       WaitFlag = w;
  118.    }
  119.  
  120.    return (c);
  121. }
  122.  
  123. UCHAR TJanus::GetPacket (VOID)
  124. {
  125.    SHORT c, i;
  126.    UCHAR *p;
  127.    ULONG PktCrc;
  128.  
  129.    WaitFlag = FALSE;
  130.    if ((p = Rxbufptr) == NULL) {
  131.       do {
  132.          c = GetByte ();
  133.       } while (c >= 0 || c == PKTEND);
  134.  
  135.       switch (c) {
  136.          case PKTSTRT:
  137.             RxCrc32 = FALSE;
  138.             p = (UCHAR *)RxBuffer;
  139.             RxPktCrc16 = 0;
  140.             break;
  141.          case PKTSTRT32:
  142.             RxCrc32 = TRUE;
  143.             p = (UCHAR *)RxBuffer;
  144.             RxPktCrc32 = 0xFFFFFFFFL;
  145.             break;
  146.          case NOCARRIER:
  147.             return (HALTPKT);
  148.          default:
  149.             return (NOPKT);
  150.       }
  151.    }
  152.  
  153.    if (RxCrc32 == TRUE) {
  154.       while ((c = GetByte ()) >= 0 && p < Rxbufmax) {
  155.          *p++ = (UCHAR)c;
  156.          RxPktCrc32 = Crc32 ((UCHAR)c, RxPktCrc32);
  157.       }
  158.    }
  159.    else {
  160.       while ((c = GetByte ()) >= 0 && p < Rxbufmax) {
  161.          *p++ = (UCHAR)c;
  162.          RxPktCrc16 = Crc16 ((UCHAR)c, RxPktCrc16);
  163.       }
  164.    }
  165.  
  166.    switch (c) {
  167.       case PKTEND:
  168.          WaitFlag = TRUE;
  169.          PktCrc = 0L;
  170.          for (i = (RxCrc32 == TRUE) ? 4 : 2; i; --i) {
  171.             if ((c = GetByte ()) < 0)
  172.                break;
  173.             PktCrc = (PktCrc << 8) | (UCHAR)c;
  174.          }
  175.          if (i == 0) {
  176.             if ((RxCrc32 && PktCrc == RxPktCrc32) || (USHORT)PktCrc == RxPktCrc16) {
  177.                Rxbufptr = NULL;
  178.                Rxblklen = (USHORT)(--p - RxBuffer);
  179.                return (*p);
  180.             }
  181.          }
  182.          /* fallthrough */
  183.  
  184.       /*---------------------------------------------------------------------*/
  185.       /* Bad CRC, carrier lost, or buffer overflow from munged PKTEND        */
  186.       /*---------------------------------------------------------------------*/
  187.       default:
  188.          if (c == NOCARRIER)
  189.             return (HALTPKT);
  190.          else {
  191.             Rxbufptr = NULL;
  192.             return (BADPKT);
  193.          }
  194.  
  195.       case BUFEMPTY:
  196.          Rxbufptr = p;
  197.          return (NOPKT);
  198.  
  199.       case PKTSTRT:
  200.          RxCrc32 = FALSE;
  201.          Rxbufptr = RxBuffer;
  202.          RxPktCrc16 = 0;
  203.          return (BADPKT);
  204.  
  205.       case PKTSTRT32:
  206.          RxCrc32 = TRUE;
  207.          Rxbufptr = RxBuffer;
  208.          RxPktCrc32 = 0xFFFFFFFFL;
  209.          return (BADPKT);
  210.    }
  211. }
  212.  
  213. SHORT TJanus::GetRawByte (VOID)
  214. {
  215.    ULONG timeval;
  216.  
  217.    if (Com->BytesReady () == TRUE)
  218.       return (Com->ReadByte ());
  219.    if (Com->Carrier () == FALSE)
  220.       return (NOCARRIER);
  221.  
  222.    if (WaitFlag == FALSE)
  223.       return (BUFEMPTY);
  224.  
  225.    timeval = time (NULL) + TimeoutSecs;
  226.  
  227.    while (Com->BytesReady () == FALSE) {
  228.       if (Com->Carrier () == FALSE)
  229.          return (NOCARRIER);
  230.       if (time (NULL) > timeval)
  231.          return (BUFEMPTY);
  232.    }
  233.  
  234.    return (Com->ReadByte ());
  235. }
  236.  
  237. VOID TJanus::SendByte (UCHAR Byte)
  238. {
  239.    switch (Byte) {
  240.       case 0x0D:
  241.          if (LastSent != '@')
  242.             goto sendit;
  243.          /* fallthrough */
  244.       case DLE:
  245.       case XON:
  246.       case XOFF:
  247.          Com->BufferByte (DLE);
  248.          Byte ^= 0x40;
  249.          /* fallthrough */
  250.       default:
  251. sendit:
  252.          Com->BufferByte (LastSent = Byte);
  253.          break;
  254.    }
  255. }
  256.  
  257. VOID TJanus::SendPacket (UCHAR *Buffer, USHORT Len, USHORT Type)
  258. {
  259.    SHORT i;
  260.    USHORT crc;
  261.    ULONG crc32;
  262.  
  263.    Com->BufferByte (DLE);
  264.  
  265.    if (CanCrc32 == TRUE && Type != FNAMEPKT) {
  266.       Com->BufferByte ((UCHAR)(PKTSTRTCHR32 ^ 0x40));
  267.  
  268.       crc32 = 0xFFFFFFFFL;
  269.       if (Buffer != NULL) {
  270.          for (i = 0; i < Len; i++) {
  271.             SendByte ((UCHAR)*Buffer);
  272.             crc32 = Crc32 ((UCHAR)((0377 & *Buffer++)), crc32);
  273.          }
  274.       }
  275.  
  276.       Com->BufferByte ((UCHAR)Type);
  277.       crc32 = Crc32 ((UCHAR)Type, crc32);
  278.  
  279.       Com->BufferByte (DLE);
  280.       Com->BufferByte ((UCHAR)(PKTENDCHR ^ 0x40));
  281.  
  282.       SendByte ((UCHAR)(crc32 >> 24));
  283.       SendByte ((UCHAR)((crc32 >> 16) & 0xFF));
  284.       SendByte ((UCHAR)((crc32 >> 8) & 0xFF));
  285.       SendByte ((UCHAR)(crc32 & 0xFF));
  286.    }
  287.    else {
  288.       Com->BufferByte ((UCHAR)(PKTSTRTCHR ^ 0x40));
  289.  
  290.       crc = 0;
  291.       if (Buffer != NULL) {
  292.          for (i = 0; i < Len; i++) {
  293.             SendByte ((UCHAR)*Buffer);
  294.             crc = Crc16 ((UCHAR)((0377 & *Buffer++)), crc);
  295.          }
  296.       }
  297.  
  298.       Com->BufferByte ((UCHAR)Type);
  299.       crc = Crc16 ((UCHAR)Type, crc);
  300.  
  301.       Com->BufferByte (DLE);
  302.       Com->BufferByte ((UCHAR)(PKTENDCHR ^ 0x40));
  303.  
  304.       SendByte ((UCHAR)(crc >> 8));
  305.       SendByte ((UCHAR)(crc & 0xFF));
  306.    }
  307.  
  308.    Com->UnbufferBytes ();
  309. }
  310.  
  311. LONG TJanus::ProcessFileName (VOID)
  312. {
  313.    SHORT gota, SharedCap;
  314.    CHAR *p, *q, *fileinfo;
  315.    LONG Rxbytes;
  316.    struct stat f;
  317.  
  318.    RxFileName[0] = '\0';
  319.    Rxbytes = -1L;
  320.  
  321.    fileinfo = strchr ((PSZ)RxBuffer, '\0') + 1;
  322.    p = strchr (fileinfo, '\0') + 1;
  323.    SharedCap = (SHORT)((Rxblklen > p - (PSZ)RxBuffer) ? *p & (CANCRC32|CANFREQ) : 0);
  324.    if (SharedCap & CANCRC32)
  325.       CanCrc32 = TRUE;
  326.  
  327.    for (p = (PSZ)RxBuffer, q = (PSZ)RxBuffer; *p; p++) {
  328.       if (*p == '/' || *p == '\\' || *p == ':')
  329.          q = p + 1;
  330.    }
  331.  
  332.    if (*q != '\0') {
  333.       sprintf (RxFileName, "%s%s", RxPath, q);
  334.  
  335.       RxFilesize = RxFiletime = 0L;
  336.       if (*fileinfo)
  337.          sscanf (fileinfo, "%ld %lo", &RxFilesize, &RxFiletime);
  338.  
  339.       Log->Write (" Receiving %s; %ldb, %d min.", q, RxFilesize, (int)((RxFilesize * 10 / Speed + 53) / 54));
  340.  
  341.       if (RxQueue != NULL) {
  342.          RxQueue->New ();
  343.          strcpy (RxQueue->Name, q);
  344.          strcpy (RxQueue->Complete, RxFileName);
  345.          RxQueue->Size = RxFilesize;
  346.       }
  347.  
  348.       Rxbytes = 0L;
  349.       if ((RxFile = sopen (RxFileName, O_RDONLY|O_BINARY, SH_DENYNO, S_IREAD|S_IWRITE)) != -1) {
  350.          fstat (RxFile, &f);
  351.          close (RxFile);
  352.  
  353.          if (RxFilesize == f.st_size && RxFiletime == f.st_mtime) {
  354.             Log->Write ("+Already have %s", RxFileName);
  355.             return (-1L);
  356.          }
  357.          else if (RxFilesize > f.st_size) {
  358.             Rxbytes = f.st_size;
  359.             Log->Write ("+Synchronizing to offset %lu", Rxbytes);
  360.          }
  361.          else {
  362.             if ((p = strchr (RxFileName, '\0')) != NULL) {
  363.                p--;
  364.                gota = FALSE;
  365.                do {
  366.                   if (isdigit (*p) || gota == TRUE) {
  367.                      if (*p == '9') {
  368.                         gota = TRUE;
  369.                         *p = 'A';
  370.                      }
  371.                      else
  372.                         *p = (char)(*p + 1);
  373.                   }
  374.                   else
  375.                      *p = '0';
  376.                   if ((RxFile = sopen (RxFileName, O_RDONLY|O_BINARY, SH_DENYNO, S_IREAD|S_IWRITE)) != -1)
  377.                      close (RxFile);
  378.                } while (RxFile != -1);
  379.                Log->Write ("+Renaming dupe file %s", RxFileName);
  380.             }
  381.          }
  382.       }
  383.  
  384.       if ((RxFile = sopen (RxFileName, O_WRONLY|O_BINARY|O_CREAT|O_APPEND, SH_DENYNO, S_IREAD|S_IWRITE)) == -1)
  385.          return (-1L);
  386.    }
  387.  
  388.    return (Rxbytes);
  389. }
  390.  
  391. VOID TJanus::GetNextFile (VOID)
  392. {
  393.    CHAR *q;
  394.    struct stat f;
  395.  
  396.    TxFileName[0] = '\0';
  397.    TxBuffer[0] = TxBuffer[1] = '\0';
  398.  
  399.    if (TxQueue != NULL) {
  400.       IsOutbound = FALSE;
  401.       while (TxQueue->First () == TRUE) {
  402.          if ((TxFile = sopen (TxQueue->Complete, O_RDONLY|O_BINARY, SH_DENYNO, S_IREAD|S_IWRITE)) != -1) {
  403.             strcpy (TxFileName, TxQueue->Complete);
  404.             strcpy ((PSZ)TxBuffer, TxQueue->Name);
  405.  
  406.             q = strchr ((PSZ)TxBuffer, '\0') + 1;
  407.             fstat (TxFile, &f);
  408.             sprintf (q, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
  409.  
  410.             Log->Write (" Sending %s; %ldb, %d min.", TxQueue->Name, f.st_size, (int)((f.st_size * 10 / Speed + 53) / 54));
  411.             break;
  412.          }
  413.          else
  414.             TxQueue->Remove ();
  415.       }
  416.    }
  417.  
  418.    if (TxFileName[0] == '\0' && Outbound != NULL) {
  419.       IsOutbound = TRUE;
  420.       while (Outbound->First () == TRUE) {
  421.          if (Outbound->Poll == FALSE && (Outbound->Request == FALSE || MakeRequests == TRUE)) {
  422.             if ((TxFile = sopen (Outbound->Complete, O_RDONLY|O_BINARY, SH_DENYNO, S_IREAD|S_IWRITE)) != -1) {
  423.                strcpy (TxFileName, Outbound->Complete);
  424.  
  425.                if (Outbound->MailPKT == TRUE) {
  426.                   while (time (NULL) == LastPktName)
  427.                      ;
  428.                   sprintf ((PSZ)TxBuffer, "%08lx.pkt", time (NULL));
  429.                }
  430.                else
  431.                   strcpy ((PSZ)TxBuffer, Outbound->Name);
  432.  
  433.                q = strchr ((PSZ)TxBuffer, '\0') + 1;
  434.                fstat (TxFile, &f);
  435.                sprintf (q, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
  436.  
  437.                Log->Write (" Sending %s; %ldb, %d min.", Outbound->Name, f.st_size, (int)((f.st_size * 10 / Speed + 53) / 54));
  438.                break;
  439.             }
  440.             else
  441.                Outbound->Remove ();
  442.          }
  443.          else
  444.             Outbound->Remove ();
  445.       }
  446.    }
  447. }
  448.  
  449. VOID TJanus::Transfer (VOID)
  450. {
  451.  
  452.    RxFile = TxFile = -1;
  453.    if (Speed > 64000L)
  454.       txblkmax = BUFMAX;
  455.    else {
  456.       txblkmax = (USHORT)(Speed / 300 * 128);
  457.       if (txblkmax > BUFMAX)
  458.          txblkmax = BUFMAX;
  459.    }
  460.    txblklen = txblkmax;
  461.    xmit_retry = 0L;
  462.    lasttx = txlength = rxstpos = length = 0L;
  463.    rpos_count = 0;
  464.    rpos_sttime = rpos_retry = last_blkpos = 0L;
  465.  
  466.    xstate = XSENDFNAME;
  467.    rstate = RRCVFNAME;
  468.  
  469.    GetNextFile ();
  470.  
  471.    do {
  472.       if (xmit_retry != 0L) {
  473.          if (time (NULL) > xmit_retry) {
  474.             xmit_retry = 0L;
  475.             switch (xstate) {
  476.                case XRCVFNACK:
  477.                   xstate = XSENDFNAME;
  478.                   break;
  479.                case XRCVFRNAKACK:
  480.                   xstate = XSENDFREQNAK;
  481.                   break;
  482.                case XRCVEOFACK:
  483.                   txpos = lasttx;
  484.                   lseek (TxFile, txpos, SEEK_SET);
  485.                   xstate = XSENDBLK;
  486.                   break;
  487.             }
  488.          }
  489.       }
  490.  
  491.       switch (xstate) {
  492.          case XSENDFNAME:
  493.             blklen = (USHORT)(strchr (strchr ((PSZ)TxBuffer, '\0') + 1, '\0') - (PSZ)TxBuffer + 1);
  494.             TxBuffer[blklen++] = (UCHAR)(CANCRC32|CANFREQ);
  495.             SendPacket (TxBuffer, blklen, FNAMEPKT);
  496.             xstate = XRCVFNACK;
  497.             xmit_retry = time (NULL) + TimeoutSecs;
  498. //            Log->Write ("> JAN=XSENDFNAME, XS=%d", xstate);
  499.             SendPacket (NULL, 0, EOFACKPKT);
  500.             break;
  501.          case XSENDBLK:
  502. //            Log->Write ("> JAN=XSENDBLK, XS=%d", xstate);
  503.             *((LONG *)TxBuffer) = lasttx = txpos;
  504.             blklen = (USHORT)read (TxFile, TxBuffer + sizeof (txpos), txblklen);
  505.             SendPacket (TxBuffer, (USHORT)(sizeof (txpos) + blklen), BLKPKT);
  506.             txpos += blklen;
  507.             if (txpos >= filelength (TxFile) || blklen < txblklen) {
  508.                xmit_retry = time (NULL) + TimeoutSecs;
  509.                xstate = XRCVEOFACK;
  510.             }
  511. //            Log->Write ("> JAN=XSENDBLK (END), XS=%d", xstate);
  512.             break;
  513.          case XSENDFREQNAK:
  514.             SendPacket (NULL, 0, FREQNAKPKT);
  515.             xmit_retry = time (NULL) + TimeoutSecs;
  516.             xstate = XRCVFRNAKACK;
  517. //            Log->Write ("> JAN=XSENDFREQNAK, XS=%d", xstate);
  518.             break;
  519.       }
  520.  
  521.       while ((pkttype = GetPacket ()) != 0) {
  522.          switch (pkttype) {
  523.             case BADPKT:
  524.             case BLKPKT:
  525. //               Log->Write ("> JAN=%s, RS=%d", (pkttype == BADPKT) ? "BADPKT" : "BLKPKT", rstate);
  526.                if (rstate == RRCVBLK) {
  527.                   if (pkttype == BADPKT || *((LONG *)RxBuffer) != Rxpos) {
  528.                      if (pkttype == BLKPKT) {
  529.                         if (*((LONG *)RxBuffer) < last_blkpos) {
  530.                            rpos_retry = 0L;
  531.                            rpos_count = 0;
  532.                         }
  533.                         last_blkpos = *((long *)RxBuffer);
  534.                      }
  535.                      if (time (NULL) > rpos_retry) {
  536.                         if (++rpos_count == 1)
  537.                            rpos_sttime = time (NULL);
  538.                         *((LONG *)RxBuffer) = Rxpos;
  539.                         *((LONG *)(RxBuffer + sizeof (Rxpos))) = rpos_sttime;
  540.                         SendPacket (RxBuffer, sizeof (Rxpos) + sizeof (rpos_sttime), RPOSPKT);
  541.                         rpos_retry = time (NULL) + (TimeoutSecs / 2);
  542. //                        Log->Write ("> SEND->RPOSPKT");
  543.                      }
  544.                   }
  545.                   else {
  546.                      last_blkpos = Rxpos;
  547.                      rpos_retry = 0L;
  548.                      rpos_count = 0;
  549.                      Rxblklen -= sizeof (Rxpos);
  550.                      write (RxFile, RxBuffer + sizeof (Rxpos), Rxblklen);
  551.                      Rxpos += Rxblklen;
  552.                      if (Rxpos >= RxFilesize) {
  553.                         close (RxFile);
  554.                         RxFile = -1;
  555.                         if ((length = time (NULL) - length) == 0L)
  556.                            length++;
  557.                         Log->Write ("+CPS: %lu (%lu bytes)  Efficiency: %d%%", (Rxpos - rxstpos) / length, Rxpos, (((Rxpos - rxstpos) / length) * 100L) / (Speed / 10));
  558.                         Log->Write ("+Received-J%s %s", (CanCrc32 == TRUE) ? "/32" : "", strupr (RxFileName));
  559.                         if (RxFiletime) {
  560.                            utimes.actime = RxFiletime;
  561.                            utimes.modtime = RxFiletime;
  562.                            utime (RxFileName, &utimes);
  563.                         }
  564.                         if (RxQueue != NULL)
  565.                            RxQueue->Add ();
  566.                         rstate = RRCVFNAME;
  567.                      }
  568.                   }
  569.                }
  570.                if (rstate == RRCVFNAME)
  571.                   SendPacket (NULL, 0, EOFACKPKT);
  572.                break;
  573.             case FNAMEPKT:
  574. //               Log->Write ("> JAN=FNAMEPKT, RS=%d", rstate);
  575.                if (rstate == RRCVFNAME)
  576.                   Rxpos = rxstpos = ProcessFileName ();
  577.                *((LONG *)RxBuffer) = Rxpos;
  578.                SharedCap = CANFREQ;
  579.                if (CanCrc32 == TRUE)
  580.                   SharedCap |= CANCRC32;
  581.                RxBuffer[sizeof (Rxpos)] = SharedCap;
  582.                SendPacket (RxBuffer, sizeof (Rxpos) + 1, FNACKPKT);
  583.                rstate = (USHORT)((RxFileName[0] != '\0') ? RRCVBLK : RDONE);
  584.                length = time (NULL);
  585.                break;
  586.             case FNACKPKT:
  587. //               Log->Write ("> JAN=FNACKPKT, RS=%d", rstate);
  588.                if (xstate == XRCVFNACK) {
  589.                   xmit_retry = 0L;
  590.                   if (TxFileName[0] != '\0') {
  591.                      SharedCap = (UCHAR)((Rxblklen > sizeof (LONG)) ? RxBuffer[sizeof (LONG)] : 0);
  592.                      if (SharedCap & CANCRC32)
  593.                         CanCrc32 = TRUE;
  594.                      if ((txpos = *((LONG *)RxBuffer)) > -1L) {
  595.                         if (txpos != 0L)
  596.                            Log->Write ("+Synchronizing to offset %lu", txpos);
  597.                         lseek (TxFile, txstpos = txpos, SEEK_SET);
  598.                         xstate = XSENDBLK;
  599.                         txlength = time (NULL);
  600.                      }
  601.                      else {
  602.                         Log->Write ("+Remote refused %s", TxFileName);
  603.                         close (TxFile);
  604.                         if (TxQueue != NULL && IsOutbound == FALSE) {
  605.                            TxQueue->DeleteAfter = TxQueue->TruncateAfter = FALSE;
  606.                            TxQueue->Remove ();
  607.                         }
  608.                         if (Outbound != NULL && IsOutbound == TRUE)
  609.                            Outbound->Remove ();
  610.                         GetNextFile ();
  611.                         xstate = XSENDFNAME;
  612.                      }
  613.                   }
  614.                   else
  615.                      xstate = XDONE;
  616.                }
  617.                break;
  618.             case RPOSPKT:
  619. //               Log->Write ("> JAN=RPOSPKT, RS=%d", rstate);
  620.                if (xstate == XSENDBLK || xstate == XRCVEOFACK) {
  621.                   xmit_retry = 0L;
  622.                   Com->ClearOutbound ();
  623.                   txpos = *((LONG *)RxBuffer);
  624.                   lseek (TxFile, txpos, SEEK_SET);
  625.                   xstate = XSENDBLK;
  626.                }
  627.                break;
  628.             case EOFACKPKT:
  629. //               Log->Write ("> JAN=EOFACKPKT, RS=%d", rstate);
  630.                if (xstate == XRCVEOFACK || xstate == XRCVFNACK) {
  631.                   if (xstate == XRCVEOFACK && TxFile != -1) {
  632.                      close (TxFile);
  633.                      TxFile = -1;
  634.                      xmit_retry = 0L;
  635.                      if ((txlength = time (NULL) - txlength) == 0L)
  636.                         txlength++;
  637.                      if (TxQueue != NULL && IsOutbound == FALSE)
  638.                         Log->Write ("+CPS: %lu (%lu bytes)  Efficiency: %d%%", (TxQueue->Size - txstpos) / txlength, TxQueue->Size, (((TxQueue->Size - txstpos) / txlength) * 100L) / (Speed / 10));
  639.                      if (Outbound != NULL && IsOutbound == TRUE)
  640.                         Log->Write ("+CPS: %lu (%lu bytes)  Efficiency: %d%%", (Outbound->Size - txstpos) / txlength, Outbound->Size, (((Outbound->Size - txstpos) / txlength) * 100L) / (Speed / 10));
  641.                      Log->Write ("+Sent-Z%s %s", (CanCrc32 == TRUE) ? "/32" : "", strupr (TxFileName));
  642.                      if (TxQueue != NULL && IsOutbound == FALSE)
  643.                         TxQueue->Remove ();
  644.                      if (Outbound != NULL && IsOutbound == TRUE)
  645.                         Outbound->Remove ();
  646.                      GetNextFile ();
  647.                   }
  648.                   xstate = XSENDFNAME;
  649.                }
  650.                break;
  651.             case FREQPKT:
  652. //               Log->Write ("> JAN=FREQPKT, RS=%d", rstate);
  653.                if (xstate == XRCVFNACK) {
  654.                   xmit_retry = 0L;
  655.                   SharedCap = *(strchr ((PSZ)RxBuffer, '\0') + 1);
  656.                   xstate = XSENDFREQNAK;
  657.                }
  658.                break;
  659.             case HALTPKT:
  660. //               Log->Write ("> JAN=HALTPKT, RS=%d", rstate);
  661.                SendPacket (NULL, 0, HALTACKPKT);
  662.                xstate = XDONE;
  663.                rstate = RDONE;
  664.                break;
  665.          }
  666.          if (pkttype == HALTPKT || (xstate == XDONE && rstate == RDONE))
  667.             break;
  668.       }
  669.    } while ((xstate != XDONE || rstate != RDONE) && Com->Carrier () == TRUE);
  670.  
  671.    if (RxFile != -1)
  672.       close (RxFile);
  673.    if (TxFile != -1)
  674.       close (TxFile);
  675.  
  676.    if (Outbound != NULL)
  677.       Outbound->Update ();
  678.  
  679. /*
  680.    Done = FALSE;
  681.    SendPacket (NULL, 0, HALTPKT);
  682.    xmit_retry = time (NULL) + (TimeoutSecs / 2);
  683.    timeout = time (NULL) + 2;
  684.  
  685.    while (Done == FALSE && Com->Carrier () == TRUE && time (NULL) < xmit_retry) {
  686.       switch (GetPacket ()) {
  687.          case NOPKT:
  688.          case BADPKT:
  689.             break;
  690.  
  691.          case HALTPKT:
  692.          case HALTACKPKT:
  693.             Done = TRUE;
  694.             break;
  695.  
  696.          default:
  697.             if (time (NULL) >= timeout) {
  698.                SendPacket (NULL, 0, HALTPKT);
  699.                timeout = time (NULL) + 2;
  700.             }
  701.             break;
  702.       }
  703.    }
  704. */
  705.  
  706.    if (Com->Carrier () == TRUE) {
  707.       SendPacket (NULL, 0, HALTACKPKT);
  708.       SendPacket (NULL, 0, HALTACKPKT);
  709.       SendPacket (NULL, 0, HALTACKPKT);
  710.       SendPacket (NULL, 0, HALTACKPKT);
  711.       SendPacket (NULL, 0, HALTACKPKT);
  712.    }
  713. }
  714.  
  715. // ----------------------------------------------------------------------
  716.  
  717. typedef struct {
  718.    USHORT Sent;
  719.    CHAR   Name[32];
  720.    ULONG  Size;
  721.    CHAR   Complete[128];
  722.    UCHAR  DeleteAfter;
  723.    UCHAR  TruncateAfter;
  724. } FILEQUEUE;
  725.  
  726. TFileQueue::TFileQueue (void)
  727. {
  728.    Data.Clear ();
  729.    New ();
  730.    TotalFiles = 0L;
  731. }
  732.  
  733. TFileQueue::~TFileQueue (void)
  734. {
  735.    Data.Clear ();
  736. }
  737.  
  738. USHORT TFileQueue::Add (VOID)
  739. {
  740.    FILEQUEUE Buffer;
  741.  
  742.    memset (&Buffer, 0, sizeof (FILEQUEUE));
  743.  
  744.    Buffer.Sent = Sent;
  745.    strcpy (Buffer.Name, Name);
  746.    strcpy (Buffer.Complete, Complete);
  747.    Buffer.Size = Size;
  748.    Buffer.DeleteAfter = DeleteAfter;
  749.    Buffer.TruncateAfter = TruncateAfter;
  750.    TotalFiles++;
  751.  
  752.    return (Data.Add (&Buffer, sizeof (FILEQUEUE)));
  753. }
  754.  
  755. VOID TFileQueue::Clear (VOID)
  756. {
  757.    Data.Clear ();
  758.    New ();
  759.    TotalFiles = 0L;
  760. }
  761.  
  762. USHORT TFileQueue::First (VOID)
  763. {
  764.    USHORT RetVal = FALSE;
  765.    FILEQUEUE *Buffer;
  766.  
  767.    if ((Buffer = (FILEQUEUE *)Data.First ()) != NULL) {
  768.       Sent = Buffer->Sent;
  769.       strcpy (Name, Buffer->Name);
  770.       strcpy (Complete, Buffer->Complete);
  771.       Size = Buffer->Size;
  772.       DeleteAfter = Buffer->DeleteAfter;
  773.       TruncateAfter = Buffer->TruncateAfter;
  774.       RetVal = TRUE;
  775.    }
  776.  
  777.    return (RetVal);
  778. }
  779.  
  780. VOID TFileQueue::New (VOID)
  781. {
  782.    Sent = FALSE;
  783.    Name[0] = '\0';
  784.    Complete[0] = '\0';
  785.    Size = 0L;
  786.    TruncateAfter = DeleteAfter = FALSE;
  787. }
  788.  
  789. USHORT TFileQueue::Next (VOID)
  790. {
  791.    USHORT RetVal = FALSE;
  792.    FILEQUEUE *Buffer;
  793.  
  794.    if ((Buffer = (FILEQUEUE *)Data.Next ()) != NULL) {
  795.       Sent = Buffer->Sent;
  796.       strcpy (Name, Buffer->Name);
  797.       strcpy (Complete, Buffer->Complete);
  798.       Size = Buffer->Size;
  799.       DeleteAfter = Buffer->DeleteAfter;
  800.       TruncateAfter = Buffer->TruncateAfter;
  801.       RetVal = TRUE;
  802.    }
  803.  
  804.    return (RetVal);
  805. }
  806.  
  807. USHORT TFileQueue::Previous (VOID)
  808. {
  809.    USHORT RetVal = FALSE;
  810.    FILEQUEUE *Buffer;
  811.  
  812.    if ((Buffer = (FILEQUEUE *)Data.Previous ()) != NULL) {
  813.       Sent = Buffer->Sent;
  814.       strcpy (Name, Buffer->Name);
  815.       strcpy (Complete, Buffer->Complete);
  816.       Size = Buffer->Size;
  817.       DeleteAfter = Buffer->DeleteAfter;
  818.       TruncateAfter = Buffer->TruncateAfter;
  819.       RetVal = TRUE;
  820.    }
  821.  
  822.    return (RetVal);
  823. }
  824.  
  825. VOID TFileQueue::Remove (PSZ pszName)
  826. {
  827.    USHORT RetVal = FALSE;
  828.    FILEQUEUE *ft;
  829.  
  830.    if (pszName != NULL) {
  831.       if ((ft = (FILEQUEUE *)Data.First ()) != NULL) {
  832.          do {
  833.             if (!stricmp (ft->Name, pszName)) {
  834.                RetVal = TRUE;
  835.                break;
  836.             }
  837.          } while ((ft = (FILEQUEUE *)Data.Next ()) != NULL);
  838.       }
  839.       if (RetVal == TRUE) {
  840.          if (ft->DeleteAfter == TRUE)
  841.             unlink (ft->Complete);
  842.          Data.Remove ();
  843.       }
  844.    }
  845.    else {
  846.       if (DeleteAfter == TRUE)
  847.          unlink (Complete);
  848.       Data.Remove ();
  849.    }
  850.  
  851.    TotalFiles--;
  852. }
  853.  
  854. VOID TFileQueue::Update (VOID)
  855. {
  856.    FILEQUEUE *Buffer;
  857.  
  858.    if ((Buffer = (FILEQUEUE *)Data.Value ()) != NULL) {
  859.       Buffer->Sent = Sent;
  860.       strcpy (Buffer->Name, Name);
  861.       strcpy (Buffer->Complete, Complete);
  862.       Buffer->Size = Size;
  863.       Buffer->DeleteAfter = DeleteAfter;
  864.       Buffer->TruncateAfter = TruncateAfter;
  865.    }
  866. }
  867.  
  868.  
  869.