home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / C / HSRC_100 / HYDRA.C < prev    next >
C/C++ Source or Header  |  1993-01-11  |  90KB  |  1,993 lines

  1. /*=============================================================================
  2.  
  3.                               HydraCom Version 1.00
  4.  
  5.                          A sample implementation of the
  6.                    HYDRA Bi-Directional File Transfer Protocol
  7.  
  8.                              HydraCom was written by
  9.                    Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT
  10.                   COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
  11.  
  12.                        The HYDRA protocol was designed by
  13.                  Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT and
  14.                              Joaquim H. Homrighausen
  15.                   COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
  16.  
  17.  
  18.   Revision history:
  19.   06 Sep 1991 - (AGL) First tryout
  20.   .. ... .... - Internal development
  21.   11 Jan 1993 - HydraCom version 1.00, Hydra revision 001 (01 Dec 1992)
  22.  
  23.  
  24.   For complete details of the Hydra and HydraCom licensing restrictions,
  25.   please refer to the license agreements which are published in their entirety
  26.   in HYDRACOM.C and LICENSE.DOC, and also contained in the documentation file
  27.   HYDRACOM.DOC
  28.  
  29.   Use of this file is subject to the restrictions contained in the Hydra and
  30.   HydraCom licensing agreements. If you do not find the text of this agreement
  31.   in any of the aforementioned files, or if you do not have these files, you
  32.   should immediately contact LENTZ SOFTWARE-DEVELOPMENT and/or Joaquim 
  33.   Homrighausen at one of the addresses listed below. In no event should you
  34.   proceed to use this file without having accepted the terms of the Hydra and
  35.   HydraCom licensing agreements, or such other agreement as you are able to
  36.   reach with LENTZ SOFTWARE-DEVELOMENT and Joaquim Homrighausen.
  37.  
  38.  
  39.   Hydra protocol design and HydraCom driver:         Hydra protocol design:
  40.   Arjen G. Lentz                                     Joaquim H. Homrighausen
  41.   LENTZ SOFTWARE-DEVELOPMENT                         389, route d'Arlon
  42.   Langegracht 7B                                     L-8011 Strassen
  43.   3811 BT  Amersfoort                                Luxembourg
  44.   The Netherlands
  45.   FidoNet 2:283/512, AINEX-BBS +31-33-633916         FidoNet 2:270/17
  46.   arjen_lentz@f512.n283.z2.fidonet.org               joho@ae.lu
  47.  
  48.   Please feel free to contact us at any time to share your comments about our
  49.   software and/or licensing policies.
  50.  
  51. =============================================================================*/
  52.  
  53. #include "hydracom.h"                             /* need 2types.h & hydra.h */
  54.  
  55.  
  56. #define H_DEBUG 1
  57.  
  58.  
  59. /* HYDRA Some stuff to aid readability of the source and prevent typos ----- */
  60. #define h_updcrc16(crc,c)  (crc16tab[(       crc ^ (c)) & 0xff] ^ ((crc >> 8) & 0x00ff))
  61. #define h_updcrc32(crc,c)  (crc32tab[((byte) crc ^ (c)) & 0xff] ^ ((crc >> 8) & 0x00ffffffL))
  62. #define h_crc16poly        (0x8408)
  63. #define h_crc32poly        (0xedb88320L)
  64. #define h_crc16test(crc)   (((crc) == 0xf0b8     ) ? 1 : 0)
  65. #define h_crc32test(crc)   (((crc) == 0xdebb20e3L) ? 1 : 0)
  66. #define h_uuenc(c)         (((c) & 0x3f) + '!')
  67. #define h_uudec(c)         (((c) - '!') & 0x3f)
  68. #define h_long1(buf)       (*((long *) (buf)))
  69. #define h_long2(buf)       (*((long *) ((buf) + ((int) sizeof (long)))))
  70. #define h_long3(buf)       (*((long *) ((buf) + (2 * ((int) sizeof (long))))))
  71. typedef long               h_timer;
  72. #define h_timer_set(t)     (time(NULL) + (t))
  73. #define h_timer_running(t) (t != 0L)
  74. #define h_timer_expired(t) (time(NULL) > (t))
  75. #define h_timer_reset()    (0L)
  76.  
  77.  
  78. /* HYDRA's memory ---------------------------------------------------------- */
  79. static  boolean originator;                     /* are we the orig side?     */
  80. static  int     batchesdone;                    /* No. HYDRA batches done    */
  81. static  boolean hdxlink;                        /* hdx link & not orig side  */
  82. static  dword   options;                        /* INIT options hydra_init() */
  83. static  word    timeout;                        /* general timeout in secs   */
  84. static  char    abortstr[] = { 24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 };
  85. static  char   *hdxmsg     = "Fallback to one-way xfer";
  86. static  char   *pktprefix  = "";
  87. static  char   *autostr    = "hydra\r";
  88. static  word   *crc16tab;                       /* CRC-16 table              */
  89. static  dword  *crc32tab;                       /* CRC-32 table              */
  90.  
  91. static  byte   *txbuf,         *rxbuf;          /* packet buffers            */
  92. static  dword   txoptions,      rxoptions;      /* HYDRA options (INIT seq)  */
  93. static  char    txpktprefix[H_PKTPREFIX + 1];   /* pkt prefix str they want  */
  94. static  long    txwindow,       rxwindow;       /* window size (0=streaming) */
  95. static  h_timer                 braindead;      /* braindead timer           */
  96. static  byte   *txbufin;                        /* read data from disk here  */
  97. static  byte    txlastc;                        /* last byte put in txbuf    */
  98. static  byte                    rxdle;          /* count of received H_DLEs  */
  99. static  byte                    rxpktformat;    /* format of pkt receiving   */
  100. static  byte                   *rxbufptr;       /* current position in rxbuf */
  101. static  byte                   *rxbufmax;       /* highwatermark of rxbuf    */
  102. static  char    txfname[13],    rxfname[13];    /* fname of current files    */
  103. static  char                   *rxpathname;     /* pointer to rx pathname    */
  104. static  long    txftime,        rxftime;        /* file timestamp (UNIX)     */
  105. static  long    txfsize,        rxfsize;        /* file length               */
  106. static  int     txfd,           rxfd;           /* file handles              */
  107. static  word                    rxpktlen;       /* length of last packet     */
  108. static  word                    rxblklen;       /* len of last good data blk */
  109. static  byte    txstate,        rxstate;        /* xmit/recv states          */
  110. static  long    txpos,          rxpos;          /* current position in files */
  111. static  word    txblklen;                       /* length of last block sent */
  112. static  word    txmaxblklen;                    /* max block length allowed  */
  113. static  long    txlastack;                      /* last dataack received     */
  114. static  long    txstart,        rxstart;        /* time we started this file */
  115. static  long    txoffset,       rxoffset;       /* offset in file we begun   */
  116. static  h_timer txtimer,        rxtimer;        /* retry timers              */
  117. static  word    txretries,      rxretries;      /* retry counters            */
  118. static  long                    rxlastsync;     /* filepos last sync retry   */
  119. static  long    txsyncid,       rxsyncid;       /* id of last resync         */
  120. static  word    txgoodneeded;                   /* to send before larger blk */
  121. static  word    txgoodbytes;                    /* no. sent at this blk size */
  122.  
  123. struct _h_flags {
  124.         char  *str;
  125.         dword  val;
  126. };
  127.  
  128. static struct _h_flags h_flags[] = {
  129.         { "XON", HOPT_XONXOFF },
  130.         { "TLN", HOPT_TELENET },
  131.         { "CTL", HOPT_CTLCHRS },
  132.         { "HIC", HOPT_HIGHCTL },
  133.         { "HI8", HOPT_HIGHBIT },
  134.         { "BRK", HOPT_CANBRK  },
  135.         { "ASC", HOPT_CANASC  },
  136.         { "UUE", HOPT_CANUUE  },
  137.         { "C32", HOPT_CRC32   },
  138.         { "DEV", HOPT_DEVICE  },
  139.         { "FPT", HOPT_FPT     },
  140.         { NULL , 0x0L         }
  141. };
  142.  
  143.  
  144. /*---------------------------------------------------------------------------*/
  145. static void hydra_msgdev (byte *data, word len)
  146. {       /* text is already NUL terminated by calling func hydra_devrecv() */
  147.         len = len;
  148.         message(3,"*HMSGDEV: %s",data);
  149. }/*hydra_msgdev()*/
  150.  
  151.  
  152. /*---------------------------------------------------------------------------*/
  153. static  word    devtxstate;                     /* dev xmit state            */
  154. static  h_timer devtxtimer;                     /* dev xmit retry timer      */
  155. static  word    devtxretries;                   /* dev xmit retry counter    */
  156. static  long    devtxid,        devrxid;        /* id of last devdata pkt    */
  157. static  char    devtxdev[H_FLAGLEN + 1];        /* xmit device ident flag    */
  158. static  byte   *devtxbuf;                       /* ptr to usersupplied dbuf  */
  159. static  word    devtxlen;                       /* len of data in xmit buf   */
  160.  
  161. struct _h_dev {
  162.         char  *dev;
  163.         void (*func) (byte *data, word len);
  164. };
  165.  
  166. static  struct _h_dev h_dev[] = {
  167.         { "MSG", hydra_msgdev },                /* internal protocol msg     */
  168.         { "CON", NULL         },                /* text to console (chat)    */
  169.         { "PRN", NULL         },                /* data to printer           */
  170.         { "ERR", NULL         },                /* text to error output      */
  171.         { NULL , NULL         }
  172. };
  173.  
  174.  
  175. /*---------------------------------------------------------------------------*/
  176. boolean hydra_devfree (void)
  177. {
  178.         if (devtxstate || !(txoptions & HOPT_DEVICE) || txstate >= HTX_END)
  179.            return (false);                      /* busy or not allowed       */
  180.         else
  181.            return (true);                       /* allowed to send a new pkt */
  182. }/*hydra_devfree()*/
  183.  
  184.  
  185. /*---------------------------------------------------------------------------*/
  186. boolean hydra_devsend (char *dev, byte *data, word len)
  187. {
  188.         if (!dev || !data || !len || !hydra_devfree())
  189.            return (false);
  190.  
  191.         strncpy(devtxdev,dev,H_FLAGLEN);
  192.         devtxdev[H_FLAGLEN] = '\0';
  193.         strupr(devtxdev);
  194.         devtxbuf = data;
  195.         devtxlen = (len > H_MAXBLKLEN) ? H_MAXBLKLEN : len;
  196.  
  197.         devtxid++;
  198.         devtxtimer   = h_timer_reset();
  199.         devtxretries = 0;
  200.         devtxstate   = HTD_DATA;
  201.  
  202.         /* special for chat, only prolong life if our side keeps typing! */
  203.         if (chattimer > 0L && !strcmp(devtxdev,"CON") && txstate == HTX_REND)
  204.            braindead = h_timer_set(H_BRAINDEAD);
  205.  
  206.         return (true);
  207. }/*hydra_devsend()*/
  208.  
  209.  
  210. /*---------------------------------------------------------------------------*/
  211. boolean hydra_devfunc (char *dev, void (*func) (byte *data, word len))
  212. {
  213.         register int i;
  214.  
  215.         for (i = 0; h_dev[i].dev; i++) {
  216.             if (!strnicmp(dev,h_dev[i].dev,H_FLAGLEN)) {
  217.                h_dev[i].func = func;
  218.                return (true);
  219.             }
  220.         }
  221.  
  222.         return (false);
  223. }/*hydra_devfunc()*/
  224.  
  225.  
  226. /*---------------------------------------------------------------------------*/
  227. static void hydra_devrecv (void)
  228. {
  229.         register char *p = (char *) rxbuf;
  230.         register int   i;
  231.         word len = rxpktlen;
  232.  
  233.         p += (int) sizeof (long);                       /* skip the id long  */
  234.         len -= (int) sizeof (long);
  235.         for (i = 0; h_dev[i].dev; i++) {                /* walk through devs */
  236.             if (!strncmp(p,h_dev[i].dev,H_FLAGLEN)) {
  237.                if (h_dev[i].func) {
  238.                   len -= ((int) strlen(p)) + 1;         /* sub devstr len    */
  239.                   p += ((int) strlen(p)) + 1;           /* skip devtag       */
  240.                   p[len] = '\0';                        /* NUL terminate     */
  241.                   (*h_dev[i].func)((byte *) p,len);     /* call output func  */
  242.                }
  243.                break;
  244.             }
  245.         }
  246. }/*hydra_devrecv()*/
  247.  
  248.  
  249. /*---------------------------------------------------------------------------*/
  250. static void put_flags (char *buf, struct _h_flags flags[], long val)
  251. {
  252.         register char *p;
  253.         register int   i;
  254.  
  255.         p = buf;
  256.         for (i = 0; flags[i].val; i++) {
  257.             if (val & flags[i].val) {
  258.                if (p > buf) *p++ = ',';
  259.                strcpy(p,flags[i].str);
  260.                p += H_FLAGLEN;
  261.             }
  262.         }
  263.         *p = '\0';
  264. }/*put_flags()*/
  265.  
  266.  
  267. /*---------------------------------------------------------------------------*/
  268. static dword get_flags (char *buf, struct _h_flags flags[])
  269. {
  270.         register dword  val;
  271.         register char  *p;
  272.         register int    i;
  273.  
  274.         val = 0x0L;
  275.         for (p = strtok(buf,","); p; p = strtok(NULL,",")) {
  276.             for (i = 0; flags[i].val; i++) {
  277.                 if (!strcmp(p,flags[i].str)) {
  278.                    val |= flags[i].val;
  279.                    break;
  280.                 }
  281.             }
  282.         }
  283.  
  284.         return (val);
  285. }/*get_flags()*/
  286.  
  287.  
  288. /*---------------------------------------------------------------------------*/
  289. static word crc16block (register byte *buf, register word len)
  290. {
  291.         register word crc;
  292.  
  293.         for (crc = 0xffff; len > 0; len--)
  294.             crc = h_updcrc16(crc,*buf++);
  295.         return (crc);
  296. }/*crc16block()*/
  297.  
  298.  
  299. /*---------------------------------------------------------------------------*/
  300. static dword crc32block (register byte *buf, register word len)
  301. {
  302.         register dword crc;
  303.  
  304.         for (crc = 0xffffffffL; len > 0; len--)
  305.             crc = h_updcrc32(crc,*buf++);
  306.         return (crc);
  307. }/*crc32block()*/
  308.  
  309.  
  310. /*---------------------------------------------------------------------------*/
  311. static byte *put_binbyte (register byte *p, register byte c)
  312. {
  313.         register byte n;
  314.  
  315.         n = c;
  316.         if (txoptions & HOPT_HIGHCTL)
  317.            n &= 0x7f;
  318.  
  319.         if (n == H_DLE ||
  320.             ((txoptions & HOPT_XONXOFF) && (n == XON || n == XOFF)) ||
  321.             ((txoptions & HOPT_TELENET) && n == '\r' && txlastc == '@') ||
  322.             ((txoptions & HOPT_CTLCHRS) && (n < 32 || n == 127))) {
  323.            *p++ = H_DLE;
  324.            c ^= 0x40;
  325.         }
  326.  
  327.         *p++ = c;
  328.         txlastc = n;
  329.  
  330.         return (p);
  331. }/*put_binbyte()*/
  332.  
  333.  
  334. /*---------------------------------------------------------------------------*/
  335. static void txpkt (register word len, int type)
  336. {
  337.         register byte *in, *out;
  338.         register word  c, n;
  339.         boolean crc32 = false;
  340.         byte    format;
  341.         static char hexdigit[] = "0123456789abcdef";
  342.  
  343.         txbufin[len++] = type;
  344.  
  345.         switch (type) {
  346.                case HPKT_START:
  347.                case HPKT_INIT:
  348.                case HPKT_INITACK:
  349.                case HPKT_END:
  350.                case HPKT_IDLE:
  351.                     format = HCHR_HEXPKT;
  352.                     break;
  353.  
  354.                default:
  355.                     /* COULD do smart format selection depending on data and options! */
  356.                     if (txoptions & HOPT_HIGHBIT) {
  357.                        if ((txoptions & HOPT_CTLCHRS) && (txoptions & HOPT_CANUUE))
  358.                           format = HCHR_UUEPKT;
  359.                        else if (txoptions & HOPT_CANASC)
  360.                           format = HCHR_ASCPKT;
  361.                        else
  362.                           format = HCHR_HEXPKT;
  363.                     }
  364.                     else
  365.                        format = HCHR_BINPKT;
  366.                     break;
  367.         }
  368.  
  369.         if (format != HCHR_HEXPKT && (txoptions & HOPT_CRC32))
  370.            crc32 = true;
  371.  
  372. #if H_DEBUG
  373. if (loglevel==0) {
  374.    char *s1, *s2, *s3, *s4;
  375.  
  376.    message(0," -> PKT (format='%c'  type='%c'  crc=%d  len=%d)",
  377.              format, type, crc32 ? 32 : 16, len - 1);
  378.  
  379.    switch (type) {
  380.           case HPKT_START:    message(0,"    <autostr>START");
  381.                               break;
  382.           case HPKT_INIT:     s1 = ((char *) txbufin) + ((int) strlen((char *) txbufin)) + 1;
  383.                               s2 = s1 + ((int) strlen(s1)) + 1;
  384.                               s3 = s2 + ((int) strlen(s2)) + 1;
  385.                               s4 = s3 + ((int) strlen(s3)) + 1;
  386.                               message(0,"    INIT (appinfo='%s'  can='%s'  want='%s'  options='%s'  pktprefix='%s')",
  387.                                       (char *) txbufin, s1, s2, s3, s4);
  388.                               break;
  389.           case HPKT_INITACK:  message(0,"    INITACK");
  390.                               break;
  391.           case HPKT_FINFO:    message(0,"    FINFO (%s)",txbufin);
  392.                               break;
  393.           case HPKT_FINFOACK: if (rxfd >= 0) {
  394.                                  if (rxpos > 0L) s1 = "RES";
  395.                                  else            s1 = "BOF";
  396.                               }
  397.                               else if (rxpos == -1L) s1 = "HAVE";
  398.                               else if (rxpos == -2L) s1 = "SKIP";
  399.                               else                   s1 = "EOB";
  400.                               message(0,"    FINFOACK (pos=%ld %s  rxstate=%d  rxfd=%d)",
  401.                                       rxpos,s1,rxstate,rxfd);
  402.                               break;
  403.           case HPKT_DATA:     message(0,"    DATA (ofs=%ld  len=%d)",
  404.                                       intell(h_long1(txbufin)), len - 5);
  405.                               break;
  406.           case HPKT_DATAACK:  message(0,"    DATAACK (ofs=%ld)",
  407.                                       intell(h_long1(txbufin)));
  408.                               break;
  409.           case HPKT_RPOS:     message(0,"    RPOS (pos=%ld%s  blklen=%ld  syncid=%ld)",
  410.                                       rxpos, rxpos < 0L ? " SKIP" : "",
  411.                                       intell(h_long2(txbufin)), rxsyncid);
  412.                               break;
  413.           case HPKT_EOF:      message(0,"    EOF (ofs=%ld%s)",
  414.                                       txpos, txpos < 0L ? " SKIP" : "");
  415.                               break;
  416.           case HPKT_EOFACK:   message(0,"    EOFACK");
  417.                               break;
  418.           case HPKT_IDLE:     message(0,"    IDLE");
  419.                               break;
  420.           case HPKT_END:      message(0,"    END");
  421.                               break;
  422.           case HPKT_DEVDATA:  message(0,"    DEVDATA (id=%ld  dev='%s'  len=%u)",
  423.                                       devtxid, devtxdev, devtxlen);
  424.                               break;
  425.           case HPKT_DEVDACK:  message(0,"    DEVDACK (id=%ld)",
  426.                                       intell(h_long1(rxbuf)));
  427.                               break;
  428.           default:            /* This couldn't possibly happen! ;-) */
  429.                               break;
  430.    }
  431. }
  432. #endif
  433.  
  434.         if (crc32) {
  435.            dword crc = ~crc32block(txbufin,len);
  436.  
  437.            txbufin[len++] = crc;
  438.            txbufin[len++] = crc >> 8;
  439.            txbufin[len++] = crc >> 16;
  440.            txbufin[len++] = crc >> 24;
  441.         }
  442.         else {
  443.            word crc = ~crc16block(txbufin,len);
  444.  
  445.            txbufin[len++] = crc;
  446.            txbufin[len++] = crc >> 8;
  447.         }
  448.  
  449.         in = txbufin;
  450.         out = txbuf;
  451.         txlastc = 0;
  452.         *out++ = H_DLE;
  453.         *out++ = format;
  454.  
  455.         switch (format) {
  456.                case HCHR_HEXPKT:
  457.                     for (; len > 0; len--, in++) {
  458.                         if (*in & 0x80) {
  459.                            *out++ = '\\';
  460.                            *out++ = hexdigit[((*in) >> 4) & 0x0f];
  461.                            *out++ = hexdigit[(*in) & 0x0f];
  462.                         }
  463.                         else if (*in < 32 || *in == 127) {
  464.                            *out++ = H_DLE;
  465.                            *out++ = (*in) ^ 0x40;
  466.                         }
  467.                         else if (*in == '\\') {
  468.                            *out++ = '\\';
  469.                            *out++ = '\\';
  470.                         }
  471.                         else
  472.                            *out++ = *in;
  473.                     }
  474.                     break;
  475.  
  476.                case HCHR_BINPKT:
  477.                     for (; len > 0; len--)
  478.                         out = put_binbyte(out,*in++);
  479.                     break;
  480.  
  481.                case HCHR_ASCPKT:
  482.                     for (n = c = 0; len > 0; len--) {
  483.                         c |= ((*in++) << n);
  484.                         out = put_binbyte(out,c & 0x7f);
  485.                         c >>= 7;
  486.                         if (++n >= 7) {
  487.                            out = put_binbyte(out,c & 0x7f);
  488.                            n = c = 0;
  489.                         }
  490.                     }
  491.                     if (n > 0)
  492.                        out = put_binbyte(out,c & 0x7f);
  493.                     break;
  494.  
  495.                case HCHR_UUEPKT:
  496.                     for ( ; len >= 3; in += 3, len -= 3) {
  497.                         *out++ = h_uuenc(in[0] >> 2);
  498.                         *out++ = h_uuenc(((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f));
  499.                         *out++ = h_uuenc(((in[1] << 2) & 0x3c) | ((in[2] >> 6) & 0x03));
  500.                         *out++ = h_uuenc(in[2] & 0x3f);
  501.                     }
  502.                     if (len > 0) {
  503.                        *out++ = h_uuenc(in[0] >> 2);
  504.                        *out++ = h_uuenc(((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f));
  505.                        if (len == 2)
  506.                           *out++ = h_uuenc((in[1] << 2) & 0x3c);
  507.                     }
  508.                     break;
  509.         }
  510.  
  511.         *out++ = H_DLE;
  512.         *out++ = HCHR_PKTEND;
  513.  
  514.         if (type != HPKT_DATA && format != HCHR_BINPKT) {
  515.            *out++ = '\r';
  516.            *out++ = '\n';
  517.         }
  518.  
  519.         for (in = (byte *) txpktprefix; *in; in++) {
  520.             switch (*in) {
  521.                    case 221: /* transmit break signal for one second */
  522.                              break;
  523.                    case 222: { h_timer t = h_timer_set(2);
  524.                                while (!h_timer_expired(t))
  525.                                      sys_idle();
  526.                              }
  527.                              break;
  528.                    case 223: com_putbyte(0);
  529.                              break;
  530.                    default:  com_putbyte(*in);
  531.                              break;
  532.             }
  533.         }
  534.  
  535.         com_putblock(txbuf,(word) (out - txbuf));
  536. }/*txpkt()*/
  537.  
  538.  
  539. /*---------------------------------------------------------------------------*/
  540. static int rxpkt (void)
  541. {
  542.         register byte *p, *q;
  543.         register int   c, n, i;
  544.  
  545.         if (keyabort())
  546.            return (H_SYSABORT);
  547.         if (!carrier())
  548.            return (H_CARRIER);
  549.  
  550.         p = rxbufptr;
  551.  
  552.         while ((c = com_getbyte()) >= 0) {
  553.               if (rxoptions & HOPT_HIGHBIT)
  554.                  c &= 0x7f;
  555.  
  556.               n = c;
  557.               if (rxoptions & HOPT_HIGHCTL)
  558.                  n &= 0x7f;
  559.               if (n != H_DLE &&
  560.                   (((rxoptions & HOPT_XONXOFF) && (n == XON || n == XOFF)) ||
  561.                    ((rxoptions & HOPT_CTLCHRS) && (n < 32 || n == 127))))
  562.                  continue;
  563.  
  564.               if (rxdle || c == H_DLE) {
  565.                  switch (c) {
  566.                         case H_DLE:
  567.                              if (++rxdle >= 5)
  568.                                 return (H_CANCEL);
  569.                              break;
  570.  
  571.                         case HCHR_PKTEND:
  572.                              rxbufptr = p;
  573.  
  574.                              switch (rxpktformat) {
  575.                                     case HCHR_BINPKT:
  576.                                          q = rxbufptr;
  577.                                          break;
  578.  
  579.                                     case HCHR_HEXPKT:
  580.                                          for (p = q = rxbuf; p < rxbufptr; p++) {
  581.                                              if (*p == '\\' && *++p != '\\') {
  582.                                                 i = *p;
  583.                                                 n = *++p;
  584.                                                 if ((i -= '0') > 9) i -= ('a' - ':');
  585.                                                 if ((n -= '0') > 9) n -= ('a' - ':');
  586.                                                 if ((i & ~0x0f) || (n & ~0x0f)) {
  587.                                                    i = H_NOPKT;
  588.                                                    break;
  589.                                                 }
  590.                                                 *q++ = (i << 4) | n;
  591.                                              }
  592.                                              else
  593.                                                 *q++ = *p;
  594.                                          }
  595.                                          if (p > rxbufptr)
  596.                                             c = H_NOPKT;
  597.                                          break;
  598.  
  599.                                     case HCHR_ASCPKT:
  600.                                          n = i = 0;
  601.                                          for (p = q = rxbuf; p < rxbufptr; p++) {
  602.                                              i |= ((*p & 0x7f) << n);
  603.                                              if ((n += 7) >= 8) {
  604.                                                 *q++ = (byte) (i & 0xff);
  605.                                                 i >>= 8;
  606.                                                 n -= 8;
  607.                                              }
  608.                                          }
  609.                                          break;
  610.  
  611.                                     case HCHR_UUEPKT:
  612.                                          n = (int) (rxbufptr - rxbuf);
  613.                                          for (p = q = rxbuf; n >= 4; n -= 4, p += 4) {
  614.                                              if (p[0] <= ' ' || p[0] >= 'a' ||
  615.                                                  p[1] <= ' ' || p[1] >= 'a' ||
  616.                                                  p[2] <= ' ' || p[2] >= 'a') {
  617.                                                 c = H_NOPKT;
  618.                                                 break;
  619.                                              }
  620.                                              *q++ = (byte) ((h_uudec(p[0]) << 2) | (h_uudec(p[1]) >> 4));
  621.                                              *q++ = (byte) ((h_uudec(p[1]) << 4) | (h_uudec(p[2]) >> 2));
  622.                                              *q++ = (byte) ((h_uudec(p[2]) << 6) | h_uudec(p[3]));
  623.                                          }
  624.                                          if (n >= 2) {
  625.                                             if (p[0] <= ' ' || p[0] >= 'a') {
  626.                                                c = H_NOPKT;
  627.                                                break;
  628.                                             }
  629.                                             *q++ = (byte) ((h_uudec(p[0]) << 2) | (h_uudec(p[1]) >> 4));
  630.                                             if (n == 3) {
  631.                                                if (p[0] <= ' ' || p[0] >= 'a') {
  632.                                                   c = H_NOPKT;
  633.                                                   break;
  634.                                                }
  635.                                                *q++ = (byte) ((h_uudec(p[1]) << 4) | (h_uudec(p[2]) >> 2));
  636.                                             }
  637.                                          }
  638.                                          break;
  639.  
  640.                                     default:   /* This'd mean internal fluke */
  641. #if H_DEBUG
  642. if (loglevel==0) {
  643.    message(0," <- <PKTEND> (pktformat='%c' dec=%d hex=%02x) ??",
  644.              rxpktformat, rxpktformat, rxpktformat);
  645. }
  646. #endif
  647.                                          c = H_NOPKT;
  648.                                          break;
  649.                              }
  650.  
  651.                              rxbufptr = NULL;
  652.  
  653.                              if (c == H_NOPKT)
  654.                                 break;
  655.  
  656.                              rxpktlen = (word) (q - rxbuf);
  657.                              if (rxpktformat != HCHR_HEXPKT && (rxoptions & HOPT_CRC32)) {
  658.                                 if (rxpktlen < 5) {
  659.                                    c = H_NOPKT;
  660.                                    break;
  661.                                 }
  662.                                 n = h_crc32test(crc32block(rxbuf,rxpktlen));
  663.                                 rxpktlen -= (int) sizeof (long);  /* remove CRC-32 */
  664.                              }
  665.                              else {
  666.                                 if (rxpktlen < 3) {
  667.                                    c = H_NOPKT;
  668.                                    break;
  669.                                 }
  670.                                 n = h_crc16test(crc16block(rxbuf,rxpktlen));
  671.                                 rxpktlen -= (int) sizeof (word);  /* remove CRC-16 */
  672.                              }
  673.  
  674.                              rxpktlen--;                     /* remove type  */
  675.  
  676.                              if (n) {
  677. #if H_DEBUG
  678. if (loglevel==0) {
  679.    char *s1, *s2, *s3, *s4;
  680.  
  681.    message(0," <- PKT (format='%c'  type='%c'  len=%d)",
  682.            rxpktformat, (int) rxbuf[rxpktlen], rxpktlen);
  683.  
  684.    switch (rxbuf[rxpktlen]) {
  685.           case HPKT_START:    message(0,"    START");
  686.                               break;
  687.           case HPKT_INIT:     s1 = ((char *) rxbuf) + ((int) strlen((char *) rxbuf)) + 1;
  688.                               s2 = s1 + ((int) strlen(s1)) + 1;
  689.                               s3 = s2 + ((int) strlen(s2)) + 1;
  690.                               s4 = s3 + ((int) strlen(s3)) + 1;
  691.                               message(0,"    INIT (appinfo='%s'  can='%s'  want='%s'  options='%s'  pktprefix='%s')",
  692.                                       (char *) rxbuf, s1, s2, s3, s4);
  693.                               break;
  694.           case HPKT_INITACK:  message(0,"    INITACK");
  695.                               break;
  696.           case HPKT_FINFO:    message(0,"    FINFO ('%s'  rxstate=%d)",rxbuf,rxstate);
  697.                               break;
  698.           case HPKT_FINFOACK: message(0,"    FINFOACK (pos=%ld  txstate=%d  txfd=%d)",
  699.                                       intell(h_long1(rxbuf)), txstate, txfd);
  700.                               break;
  701.           case HPKT_DATA:     message(0,"    DATA (rxstate=%d  pos=%ld  len=%u)",
  702.                                       rxstate, intell(h_long1(rxbuf)),
  703.                                       (word) (rxpktlen - ((int) sizeof (long))));
  704.                               break;
  705.           case HPKT_DATAACK:  message(0,"    DATAACK (rxstate=%d  pos=%ld)",
  706.                                       rxstate, intell(h_long1(rxbuf)));
  707.                               break;
  708.           case HPKT_RPOS:     message(0,"    RPOS (pos=%ld%s  blklen=%u->%ld  syncid=%ld%s  txstate=%d  txfd=%d)",
  709.                                       intell(h_long1(rxbuf)),
  710.                                       intell(h_long1(rxbuf)) < 0L ? " SKIP" : "",
  711.                                       txblklen, intell(h_long2(rxbuf)),
  712.                                       intell(h_long3(rxbuf)),
  713.                                       intell(h_long3(rxbuf)) == rxsyncid ? " DUP" : "",
  714.                                       txstate, txfd);
  715.                               break;
  716.           case HPKT_EOF:      message(0,"    EOF (rxstate=%d  pos=%ld%s)",
  717.                                       rxstate, intell(h_long1(rxbuf)),
  718.                                       intell(h_long1(rxbuf)) < 0L ? " SKIP" : "");
  719.                               break;
  720.           case HPKT_EOFACK:   message(0,"    EOFACK (txstate=%d)", txstate);
  721.                               break;
  722.           case HPKT_IDLE:     message(0,"    IDLE");
  723.                               break;
  724.           case HPKT_END:      message(0,"    END");
  725.                               break;
  726.           case HPKT_DEVDATA:  s1 = ((char *) rxbuf) + ((int) sizeof (long));
  727.                               message(0,"    DEVDATA (id=%ld  dev=%s  len=%u",
  728.                                       intell(h_long1(rxbuf)), s1,
  729.                                       rxpktlen - (((int) sizeof (long)) + ((int) strlen(s1)) + 1));
  730.                               break;
  731.           case HPKT_DEVDACK:  message(0,"    DEVDACK (devtxstate=%d  id=%ld)",
  732.                                       devtxstate, intell(h_long1(rxbuf)));
  733.                               break;
  734.           default:            message(0,"    Unkown pkttype %d (txstate=%d  rxstate=%d)",
  735.                                       (int) rxbuf[rxpktlen], txstate, rxstate);
  736.                               break;
  737.    }
  738. }
  739. #endif
  740.                                 return ((int) rxbuf[rxpktlen]);
  741.                              }/*goodpkt*/
  742.  
  743. #if H_DEBUG
  744. if (loglevel==0)
  745.    message(0," Bad CRC (format='%c'  type='%c'  len=%d)",
  746.              rxpktformat, (int) rxbuf[rxpktlen], rxpktlen);
  747. #endif
  748.                              break;
  749.  
  750.                         case HCHR_BINPKT: 
  751.                         case HCHR_HEXPKT: 
  752.                         case HCHR_ASCPKT: 
  753.                         case HCHR_UUEPKT:
  754. #if H_DEBUG
  755. if (loglevel==0)
  756.    message(0," <- <PKTSTART> (pktformat='%c')",c);
  757. #endif
  758.                              rxpktformat = c;
  759.                              p = rxbufptr = rxbuf;
  760.                              rxdle = 0;
  761.                              break;
  762.  
  763.                         default:
  764.                              if (p) {
  765.                                 if (p < rxbufmax)
  766.                                    *p++ = (byte) (c ^ 0x40);
  767.                                 else {
  768. #if H_DEBUG
  769. if (loglevel==0)
  770.    message(0," <- Pkt too long - discarded");
  771. #endif
  772.                                    p = NULL;
  773.                                 }
  774.                              }
  775.                              rxdle = 0;
  776.                              break;
  777.                  }
  778.               }
  779.               else if (p) {
  780.                  if (p < rxbufmax)
  781.                     *p++ = (byte) c;
  782.                  else {
  783. #if H_DEBUG
  784. if (loglevel==0)
  785.    message(0," <- Pkt too long - discarded");
  786. #endif
  787.                     p = NULL;
  788.                  }
  789.               }
  790.         }
  791.  
  792.         rxbufptr = p;
  793.  
  794.         if (h_timer_running(braindead) && h_timer_expired(braindead)) {
  795. #if H_DEBUG
  796. if (loglevel==0)
  797.    message(0," <- BrainDead (timer=%08lx  time=%08lx)",
  798.            braindead,time(NULL));
  799. #endif
  800.            return (H_BRAINTIME);
  801.         }
  802.         if (h_timer_running(txtimer) && h_timer_expired(txtimer)) {
  803. #if H_DEBUG
  804. if (loglevel==0)
  805.    message(0," <- TxTimer (timer=%08lx  time=%08lx)",
  806.            txtimer,time(NULL));
  807. #endif
  808.            return (H_TXTIME);
  809.         }
  810.         if (h_timer_running(devtxtimer) && h_timer_expired(devtxtimer)) {
  811. #if H_DEBUG
  812. if (loglevel==0)
  813.    message(0," <- DevTxTimer (timer=%08lx  time=%08lx)",
  814.            devtxtimer,time(NULL));
  815. #endif
  816.            return (H_DEVTXTIME);
  817.         }
  818.  
  819.         sys_idle();
  820.         return (H_NOPKT);
  821. }/*rxpkt()*/
  822.  
  823.  
  824. /*---------------------------------------------------------------------------*/
  825. static void hydra_status (boolean xmit)
  826. {
  827.         long pos    = xmit ? txpos    : rxpos,
  828.              fsize  = xmit ? txfsize  : rxfsize;
  829.  
  830.         hydra_gotoxy(46,xmit ? 1 : 2);
  831.         if (pos >= fsize)
  832.            hydra_printf("%ld/%ld (EOF)",pos,fsize);
  833.         else {
  834.            int left = (int) ((((fsize - pos) / 128L) * 1340L) / cur_speed);
  835.            char *p = "";
  836.  
  837.            if (xmit) {
  838.               if      (txstate == HTX_DATAACK) p = "ACK ";
  839.               else if (txstate == HTX_XWAIT)   p = "WAIT ";
  840.            }
  841.            hydra_printf("%ld/%ld (%s%d:%02d min left)",
  842.                         pos, fsize, p, left / 60, left % 60);
  843.         }
  844.         hydra_clreol();
  845. }/*hydra_status()*/
  846.  
  847.  
  848. /*---------------------------------------------------------------------------*/
  849. static void hydra_pct (boolean xmit)
  850. {
  851.         long offset = xmit ? txoffset : rxoffset,
  852.              fsize  = xmit ? txfsize  : rxfsize,
  853.              start  = xmit ? txstart  : rxstart,
  854.              elapsed, bytes, cps, pct;
  855.  
  856.         elapsed = time(NULL) - start;
  857.         bytes = fsize - offset;
  858.         if (bytes < 1024L || elapsed == 0L)
  859.            return;
  860.         cps = bytes / elapsed;
  861.         pct = (cps * 1000L) / ((long) cur_speed);
  862.         message(2,"+%s-H CPS: %ld (%ld bytes), %d:%02d min.  Eff: %ld%%",
  863.                 xmit ? "Sent" : "Rcvd", cps, bytes,
  864.                 (int) (elapsed / 60), (int) (elapsed % 60), pct);
  865. }/*hydra_pct()*/
  866.  
  867.  
  868. /*---------------------------------------------------------------------------*/
  869. void hydra_badxfer (void)
  870. {
  871.         if (rxfd >= 0) {
  872.            dos_close(rxfd);
  873.            rxfd = -1;
  874.            if (xfer_bad())
  875.               message(1,"+HRECV: Bad xfer recovery-info saved");
  876.            else
  877.               message(0,"-HRECV: Bad xfer - file deleted");
  878.         }
  879. }/*hydra_badxfer()*/
  880.  
  881.  
  882. /*---------------------------------------------------------------------------*/
  883. void hydra_init (dword want_options)
  884. {
  885.         register word i, j;
  886.         word  crc16;
  887.         dword crc32;
  888.  
  889.         txbuf    = (byte *)  malloc(H_BUFLEN);
  890.         rxbuf    = (byte *)  malloc(H_BUFLEN);
  891.         crc16tab = (word *)  malloc(256 * ((int) sizeof (word)));
  892.         crc32tab = (dword *) malloc(256 * ((int) sizeof (dword)));
  893.         if (!txbuf || !rxbuf || !crc16tab || !crc32tab) {
  894.            message(6,"!HYDRA: Can't allocate buffers!");
  895.            endprog(2);
  896.         }
  897.         txbufin  = txbuf + ((H_MAXBLKLEN + H_OVERHEAD + 5) * 2);
  898.         rxbufmax = rxbuf + H_MAXPKTLEN;
  899.  
  900.         for (i = 0; i < 256; i++) {
  901.             crc16 = i;
  902.             crc32 = i;
  903.             for (j = 8; j > 0; j--) {
  904.                 if (crc16 & 1) crc16 = (crc16 >> 1) ^ h_crc16poly;
  905.                 else           crc16 >>= 1;
  906.                 if (crc32 & 1) crc32 = (crc32 >> 1) ^ h_crc32poly;
  907.                 else           crc32 >>= 1;
  908.             }
  909.             crc16tab[i] = crc16;
  910.             crc32tab[i] = crc32;
  911.         }
  912.  
  913.         batchesdone = 0;
  914.  
  915.         originator = nooriginator ? false : true;
  916.  
  917.         if (originator)
  918.            hdxlink = false;
  919.         else if (hdxsession)
  920.            hdxlink = true;
  921.  
  922.         options = (want_options & HCAN_OPTIONS) & ~HUNN_OPTIONS;
  923.  
  924.         timeout = (word) (40960L / cur_speed);
  925.         if      (timeout < H_MINTIMER) timeout = H_MINTIMER;
  926.         else if (timeout > H_MAXTIMER) timeout = H_MAXTIMER;
  927.  
  928.         txmaxblklen = (cur_speed / 300) * 128;
  929.         if      (txmaxblklen < 256)         txmaxblklen = 256;
  930.         else if (txmaxblklen > H_MAXBLKLEN) txmaxblklen = H_MAXBLKLEN;
  931.  
  932.         rxblklen = txblklen = (cur_speed < 2400U) ? 256 : 512;
  933.  
  934.         txgoodbytes  = 0;
  935.         txgoodneeded = 1024;
  936.  
  937.         txstate = HTX_DONE;
  938.  
  939.         if (!mailer)
  940.            message(-1,"+HYDRA session (%s-directional mode)",
  941.                       hdxlink ? "Uni" : "Bi");
  942.  
  943. #if WIN_AGL
  944. { byte ev   = win_maxver - 25,          /* extra lines available vertically? */
  945.        elog = ev / 3,                   /* 1/3 of extra lines for log_win    */
  946.        eloc = ev / 3,                   /* 1/3 of extra lines for local_win  */
  947.        erem = ev - (elog + eloc);       /* the rest is extra for remote_win  */
  948.  
  949.         log_win = win_create(1, 1, win_maxhor, 6 + elog,
  950.                               CUR_NONE, CON_RAW | CON_WRAP | CON_SCROLL,
  951.                               CHR_NORMAL, KEY_RAW);
  952.         win_setattrib(log_win,CHR_INVERSE);
  953.         win_clreol(log_win);
  954.         win_printf(log_win," %s v%s - COPYRIGHT (C) 1991-1993 A.G.Lentz, LENTZ SOFTWARE-DEVELOPMENT",PRGNAME,VERSION);
  955.         win_setattrib(log_win,CHR_NORMAL);
  956.         win_setrange(log_win,1,2,win_maxhor,6 + elog);
  957.  
  958.         file_win = win_create(1, 7 + elog, win_maxhor, 9 + elog,
  959.                               CUR_NONE, CON_RAW, CHR_NORMAL, KEY_RAW);
  960.         win_setattrib(file_win,CHR_INVERSE);
  961.         win_clreol(file_win);
  962.         win_printf(file_win," Port=%u   ComSpeed=%u   LineSpeed=%u",
  963.                             port + 1, com_speed, cur_speed);
  964.         win_xyputs(file_win,48,1,"Press ESC to abort Hydra session");
  965.         win_setattrib(file_win,CHR_F_YELLOW);
  966.         win_xyputs(file_win,2,2,"Sending  :");
  967.         win_xyputs(file_win,2,3,"Receiving:");
  968.         win_setattrib(file_win,CHR_NORMAL);
  969.         win_setrange(file_win,1,2,win_maxhor,3);
  970.  
  971.         remote_win = win_create(1, 10 + elog, win_maxhor, 17 + elog + erem,
  972.                                 CUR_NONE, CON_COOKED | CON_WRAP | CON_SCROLL,
  973.                                 CHR_NORMAL, KEY_RAW);
  974.         win_setattrib(remote_win,CHR_INVERSE);
  975.         win_fill(remote_win,177);
  976.         win_puts(remote_win," Remote ");
  977.         win_setattrib(remote_win,CHR_NORMAL);
  978.         win_setrange(remote_win,1,2,win_maxhor,8 + erem);
  979.         win_cls(remote_win);
  980.  
  981.         local_win = win_create(1, 18 + elog + erem, win_maxhor, win_maxver,
  982.                                CUR_NORMAL, CON_COOKED | CON_WRAP | CON_SCROLL,
  983.                                CHR_NORMAL, KEY_RAW);
  984.         win_setattrib(local_win,CHR_INVERSE);
  985.         win_fill(local_win,177);
  986.         win_puts(local_win," Local (Press Alt-C to start/end chat mode) ");
  987.         win_setattrib(local_win,CHR_NORMAL);
  988.         win_setrange(local_win,1,2,win_maxhor,8 + eloc);
  989.         win_cls(local_win);
  990.  
  991.         log_first = false;
  992.  
  993.         win_settop(log_win);
  994.         win_settop(file_win);
  995.         win_settop(remote_win);
  996.         win_settop(local_win);
  997. }
  998. #else
  999. { struct text_info ti;
  1000.  
  1001.         term_x = wherex();
  1002.         term_y = wherey();
  1003.         gettextinfo(&ti);
  1004.         window(1,1,ti.screenwidth,ti.screenheight);
  1005.         term_scr = malloc(ti.screenwidth * ti.screenheight * sizeof (word));
  1006.         gettext(1,1,ti.screenwidth,ti.screenheight,term_scr);
  1007.  
  1008.         clrscr();
  1009.         textbackground(LIGHTGRAY);
  1010.         textcolor(BLACK);
  1011.  
  1012.         gotoxy(1,1);
  1013.         clreol();
  1014.         cprintf(" %s v%s - COPYRIGHT (C) 1991-1993 A.G.Lentz, LENTZ SOFTWARE-DEVELOPMENT",PRGNAME,VERSION);
  1015.  
  1016.         gotoxy(1,7);
  1017.         clreol();
  1018.         cprintf(" Port=%u   ComSpeed=%u   LineSpeed=%u",
  1019.                 port + 1, com_speed, cur_speed);
  1020.         gotoxy(48,7);
  1021.         cprintf("Press ESC to abort Hydra session");
  1022.  
  1023.         gotoxy(1,10);
  1024.         for (i = 0; i < ti.screenwidth; i++) putch(177);
  1025.         gotoxy(1,10);
  1026.         cprintf(" Remote ");
  1027.  
  1028.         gotoxy(1,18);
  1029.         for (i = 0; i < ti.screenwidth; i++) putch(177);
  1030.         gotoxy(1,18);
  1031.         cprintf(" Local (Press Alt-C to start/end chat mode) ");
  1032.  
  1033.         textbackground(BLACK);
  1034.         textcolor(YELLOW);
  1035.         gotoxy(2,8);
  1036.         cprintf("Sending  :");
  1037.         gotoxy(2,9);
  1038.         cprintf("Receiving:");
  1039.  
  1040.         window(1,19,80,25);
  1041.         textcolor(LIGHTGRAY);
  1042.         file_x = file_y = remote_x = remote_y = local_x = local_y = 1;
  1043.         log_y = 0;
  1044. }
  1045. #endif
  1046.  
  1047.         hydra_devfunc("CON",rem_chat);
  1048.  
  1049.         chatfill  = 0;
  1050.         chattimer = -1L;
  1051.         lasttimer = 0L;
  1052.  
  1053.         message(2,"+HYDRA session (%s-directional mode)",
  1054.                   hdxlink ? "Uni" : "Bi");
  1055. }/*hydra_init()*/
  1056.  
  1057.  
  1058. /*---------------------------------------------------------------------------*/
  1059. void hydra_deinit (void)
  1060. {
  1061. #if WIN_AGL
  1062.         win_settop(0);
  1063.         win_close(file_win);
  1064.         win_close(log_win);
  1065.         win_close(remote_win);
  1066.         win_close(local_win);
  1067.         file_win = 0;
  1068. #else
  1069. { struct text_info ti;
  1070.  
  1071.         gettextinfo(&ti);
  1072.         window(1,1,ti.screenwidth,ti.screenheight);
  1073.         puttext(1,1,ti.screenwidth,ti.screenheight,term_scr);
  1074.         gotoxy(term_x,term_y);
  1075.         free(term_scr);
  1076.         file_x = 0;
  1077. }
  1078. #endif
  1079.  
  1080.         free(txbuf);
  1081.         free(rxbuf);
  1082.         free(crc16tab);
  1083.         free(crc32tab);
  1084. }/*hydra_deinit()*/
  1085.  
  1086.  
  1087. /*---------------------------------------------------------------------------*/
  1088. int hydra (char *txpathname, char *txalias)
  1089. {
  1090.         int   res;
  1091.         int   pkttype;
  1092.         char *p, *q;
  1093.         int   i;
  1094.         struct stat f;
  1095.  
  1096.         /*-------------------------------------------------------------------*/
  1097.         if (txstate == HTX_DONE) {
  1098.            txstate        = HTX_START;
  1099.            hydra_gotoxy(13,1);
  1100.            hydra_printf("Init");
  1101.            txoptions      = HTXI_OPTIONS;
  1102.            txpktprefix[0] = '\0';
  1103.  
  1104.            rxstate   = HRX_INIT;
  1105.            hydra_gotoxy(13,2);
  1106.            hydra_printf("Init");
  1107.            rxoptions = HRXI_OPTIONS;
  1108.            rxfd      = -1;
  1109.            rxdle     = 0;
  1110.            rxbufptr  = NULL;
  1111.            rxtimer   = h_timer_reset();
  1112.  
  1113.            devtxid    = devrxid = 0L;
  1114.            devtxtimer = h_timer_reset();
  1115.            devtxstate = HTD_DONE;
  1116.  
  1117.            braindead = h_timer_set(H_BRAINDEAD);
  1118.         }
  1119.         else
  1120.            txstate = HTX_FINFO;
  1121.  
  1122.         txtimer   = h_timer_reset();
  1123.         txretries = 0;
  1124.  
  1125.         /*-------------------------------------------------------------------*/
  1126.         if (txpathname) {
  1127.            stat(txpathname,&f);
  1128.            txfsize = f.st_size;
  1129.            txftime = f.st_mtime;
  1130.  
  1131.            if ((txfd = dos_sopen(txpathname,0)) < 0) {
  1132.               message(3,"-HSEND: Unable to open %s",txpathname);
  1133.               return (XFER_SKIP);
  1134.            }
  1135.  
  1136.            strupr(txpathname);
  1137.            for (p=txpathname, q=txfname; *p; p++) {
  1138.                if (*q=*p, *p=='\\' || *p==':' || *p=='/')
  1139.                   q=txfname;
  1140.                else q++;
  1141.            }
  1142.            *q = '\0';
  1143.  
  1144.            if (txalias)
  1145.               strupr(txalias);
  1146.  
  1147.            txstart  = 0L;
  1148.            txsyncid = 0L;
  1149.         }
  1150.         else {
  1151.            txfd = -1;
  1152.            strcpy(txfname,"");
  1153.         }
  1154.  
  1155.         /*-------------------------------------------------------------------*/
  1156.         do {
  1157.            /*----------------------------------------------------------------*/
  1158.            switch (devtxstate) {
  1159.                   /*---------------------------------------------------------*/
  1160.                   case HTD_DATA:
  1161.                        if (txstate > HTX_RINIT) {
  1162.                           h_long1(txbufin) = intell(devtxid);
  1163.                           p = ((char *) txbufin) + ((int) sizeof(long));
  1164.                           strcpy(p,devtxdev);
  1165.                           p += H_FLAGLEN + 1;
  1166.                           memcpy(p,devtxbuf,devtxlen);
  1167.                           txpkt(((int) sizeof (long)) + H_FLAGLEN + 1 + devtxlen,HPKT_DEVDATA);
  1168.                           devtxtimer = h_timer_set(timeout);
  1169.                           devtxstate = HTD_DACK;
  1170.                        }
  1171.                        break;
  1172.  
  1173.                   /*---------------------------------------------------------*/
  1174.                   default:
  1175.                        break;
  1176.  
  1177.                   /*---------------------------------------------------------*/
  1178.            }
  1179.  
  1180.            /*----------------------------------------------------------------*/
  1181.            switch (txstate) {
  1182.                   /*---------------------------------------------------------*/
  1183.                   case HTX_START:
  1184.                        com_putblock((byte *) autostr,(int) strlen(autostr));
  1185.                        txpkt(0,HPKT_START);
  1186.                        txtimer = h_timer_set(H_START);
  1187.                        txstate = HTX_SWAIT;
  1188.                        break;
  1189.  
  1190.                   /*---------------------------------------------------------*/
  1191.                   case HTX_INIT:
  1192.                        p = (char *) txbufin;
  1193.                        sprintf(p,"%08lx%s,%s %s",
  1194.                                  H_REVSTAMP,PRGNAME,VERSION,HC_OS);
  1195.                        p += ((int) strlen(p)) + 1;/* our app info & HYDRA rev. */
  1196.                        put_flags(p,h_flags,HCAN_OPTIONS);    /* what we CAN  */
  1197.                        p += ((int) strlen(p)) + 1;
  1198.                        put_flags(p,h_flags,options);         /* what we WANT */
  1199.                        p += ((int) strlen(p)) + 1;
  1200.                        sprintf(p,"%08lx%08lx",               /* TxRx windows */
  1201.                                  hydra_txwindow,hydra_rxwindow);
  1202.                        p += ((int) strlen(p)) + 1;
  1203.                        strcpy(p,pktprefix);     /* pkt prefix string we want */
  1204.                        p += ((int) strlen(p)) + 1;
  1205.  
  1206.                        txoptions = HTXI_OPTIONS;
  1207.                        txpkt((word) (((byte *) p) - txbufin), HPKT_INIT);
  1208.                        txoptions = rxoptions;
  1209.                        txtimer = h_timer_set(timeout / 2);
  1210.                        txstate = HTX_INITACK;
  1211.                        break;
  1212.  
  1213.                   /*---------------------------------------------------------*/
  1214.                   case HTX_FINFO:
  1215.                        if (txfd >= 0) {
  1216.                           if (!txretries) {
  1217.                              hydra_gotoxy(13,1);
  1218.                              hydra_printf(txfname);
  1219.                              if (txalias) {
  1220.                                 hydra_gotoxy(25,1);
  1221.                                 hydra_printf("  ->  %s",txalias);
  1222.                              }
  1223.                              hydra_clreol();
  1224.                              message(2,"+HSEND: %s%s%s (%ldb), %d min.",
  1225.                                      txpathname, txalias ? " -> " : "", txalias ? txalias : "",
  1226.                                      txfsize, (int) (txfsize * 10L / cur_speed + 27L) / 54L);
  1227.  
  1228.                              strlwr(txfname);
  1229.                           }
  1230.                           sprintf((char *) txbufin,"%08lx%08lx%08lx%08lx%08lx%s",
  1231.                                   txftime, txfsize, 0L, 0L, 0L,
  1232.                                   txalias ? txalias : txfname);
  1233.                        }
  1234.                        else {
  1235.                           if (!txretries) {
  1236.                              hydra_gotoxy(13,1);
  1237.                              hydra_printf("End of batch");
  1238.                              hydra_clreol();
  1239.                              message(1,"+HSEND: End of batch");
  1240.                           }
  1241.                           strcpy((char *) txbufin,txfname);
  1242.                        }
  1243.                        txpkt(((int) strlen((char *) txbufin)) + 1,HPKT_FINFO);
  1244.                        txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1245.                        txstate = HTX_FINFOACK;
  1246.                        break;
  1247.  
  1248.                   /*---------------------------------------------------------*/
  1249.                   case HTX_XDATA:
  1250.                        if (com_outfull() > txmaxblklen)
  1251.                           break;
  1252.  
  1253.                        if (txpos < 0L)
  1254.                           i = -1;                                    /* Skip */
  1255.                        else {
  1256.                           h_long1(txbufin) = intell(txpos);
  1257.                           if ((i = dos_read(txfd,txbufin + ((int) sizeof (long)),txblklen)) < 0) {
  1258.                              message(6,"!HSEND: File read error");
  1259.                              dos_close(txfd);
  1260.                              txfd = -1;
  1261.                              txpos = -2L;                            /* Skip */
  1262.                           }
  1263.                        }
  1264.  
  1265.                        if (i > 0) {
  1266.                           txpos += i;
  1267.                           txpkt(((int) sizeof (long)) + i, HPKT_DATA);
  1268.  
  1269.                           if (txblklen < txmaxblklen &&
  1270.                               (txgoodbytes += i) >= txgoodneeded) {
  1271.                              txblklen <<= 1;
  1272.                              if (txblklen >= txmaxblklen) {
  1273.                                 txblklen = txmaxblklen;
  1274.                                 txgoodneeded = 0;
  1275.                              }
  1276.                              txgoodbytes = 0;
  1277.                           }
  1278.  
  1279.                           if (txwindow && (txpos >= (txlastack + txwindow))) {
  1280.                              txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1281.                              txstate = HTX_DATAACK;
  1282.                           }
  1283.  
  1284.                           if (!txstart)
  1285.                              txstart = time(NULL);
  1286.                           hydra_status(true);
  1287.                           break;
  1288.                        }
  1289.  
  1290.                        /* fallthrough to HTX_EOF */
  1291.  
  1292.                   /*---------------------------------------------------------*/
  1293.                   case HTX_EOF:
  1294.                        h_long1(txbufin) = intell(txpos);
  1295.                        txpkt((int) sizeof (long),HPKT_EOF);
  1296.                        txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1297.                        txstate = HTX_EOFACK;
  1298.                        break;
  1299.  
  1300.                   /*---------------------------------------------------------*/
  1301.                   case HTX_END:
  1302.                        txpkt(0,HPKT_END);
  1303.                        txpkt(0,HPKT_END);
  1304.                        txtimer = h_timer_set(timeout / 2);
  1305.                        txstate = HTX_ENDACK;
  1306.                        break;
  1307.  
  1308.                   /*---------------------------------------------------------*/
  1309.                   default:
  1310.                        break;
  1311.  
  1312.                   /*---------------------------------------------------------*/
  1313.            }
  1314.  
  1315.            /*----------------------------------------------------------------*/
  1316.            while (txstate && (pkttype = rxpkt()) != H_NOPKT) {
  1317.                  /*----------------------------------------------------------*/
  1318.                  switch (pkttype) {
  1319.                         /*---------------------------------------------------*/
  1320.                         case H_CARRIER:
  1321.                         case H_CANCEL:
  1322.                         case H_SYSABORT:
  1323.                         case H_BRAINTIME:
  1324.                              switch (pkttype) {
  1325.                                     case H_CARRIER:   p = "Carrier lost";          break;
  1326.                                     case H_CANCEL:    p = "Aborted by other side"; break;
  1327.                                     case H_SYSABORT:  p = "Aborted by operator";   break;
  1328.                                     case H_BRAINTIME: p = "Other end died";        break;
  1329.                              }
  1330.                              message(3,"-HYDRA: %s",p);
  1331.                              txstate = HTX_DONE;
  1332.                              res = XFER_ABORT;
  1333.                              break;
  1334.  
  1335.                         /*---------------------------------------------------*/
  1336.                         case H_TXTIME:
  1337.                              if (txstate == HTX_XWAIT || txstate == HTX_REND) {
  1338.                                 txpkt(0,HPKT_IDLE);
  1339.                                 txtimer = h_timer_set(H_IDLE);
  1340.                                 break;
  1341.                              }
  1342.  
  1343.                              if (++txretries > H_RETRIES) {
  1344.                                 message(3,"-HSEND: Too many errors");
  1345.                                 txstate = HTX_DONE;
  1346.                                 res = XFER_ABORT;
  1347.                                 break;
  1348.                              }
  1349.  
  1350.                              message(0,"-HSEND: Timeout - Retry %u",txretries);
  1351.  
  1352.                              txtimer = h_timer_reset();
  1353.  
  1354.                              switch (txstate) {
  1355.                                     case HTX_SWAIT:    txstate = HTX_START; break;
  1356.                                     case HTX_INITACK:  txstate = HTX_INIT;  break;
  1357.                                     case HTX_FINFOACK: txstate = HTX_FINFO; break;
  1358.                                     case HTX_DATAACK:  txstate = HTX_XDATA; break;
  1359.                                     case HTX_EOFACK:   txstate = HTX_EOF;   break;
  1360.                                     case HTX_ENDACK:   txstate = HTX_END;   break;
  1361.                              }
  1362.                              break;
  1363.  
  1364.                         /*---------------------------------------------------*/
  1365.                         case H_DEVTXTIME:
  1366.                              if (++devtxretries > H_RETRIES) {
  1367.                                 message(3,"-HDEVTX: Too many errors");
  1368.                                 txstate = HTX_DONE;
  1369.                                 res = XFER_ABORT;
  1370.                                 break;
  1371.                              }
  1372.  
  1373.                              message(0,"-HDEVTX: Timeout - Retry %u",devtxretries);
  1374.  
  1375.                              devtxtimer = h_timer_reset();
  1376.                              devtxstate = HTD_DATA;
  1377.                              break;
  1378.  
  1379.                         /*---------------------------------------------------*/
  1380.                         case HPKT_START:
  1381.                              if (txstate == HTX_START || txstate == HTX_SWAIT) {
  1382.                                 txtimer = h_timer_reset();
  1383.                                 txretries = 0;
  1384.                                 txstate = HTX_INIT;
  1385.                                 braindead = h_timer_set(H_BRAINDEAD);
  1386.                              }
  1387.                              break;
  1388.  
  1389.                         /*---------------------------------------------------*/
  1390.                         case HPKT_INIT:
  1391.                              if (rxstate == HRX_INIT) {
  1392.                                 p = (char *) rxbuf;
  1393.                                 p += ((int) strlen(p)) + 1;
  1394.                                 q = p + ((int) strlen(p)) + 1;
  1395.                                 rxoptions  = options | HUNN_OPTIONS;
  1396.                                 rxoptions |= get_flags(q,h_flags);
  1397.                                 rxoptions &= get_flags(p,h_flags);
  1398.                                 rxoptions &= HCAN_OPTIONS;
  1399.                                 if (rxoptions < (options & HNEC_OPTIONS)) {
  1400.                                    message(6,"!HYDRA: Incompatible on this link");
  1401.                                    txstate = HTX_DONE;
  1402.                                    res = XFER_ABORT;
  1403.                                    break;
  1404.                                 }
  1405.                                 p = q + ((int) strlen(q)) + 1;
  1406.                                 rxwindow = txwindow = 0L;
  1407.                                 sscanf(p,"%08lx%08lx", &rxwindow,&txwindow);
  1408.                                 if (rxwindow < 0L) rxwindow = 0L;
  1409.                                 if (hydra_rxwindow &&
  1410.                                     (!rxwindow || hydra_rxwindow < rxwindow))
  1411.                                    rxwindow = hydra_rxwindow;
  1412.                                 if (txwindow < 0L) txwindow = 0L;
  1413.                                 if (hydra_txwindow &&
  1414.                                     (!txwindow || hydra_txwindow < txwindow))
  1415.                                    txwindow = hydra_txwindow;
  1416.                                 p += ((int) strlen(p)) + 1;
  1417.                                 strncpy(txpktprefix,p,H_PKTPREFIX);
  1418.                                 txpktprefix[H_PKTPREFIX] = '\0';
  1419.  
  1420.                                 if (!batchesdone) {
  1421.                                    long revstamp;
  1422.  
  1423.                                    p = (char *) rxbuf;
  1424.                                    sscanf(p,"%08lx",&revstamp);
  1425.                                    message(0,"*HYDRA: Other's HydraRev=%s",
  1426.                                            h_revdate(revstamp));
  1427.                                    p += 8;
  1428.                                    if ((q = strchr(p,',')) != NULL) *q = ' ';
  1429.                                    if ((q = strchr(p,',')) != NULL) *q = '/';
  1430.                                    message(0,"*HYDRA: Other's App.Info '%s'",p);
  1431.                                    put_flags((char *) rxbuf,h_flags,rxoptions);
  1432.                                    message(1,"*HYDRA: Using link options '%s'",rxbuf);
  1433.                                    if (txwindow || rxwindow)
  1434.                                       message(0,"*HYDRA: Window tx=%ld rx=%ld",
  1435.                                                 txwindow,rxwindow);
  1436.                                 }
  1437.  
  1438.                                 chattimer = (rxoptions & HOPT_DEVICE) ? 0L : -2L;
  1439.  
  1440.                                 txoptions = rxoptions;
  1441.                                 rxstate = HRX_FINFO;
  1442.                              }
  1443.  
  1444.                              txpkt(0,HPKT_INITACK);
  1445.                              break;
  1446.  
  1447.                         /*---------------------------------------------------*/
  1448.                         case HPKT_INITACK:
  1449.                              if (txstate == HTX_INIT || txstate == HTX_INITACK) {
  1450.                                 braindead = h_timer_set(H_BRAINDEAD);
  1451.                                 txtimer = h_timer_reset();
  1452.                                 txretries = 0;
  1453.                                 txstate = HTX_RINIT;
  1454.                              }
  1455.                              break;
  1456.  
  1457.                         /*---------------------------------------------------*/
  1458.                         case HPKT_FINFO:
  1459.                              if (rxstate == HRX_FINFO) {
  1460.                                 braindead = h_timer_set(H_BRAINDEAD);
  1461.                                 if (!rxbuf[0]) {
  1462.                                    hydra_gotoxy(13,2);
  1463.                                    hydra_printf("End of batch");
  1464.                                    hydra_clreol();
  1465.                                    message(1,"*HRECV: End of batch");
  1466.                                    rxpos = 0L;
  1467.                                    rxstate = HRX_DONE;
  1468.                                    batchesdone++;
  1469.                                 }
  1470.                                 else {
  1471.                                    long diskfree;
  1472.  
  1473.                                    rxfsize = rxftime = 0L;
  1474.                                    rxfname[0] = '\0';
  1475.                                    sscanf((char *) rxbuf,"%08lx%08lx%*08lx%*08lx%*08lx%s",
  1476.                                           &rxftime, &rxfsize, rxfname);
  1477.                                    strupr(rxfname);
  1478.  
  1479.                                    hydra_gotoxy(13,2);
  1480.                                    hydra_printf(rxfname);
  1481.                                    hydra_clreol();
  1482.  
  1483.                                    rxpathname = xfer_init(rxfname,rxfsize,rxftime);
  1484.  
  1485.                                    diskfree = freespace(rxpathname);
  1486.  
  1487.                                    if (!rxpathname) {   /* Already have file */
  1488.                                       if (single_done) {
  1489.                                          hydra_gotoxy(29,2);
  1490.                                          hydra_printf("Skipping additional files");
  1491.                                          message(1,"+HRECV: Skipping additional files (file %s)",rxfname);
  1492.                                          rxpos = -2L;
  1493.                                       }
  1494.                                       else {
  1495.                                          hydra_gotoxy(29,2);
  1496.                                          hydra_printf("Already have file");
  1497.                                          message(1,"+HRECV: Already have %s",rxfname);
  1498.                                          rxpos = -1L;
  1499.                                       }
  1500.                                    }
  1501.                                    else if (rxfsize + 10240L > diskfree) {
  1502.                                       hydra_gotoxy(29,2);
  1503.                                       hydra_printf("Not enough diskspace");
  1504.                                       message(6,"!HRECV: %s not enough diskspace: %ld > %ld",
  1505.                                               rxfname, rxfsize + 10240L, diskfree);
  1506.                                       rxpos = -2L;
  1507.                                    }
  1508.                                    else {
  1509.                                       if (fexist(rxpathname)) { /* Resuming? */
  1510.                                          if ((rxfd = dos_sopen(rxpathname,0)) < 0) {
  1511.                                             message(6,"!HRECV: Unable to re-open %s",rxpathname);
  1512.                                             rxpos = -2L;
  1513.                                          }
  1514.                                       }
  1515.                                       else if ((rxfd = dos_sopen(rxpathname,1)) < 0) {
  1516.                                          message(6,"!HRECV: Unable to create %s",rxpathname);
  1517.                                          rxpos = -2L;
  1518.                                       }
  1519.  
  1520.                                       if (rxfd >= 0) {
  1521.                                          message(2,"+HRECV: %s (%ldb), %d min.",
  1522.                                                  rxfname, rxfsize,
  1523.                                                  (int) (rxfsize * 10L / cur_speed + 27L) / 54L);
  1524.                                          if (dos_seek(rxfd,0L,SEEK_END) < 0L) {
  1525.                                             message(6,"!HRECV: File seek error");
  1526.                                             hydra_badxfer();
  1527.                                             rxpos = -2L;
  1528.                                          }
  1529.                                          else {
  1530.                                             rxoffset = rxpos = dos_tell(rxfd);
  1531.                                             if (rxpos < 0L) {
  1532.                                                message(6,"!HRECV: File tell error");
  1533.                                                hydra_badxfer();
  1534.                                                rxpos = -2L;
  1535.                                             }
  1536.                                             else {
  1537.                                                rxstart = 0L;
  1538.                                                rxtimer = h_timer_reset();
  1539.                                                rxretries = 0;
  1540.                                                rxlastsync = 0L;
  1541.                                                rxsyncid = 0L;
  1542.                                                hydra_status(false);
  1543.                                                if (rxpos > 0L) {
  1544.                                                   hydra_gotoxy(46,2);
  1545.                                                   hydra_printf("%ld/%ld",rxpos,rxfsize);
  1546.                                                   message(1,"+HRECV: Resuming from offset %ld (%d min. to go)",
  1547.                                                           rxpos, (int) ((rxfsize - rxoffset) * 10L / cur_speed + 27L) / 54L);
  1548.                                                }
  1549.                                                rxstate = HRX_DATA;
  1550.                                             }
  1551.                                          }
  1552.                                       }
  1553.                                    }
  1554.                                 }
  1555.                              }
  1556.                              else if (rxstate == HRX_DONE)
  1557.                                 rxpos = (!rxbuf[0]) ? 0L : -2L;
  1558.  
  1559.                              h_long1(txbufin) = intell(rxpos);
  1560.                              txpkt((int) sizeof (long),HPKT_FINFOACK);
  1561.                              break;
  1562.  
  1563.                         /*---------------------------------------------------*/
  1564.                         case HPKT_FINFOACK:
  1565.                              if (txstate == HTX_FINFO || txstate == HTX_FINFOACK) {
  1566.                                 braindead = h_timer_set(H_BRAINDEAD);
  1567.                                 txretries = 0;
  1568.                                 if (!txfname[0]) {
  1569.                                    txtimer = h_timer_set(H_IDLE);
  1570.                                    txstate = HTX_REND;
  1571.                                 }
  1572.                                 else {
  1573.                                    txtimer = h_timer_reset();
  1574.                                    txpos = intell(h_long1(rxbuf));
  1575.                                    if (txpos >= 0L) {
  1576.                                       txoffset = txpos;
  1577.                                       txlastack = txpos;
  1578.                                       hydra_status(true);
  1579.                                       if (txpos > 0L) {
  1580.                                          message(1,"+HSEND: Transmitting from offset %ld (%d min. to go)",
  1581.                                                  txpos, (int) ((txfsize - txoffset) * 10L / cur_speed + 27L) / 54L);
  1582.                                          if (dos_seek(txfd,txpos,SEEK_SET) < 0L) {
  1583.                                             message(6,"!HSEND: File seek error");
  1584.                                             dos_close(txfd);
  1585.                                             txfd = -1;
  1586.                                             txpos = -2L;
  1587.                                             txstate = HTX_EOF;
  1588.                                             break;
  1589.                                          }
  1590.                                       }
  1591.                                       txstate = HTX_XDATA;
  1592.                                    }
  1593.                                    else {
  1594.                                       dos_close(txfd);
  1595.                                       if (txpos == -1L) {
  1596.                                          hydra_gotoxy(29,1);
  1597.                                          hydra_printf("They already have file");
  1598.                                          message(1,"+HSEND: They already have %s",txfname);
  1599.                                          if (mailer)
  1600.                                             resultlog(true,txpathname,txfsize,0L);
  1601.                                          return (XFER_OK);
  1602.                                       }
  1603.                                       else {  /* (txpos < -1L) file NOT sent */
  1604.                                          hydra_gotoxy(29,1);
  1605.                                          hydra_printf("Skipping");
  1606.                                          message(1,"+HSEND: Skipping %s",txfname);
  1607.                                          return (XFER_SKIP);
  1608.                                       }
  1609.                                    }
  1610.                                 }
  1611.                              }
  1612.                              break;
  1613.  
  1614.                         /*---------------------------------------------------*/
  1615.                         case HPKT_DATA:
  1616.                              if (rxstate == HRX_DATA) {
  1617.                                 if (intell(h_long1(rxbuf)) != rxpos ||
  1618.                                     intell(h_long1(rxbuf)) < 0L) {
  1619.                                    if (intell(h_long1(rxbuf)) <= rxlastsync) {
  1620.                                       rxtimer = h_timer_reset();
  1621.                                       rxretries = 0;
  1622.                                    }
  1623.                                    rxlastsync = intell(h_long1(rxbuf));
  1624.  
  1625.                                    if (!h_timer_running(rxtimer) ||
  1626.                                        h_timer_expired(rxtimer)) {
  1627.                                       if (rxretries > 4) {
  1628.                                          if (txstate < HTX_REND &&
  1629.                                              !originator && !hdxlink) {
  1630.                                             hdxlink = true;
  1631.                                             rxretries = 0;
  1632.                                          }
  1633.                                       }
  1634.                                       if (++rxretries > H_RETRIES) {
  1635.                                          message(3,"-HRECV: Too many errors");
  1636.                                          txstate = HTX_DONE;
  1637.                                          res = XFER_ABORT;
  1638.                                          break;
  1639.                                       }
  1640.                                       if (rxretries == 1)
  1641.                                          rxsyncid++;
  1642.  
  1643.                                       rxblklen /= 2;
  1644.                                       i = rxblklen;
  1645.                                       if      (i <=  64) i =   64;
  1646.                                       else if (i <= 128) i =  128;
  1647.                                       else if (i <= 256) i =  256;
  1648.                                       else if (i <= 512) i =  512;
  1649.                                       else               i = 1024;
  1650.                                       message(0,"-HRECV: Bad pkt at %ld - Retry %u (newblklen=%u)",
  1651.                                               rxpos,rxretries,i);
  1652.                                       h_long1(txbufin) = intell(rxpos);
  1653.                                       h_long2(txbufin) = intell((long) i);
  1654.                                       h_long3(txbufin) = intell(rxsyncid);
  1655.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1656.                                       rxtimer = h_timer_set(timeout);
  1657.                                    }
  1658.                                 }
  1659.                                 else {
  1660.                                    braindead = h_timer_set(H_BRAINDEAD);
  1661.                                    rxpktlen -= (int) sizeof (long);
  1662.                                    rxblklen = rxpktlen;
  1663.                                    if (dos_write(rxfd,rxbuf + ((int) sizeof (long)),rxpktlen) < 0) {
  1664.                                       message(6,"!HRECV: File write error");
  1665.                                       hydra_badxfer();
  1666.                                       rxpos = -2L;
  1667.                                       rxretries = 1;
  1668.                                       rxsyncid++;
  1669.                                       h_long1(txbufin) = intell(rxpos);
  1670.                                       h_long2(txbufin) = intell(0L);
  1671.                                       h_long3(txbufin) = intell(rxsyncid);
  1672.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1673.                                       rxtimer = h_timer_set(timeout);
  1674.                                       break;
  1675.                                    }
  1676.                                    rxretries = 0;
  1677.                                    rxtimer = h_timer_reset();
  1678.                                    rxlastsync = rxpos;
  1679.                                    rxpos += rxpktlen;
  1680.                                    if (rxwindow) {
  1681.                                       h_long1(txbufin) = intell(rxpos);
  1682.                                       txpkt((int) sizeof(long),HPKT_DATAACK);
  1683.                                    }
  1684.                                    if (!rxstart)
  1685.                                       rxstart = time(NULL) -
  1686.                                                 ((rxpktlen * 10) / cur_speed);
  1687.                                    hydra_status(false);
  1688.                                 }/*badpkt*/
  1689.                              }/*rxstate==HRX_DATA*/
  1690.                              break;
  1691.  
  1692.                         /*---------------------------------------------------*/
  1693.                         case HPKT_DATAACK:
  1694.                              if (txstate == HTX_XDATA || txstate == HTX_DATAACK ||
  1695.                                  txstate == HTX_XWAIT ||
  1696.                                  txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1697.                                 if (txwindow && intell(h_long1(rxbuf)) > txlastack) {
  1698.                                    txlastack = intell(h_long1(rxbuf));
  1699.                                    if (txstate == HTX_DATAACK &&
  1700.                                        (txpos < (txlastack + txwindow))) {
  1701.                                       txstate = HTX_XDATA;
  1702.                                       txretries = 0;
  1703.                                       txtimer = h_timer_reset();
  1704.                                    }
  1705.                                 }
  1706.                              }
  1707.                              break;
  1708.  
  1709.                         /*---------------------------------------------------*/
  1710.                         case HPKT_RPOS:
  1711.                              if (txstate == HTX_XDATA || txstate == HTX_DATAACK ||
  1712.                                  txstate == HTX_XWAIT ||
  1713.                                  txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1714.                                 if (intell(h_long3(rxbuf)) != txsyncid) {
  1715.                                    txsyncid = intell(h_long3(rxbuf));
  1716.                                    txretries = 1;
  1717.                                    txtimer = h_timer_reset();
  1718.                                    txpos = intell(h_long1(rxbuf));
  1719.                                    if (txpos < 0L) {
  1720.                                       if (txfd >= 0) {
  1721.                                          hydra_gotoxy(29,1);
  1722.                                          hydra_printf("Skipping");
  1723.                                          message(1,"+HSEND: Skipping %s",txfname);
  1724.                                          dos_close(txfd);
  1725.                                          txfd = -1;
  1726.                                          txstate = HTX_EOF;
  1727.                                       }
  1728.                                       txpos = -2L;
  1729.                                       break;
  1730.                                    }
  1731.  
  1732.                                    if (txblklen > intell(h_long2(rxbuf)))
  1733.                                       txblklen = (word) intell(h_long2(rxbuf));
  1734.                                    else
  1735.                                       txblklen >>= 1;
  1736.                                    if      (txblklen <=  64) txblklen =   64;
  1737.                                    else if (txblklen <= 128) txblklen =  128;
  1738.                                    else if (txblklen <= 256) txblklen =  256;
  1739.                                    else if (txblklen <= 512) txblklen =  512;
  1740.                                    else                      txblklen = 1024;
  1741.                                    txgoodbytes = 0;
  1742.                                    txgoodneeded += 1024;
  1743.                                    if (txgoodneeded > 8192)
  1744.                                       txgoodneeded = 8192;
  1745.  
  1746.                                    hydra_status(true);
  1747.                                    message(0,"+HSEND: Resending from offset %ld (newblklen=%u)",
  1748.                                            txpos,txblklen);
  1749.                                    if (dos_seek(txfd,txpos,SEEK_SET) < 0L) {
  1750.                                       message(6,"!HSEND: File seek error");
  1751.                                       dos_close(txfd);
  1752.                                       txfd = -1;
  1753.                                       txpos = -2L;
  1754.                                       txstate = HTX_EOF;
  1755.                                       break;
  1756.                                    }
  1757.  
  1758.                                    if (txstate != HTX_XWAIT)
  1759.                                       txstate = HTX_XDATA;
  1760.                                 }
  1761.                                 else {
  1762.                                    if (++txretries > H_RETRIES) {
  1763.                                       message(3,"-HSEND: Too many errors");
  1764.                                       txstate = HTX_DONE;
  1765.                                       res = XFER_ABORT;
  1766.                                       break;
  1767.                                    }
  1768.                                 }
  1769.                              }
  1770.                              break;
  1771.  
  1772.                         /*---------------------------------------------------*/
  1773.                         case HPKT_EOF:
  1774.                              if (rxstate == HRX_DATA) {
  1775.                                 if (intell(h_long1(rxbuf)) < 0L) {
  1776.                                    hydra_badxfer();
  1777.                                    hydra_gotoxy(29,2);
  1778.                                    hydra_printf("Skipping");
  1779.                                    hydra_clreol();
  1780.                                    message(1,"+HRECV: Skipping %s",rxfname);
  1781.                                    rxstate = HRX_FINFO;
  1782.                                    braindead = h_timer_set(H_BRAINDEAD);
  1783.                                 }
  1784.                                 else if (intell(h_long1(rxbuf)) != rxpos) {
  1785.                                    if (intell(h_long1(rxbuf)) <= rxlastsync) {
  1786.                                       rxtimer = h_timer_reset();
  1787.                                       rxretries = 0;
  1788.                                    }
  1789.                                    rxlastsync = intell(h_long1(rxbuf));
  1790.  
  1791.                                    if (!h_timer_running(rxtimer) ||
  1792.                                        h_timer_expired(rxtimer)) {
  1793.                                       if (++rxretries > H_RETRIES) {
  1794.                                          message(3,"-HRECV: Too many errors");
  1795.                                          txstate = HTX_DONE;
  1796.                                          res = XFER_ABORT;
  1797.                                          break;
  1798.                                       }
  1799.                                       if (rxretries == 1)
  1800.                                          rxsyncid++;
  1801.  
  1802.                                       rxblklen /= 2;
  1803.                                       i = rxblklen;
  1804.                                       if      (i <=  64) i =   64;
  1805.                                       else if (i <= 128) i =  128;
  1806.                                       else if (i <= 256) i =  256;
  1807.                                       else if (i <= 512) i =  512;
  1808.                                       else               i = 1024;
  1809.                                       message(0,"-HRECV: Bad EOF at %ld - Retry %u (newblklen=%u)",
  1810.                                               rxpos,rxretries,i);
  1811.                                       h_long1(txbufin) = intell(rxpos);
  1812.                                       h_long2(txbufin) = intell((long) i);
  1813.                                       h_long3(txbufin) = intell(rxsyncid);
  1814.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1815.                                       rxtimer = h_timer_set(timeout);
  1816.                                    }
  1817.                                 }
  1818.                                 else {
  1819.                                    rxfsize = rxpos;
  1820.                                    dos_close(rxfd);
  1821.                                    rxfd = -1;
  1822.                                    hydra_pct(false);
  1823.  
  1824.                                    p = xfer_okay();
  1825.                                    if (p) {
  1826.                                       hydra_gotoxy(25,2);
  1827.                                       hydra_printf("  -> %s",p);
  1828.                                       message(1,"+HRECV: Dup file renamed: %s",p);
  1829.                                    }
  1830.  
  1831.                                    hydra_status(false);
  1832.                                    message(1,"+Rcvd-H %s",p ? p : rxfname);
  1833.                                    resultlog(false,p ? p : rxfname,rxfsize - rxoffset,time(NULL) - rxstart);
  1834.                                    rxstate = HRX_FINFO;
  1835.                                    braindead = h_timer_set(H_BRAINDEAD);
  1836.                                 }/*skip/badeof/eof*/
  1837.                              }/*rxstate==HRX_DATA*/
  1838.  
  1839.                              if (rxstate == HRX_FINFO)
  1840.                                 txpkt(0,HPKT_EOFACK);
  1841.                              break;
  1842.  
  1843.                         /*---------------------------------------------------*/
  1844.                         case HPKT_EOFACK:
  1845.                              if (txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1846.                                 braindead = h_timer_set(H_BRAINDEAD);
  1847.                                 if (txfd >= 0) {
  1848.                                    txfsize = txpos;
  1849.                                    dos_close(txfd);
  1850.                                    hydra_pct(true);
  1851.                                    resultlog(true,txpathname,txfsize - txoffset,time(NULL) - txstart);
  1852.                                    return (XFER_OK);
  1853.                                 }
  1854.                                 else
  1855.                                    return (XFER_SKIP);
  1856.                              }
  1857.                              break;
  1858.  
  1859.                         /*---------------------------------------------------*/
  1860.                         case HPKT_IDLE:
  1861.                              if (txstate == HTX_XWAIT) {
  1862.                                 hdxlink = false;
  1863.                                 txtimer = h_timer_reset();
  1864.                                 txretries = 0;
  1865.                                 txstate = HTX_XDATA;
  1866.                              }
  1867.                              else if (txstate >= HTX_FINFO && txstate < HTX_REND)
  1868.                                 braindead = h_timer_set(H_BRAINDEAD);
  1869.                              break;
  1870.  
  1871.                         /*---------------------------------------------------*/
  1872.                         case HPKT_END:
  1873.                              /* special for chat, other side wants to quit */
  1874.                              if (chattimer > 0L && txstate == HTX_REND) {
  1875.                                 chattimer = -3L;
  1876.                                 break;
  1877.                              }
  1878.  
  1879.                              if (txstate == HTX_END || txstate == HTX_ENDACK) {
  1880.                                 txpkt(0,HPKT_END);
  1881.                                 txpkt(0,HPKT_END);
  1882.                                 txpkt(0,HPKT_END);
  1883.                                 message(1,"+HYDRA: Completed");
  1884.                                 txstate = HTX_DONE;
  1885.                                 res = XFER_OK;
  1886.                              }
  1887.                              break;
  1888.  
  1889.                         /*---------------------------------------------------*/
  1890.                         case HPKT_DEVDATA:
  1891.                              if (devrxid != intell(h_long1(rxbuf))) {
  1892.                                 hydra_devrecv();
  1893.                                 devrxid = intell(h_long1(rxbuf));
  1894.                              }
  1895.                              h_long1(txbufin) = intell(devrxid);
  1896.                              txpkt((int) sizeof (long),HPKT_DEVDACK);
  1897.                              break;
  1898.  
  1899.                         /*---------------------------------------------------*/
  1900.                         case HPKT_DEVDACK:
  1901.                              if (devtxstate && (devtxid == intell(h_long1(rxbuf)))) {
  1902.                                 devtxtimer = h_timer_reset();
  1903.                                 devtxstate = HTD_DONE;
  1904.                              }
  1905.                              break;
  1906.  
  1907.                         /*---------------------------------------------------*/
  1908.                         default:  /* unknown packet types: IGNORE, no error! */
  1909.                              break;
  1910.  
  1911.                         /*---------------------------------------------------*/
  1912.                  }/*switch(pkttype)*/
  1913.  
  1914.                  /*----------------------------------------------------------*/
  1915.                  switch (txstate) {
  1916.                         /*---------------------------------------------------*/
  1917.                         case HTX_START:
  1918.                         case HTX_SWAIT:
  1919.                              if (rxstate == HRX_FINFO) {
  1920.                                 txtimer = h_timer_reset();
  1921.                                 txretries = 0;
  1922.                                 txstate = HTX_INIT;
  1923.                              }
  1924.                              break;
  1925.  
  1926.                         /*---------------------------------------------------*/
  1927.                         case HTX_RINIT:
  1928.                              if (rxstate == HRX_FINFO) {
  1929.                                 txtimer = h_timer_reset();
  1930.                                 txretries = 0;
  1931.                                 txstate = HTX_FINFO;
  1932.                              }
  1933.                              break;
  1934.  
  1935.                         /*---------------------------------------------------*/
  1936.                         case HTX_XDATA:
  1937.                              if (rxstate && hdxlink) {
  1938.                                 message(3,"*HYDRA: %s",hdxmsg);
  1939.                                 hydra_devsend("MSG",(byte *) hdxmsg,(int) strlen(hdxmsg));
  1940.  
  1941.                                 txtimer = h_timer_set(H_IDLE);
  1942.                                 txstate = HTX_XWAIT;
  1943.                              }
  1944.                              break;
  1945.  
  1946.                         /*---------------------------------------------------*/
  1947.                         case HTX_XWAIT:
  1948.                              if (!rxstate) {
  1949.                                 txtimer = h_timer_reset();
  1950.                                 txretries = 0;
  1951.                                 txstate = HTX_XDATA;
  1952.                              }
  1953.                              break;
  1954.  
  1955.                         /*---------------------------------------------------*/
  1956.                         case HTX_REND:
  1957.                              if (!rxstate && !devtxstate) {
  1958.                                 /* special for chat, braindead will protect */
  1959.                                 if (chattimer > 0L) break;
  1960.                                 if (chattimer == 0L) chattimer = -3L;
  1961.  
  1962.                                 txtimer = h_timer_reset();
  1963.                                 txretries = 0;
  1964.                                 txstate = HTX_END;
  1965.                              }
  1966.                              break;
  1967.  
  1968.                         /*---------------------------------------------------*/
  1969.                  }/*switch(txstate)*/
  1970.            }/*while(txstate&&pkttype)*/
  1971.         } while (txstate);
  1972.  
  1973.         if (txfd >= 0)
  1974.            dos_close(txfd);
  1975.         hydra_badxfer();
  1976.  
  1977.         if (res == XFER_ABORT) {
  1978.            com_dump();
  1979.            if (carrier()) {
  1980.               com_putblock((byte *) abortstr,(int) strlen(abortstr));
  1981.               com_flush();
  1982.            }
  1983.            com_purge();
  1984.         }
  1985.         else
  1986.            com_flush();
  1987.  
  1988.         return (res);
  1989. }/*hydra()*/
  1990.  
  1991.  
  1992. /* end of hydra.c */
  1993.