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