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