home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / win100b / wkkerm.w < prev    next >
Text File  |  1991-10-19  |  9KB  |  395 lines

  1. /*
  2.  * Protocol module for Windows Kermit
  3.  * 
  4.  * Copyright (c) 1990, 1991 by
  5.  * William S. Hall
  6.  * 3665 Benton Street  #66
  7.  * Santa Clara, CA 95051
  8.  *
  9.  * This module must be preprocessed by wart
  10.  */
  11.  
  12. #define NOCOMM
  13. #define NOKANJI
  14. #define NOSOUND
  15. #define NOATOM
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #ifdef COLUMBIA
  20. #include "wkkerm.h"
  21. #else
  22. #include "wnkerm.h"
  23. #endif
  24.  
  25. /* The state machine returns 0 to show completion or 1 if more input
  26.  * is expected.  Currently, these return values are not used.
  27.  */
  28. #define RESUME return(0)
  29. #define CONTINUE return(1)
  30.  
  31. /* local function prototypes */
  32. static int near input(void);
  33.  
  34. static char vcmd;
  35. static int vstate;
  36.  
  37. /* protocol states */
  38. %states get rsfile rsdata ipkt rgen
  39. %states ssinit ssfile ssdata sseof sseot
  40.  
  41. /* Protocol description.
  42.  */
  43. %%
  44.  
  45. /* Begin file send
  46.  */
  47. s {        
  48.     krm_tinit();            /* initialize */
  49.     Kermit.start = 'w';            /* switch to wait */
  50. }
  51.  
  52. /* Begin get
  53.  */
  54. r {
  55.     krm_tinit();
  56.     vstate = get;
  57.     vcmd = 0;
  58.     krm_sinit('I');
  59.     BEGIN ipkt;
  60. }
  61.  
  62. /* Begin host command
  63.  */
  64. c {
  65.     krm_tinit();
  66.     vstate = rgen;
  67.     vcmd = 'C';
  68.     krm_sinit('I');
  69.     BEGIN ipkt;
  70. }
  71.  
  72. /* Begin generic command
  73.  */
  74. g {
  75.     krm_tinit();
  76.     vstate = rgen;
  77.     vcmd = 'G';
  78.     krm_sinit('I');
  79.     BEGIN ipkt;
  80. }
  81.  
  82. /* Wait to send first packet
  83.  */
  84. w {
  85.     if (Kermit.delay) {            /* timer will reset this parameter */
  86.     Kermit.start = 'w';        /* wait to send first packet */
  87.         CONTINUE;
  88.     } else {
  89.         if (krm_sinit('S') < 0) {        /* transmit sendinit packet */
  90.             krm_err(IDS_KRM_SENDINIT_ERROR);    /* error; inform remote */
  91.             RESUME;                /* quit */
  92.         }    
  93.     krmFlushQue();        /* flush any pending input in local buffer */
  94.         BEGIN ssinit;        /* prepare to open file and send file name */
  95.     }    
  96. }
  97.  
  98. /* Begin receive file
  99.  */
  100. v {
  101.     krm_tinit();            /* initialize */
  102.     BEGIN get;
  103. }
  104.  
  105. <ipkt>Y {
  106.     krm_spar(krm_rcvpkt.data, krm_rcvpkt.len);    /* read send-init data */
  107.     if (vcmd) {
  108.         if (krm_sendcmd(vcmd, Kermit.pFilelist) < 0) {
  109.             krm_err(IDS_KRM_SENDCMD_ERROR);    /* error; inform remote */
  110.             RESUME;                /* quit */
  111.         }    
  112.     vcmd = 0;
  113.     }
  114.     if (vstate == get)
  115.         if (krm_srinit(Kermit.pFilelist) < 0) {
  116.         krm_err(IDS_KRM_SENDR_ERROR);
  117.         RESUME;
  118.     }
  119.     BEGIN vstate;
  120. }
  121.  
  122. <ipkt>E {
  123.     if (vcmd)
  124.         if (krm_sendcmd(vcmd, Kermit.pFilelist) < 0) {
  125.             krm_err(IDS_KRM_SENDCMD_ERROR);    /* error; inform remote */
  126.             RESUME;                /* quit */
  127.         }    
  128.     vcmd = 0;
  129.     if (vstate == get)
  130.         if (krm_srinit(Kermit.pFilelist) < 0) {
  131.         krm_err(IDS_KRM_SENDR_ERROR);
  132.         RESUME;
  133.     }
  134.     BEGIN vstate;
  135. }
  136.         
  137. /* got ACK of sendinit packet
  138.  */
  139. <ssinit>Y {
  140.     krm_spar(krm_rcvpkt.data, krm_rcvpkt.len);    /* set init data */
  141.     Kermit.bctu = Kermit.bctr;            /* select block check type */
  142.     Kermit.pFile = krm_getnextfile(TRUE);    /* get file to send */
  143.     if (krm_sfile() < 0) {            /* send file name packet */
  144.         krm_err(IDS_KRM_SENDFILENAME_ERROR);    /* error; inform remote */
  145.         RESUME;                    /* quit */
  146.     }
  147.     BEGIN ssfile;               /* prepare to send first data packet */
  148. }
  149.  
  150. /* Got ACK of file name packet
  151.  */
  152. <ssfile>Y {
  153.     int x;
  154.     krm_savename();            /* post the remote's name for file */
  155.     if ((x = krm_sdata()) == 0) {    /* no data in file */
  156.         if (krm_seof("") < 0) {        /* send end of file */
  157.            krm_err(IDS_KRM_SENDEOF_ERROR);   /* error; inform remote */
  158.            RESUME;            /* quit */
  159.         }
  160.         BEGIN sseof;
  161.     }
  162.     else if (x < 0) {            /* error in sending file */
  163.         krm_rclose(FALSE);        /* close the file */
  164.         krm_err(IDS_KRM_SENDDATA_ERROR); /* post error to remote and quit */
  165.         RESUME;
  166.     }
  167.     else
  168.     BEGIN ssdata;            /* prepare to receive data */
  169. }
  170.  
  171. /* Got ACK to data packet
  172.  */
  173. <ssdata>Y {                
  174.     krm_checkcnx();            /* check if transaction cancelled */
  175.     if (Kermit.abort) {
  176.     if (Kermit.abort == KRM_FILEABORT)  /* cancel file send */
  177.         Kermit.abort = 0;
  178.     if (krm_seof("D") < 0) {        /* tell remote about cancellation */
  179.        krm_err(IDS_KRM_SENDEOF_ERROR);  /* error; inform remote */
  180.        RESUME;                /* quit */
  181.     }
  182.         BEGIN sseof;            /* prepare to send end of file */
  183.     }
  184.     else {
  185.         int x;
  186.     if ((x = krm_sdata()) == 0) {        /* no more data */
  187.         if (krm_seof("") < 0) {        /* send end of file */
  188.            krm_err(IDS_KRM_SENDEOF_ERROR);  /* error; inform remote */
  189.            RESUME;                /* quit */
  190.         }
  191.             BEGIN sseof;        /* prepare to send end of file */
  192.         }
  193.     else if (x < 0) {            /* error */
  194.         krm_rclose(FALSE);            /* close the file */
  195.         krm_err(IDS_KRM_SENDDATA_ERROR);    /* inform remote */
  196.         RESUME;                /* quit */
  197.         }
  198.     }
  199. }
  200.  
  201. /* Got ACK to end of file packet
  202.  */
  203. <sseof>Y {
  204.     if (Kermit.pFile = krm_getnextfile(FALSE)) {  /* any more files? */
  205.         if (krm_sfile() < 0) {              /* send next file name */
  206.             krm_err(IDS_KRM_SENDFILENAME_ERROR);  /* error, inform remote */
  207.             RESUME;                  /* quit */
  208.         }
  209.         BEGIN ssfile;                /* prepare for next file */
  210.     }    
  211.     else {                    /* no more files to send */
  212.     if (krm_seot() < 0) {            /* send break */
  213.         krm_err(IDS_KRM_SENDEOT_ERROR);    /* error, inform remote */
  214.         RESUME;                /* quit */
  215.     }
  216.     BEGIN sseot;                /* prepare to exit file send */
  217.     }
  218. }
  219.  
  220. /* Got ACK to end of transmission packet
  221.  */
  222. <sseot>Y {
  223.     krm_tend(IDS_KRM_TRANSACTION_DONE);        /* clean up */
  224.     RESUME;                    /* quit */
  225. }
  226.  
  227. /* resend of previous I packet ACK, 
  228. same sequence number */
  229. <get>Y {
  230.  
  231.     krm_srinit(Kermit.pFilelist);
  232.  
  233. }
  234.  
  235. <rgen>Y {
  236.     if (krm_rcvpkt.len > 0)
  237.     krm_tend(KRM_DATA_PACKET);
  238.     else
  239.         krm_tend(IDS_KRM_TRANSACTION_DONE);    /* clean up */
  240.     RESUME;                    /* quit */
  241. }
  242.  
  243. /* Got sendinit packet
  244.  */
  245. <rgen,get>S {
  246.     BYTE data[KRM_MAXDATALEN + 1];
  247.     krm_spar(krm_rcvpkt.data, krm_rcvpkt.len);    /* read send-init data */
  248.     krm_ack(krm_rpar(data), data);        /* return init data in ACK */
  249.     Kermit.bctu = Kermit.bctr;            /* set block check type */
  250.     BEGIN rsfile;                    /* prepare for file name */
  251. }
  252.  
  253. /* Got file name packet
  254.  */
  255. <rgen,rsfile>F {
  256.     if (krm_rcvfil()) {                /* try to open file */
  257.     char buf[KRM_MAXDATALEN + 1];            
  258.     int inlen, outlen;
  259.     inlen = strlen(Kermit.pFile);        /* return our name to remote */
  260.     outlen = krm_encode(buf, Kermit.pFile, sizeof(buf) - 1, &inlen);
  261.         krm_ack(outlen, buf);            /* send the name in ACK */
  262.         BEGIN rsdata;                /* prepare to receive data */
  263.     }
  264.     else {
  265.     krm_err(IDS_KRM_FILE_OPEN_ERROR);    /* error, inform remote */
  266.     RESUME;                    /* quit */
  267.     }
  268. }
  269.  
  270. <rgen,rsfile>X {
  271.     if (krm_opent()) {
  272.     krm_ack(0, "");
  273.     BEGIN rsdata;
  274.     }
  275.     else {
  276.     krm_err(IDS_KRM_TERMINAL_OPEN_ERROR);
  277.     RESUME;
  278.     }
  279. }
  280.  
  281. /* Got data packet
  282.  */
  283. <rsdata>D {
  284.     if (krm_rcvdata()) {
  285.     switch(Kermit.abort) {            /* see if abort flag is on */
  286.         case KRM_BATCHABORT:
  287.         krm_ack(1, "Z");        /* cancel remaining files */
  288.         Kermit.abort = 0;
  289.         break;
  290.         case KRM_FILEABORT:
  291.         krm_ack(1, "X");        /* cancel current file */
  292.         Kermit.abort = 0;
  293.         break;
  294.         default:
  295.         krm_ack(0, "");                /* continue */
  296.     }
  297.     }
  298.     else {
  299.     krm_rclose(TRUE);            /* error in storing data */
  300.     krm_err(IDS_KRM_FILE_WRITE_ERROR);    /* inform host */
  301.     RESUME;                    /* quit */
  302.     }
  303. }
  304.  
  305. /* Got end of file packet
  306.  */
  307. <rsdata>Z {        /* see if remote wants us to delete file */
  308.     if (krm_rclose(krm_rcvpkt.len && 
  309.     (krm_rcvpkt.data[0] == 'D') ? TRUE : FALSE)) {
  310.         krm_ack(0, "");                /* acknowledge */
  311.         BEGIN rsfile;                /* prepare for next file */
  312.     }
  313.     else {
  314.     krm_err(IDS_KRM_FILE_CLOSE_ERROR);    /* error; inform remote */
  315.     RESUME;                    /* quit */
  316.     }
  317. }
  318.  
  319. /* Got end of transmission packet
  320.  */
  321. <rsfile>B {
  322.     krm_ack(0, "");            /* acknowledge */
  323.     krm_tend(IDS_KRM_TRANSACTION_DONE);    /* clean up */
  324.     RESUME;                /* quit */
  325. }
  326.  
  327. /* Packet is incomplete; return.
  328.  */
  329. $ {
  330.     CONTINUE;            /* continue until packet is filled */
  331. }
  332.  
  333. /* Got error packet
  334.  */
  335. E {
  336.     krm_rclose(TRUE);        /* close any open files */
  337.     krm_tend(KRM_DATA_PACKET);    /* clean up */
  338.     RESUME;            /* quit */
  339. }
  340.  
  341. /* Unrecognized packet
  342.  */
  343. . {
  344.     krm_rclose(TRUE);            /* close any open files */
  345.     krm_err(IDS_KRM_UNKNOWN_PACKET);    /* post error to remote */
  346.     RESUME;                /* quit */
  347. }
  348.  
  349. %%
  350.  
  351. /* input
  352.  *
  353.  * provide packet type to state machine
  354.  */
  355. static int near input()
  356. {
  357.  
  358.     register int type;
  359.  
  360.     if (Kermit.start) {
  361.     type = Kermit.start;
  362.     Kermit.start = 0;
  363.     }
  364.     else {
  365.     type = krm_rpack();        /* read input */
  366.     if ((type != '$') && (type != 'E'))  {
  367.       /* packet is complete but is not an error packet */
  368.         if ((Kermit.seq != krm_rcvpkt.seq) || strchr("NQT", type)) {
  369.           /* something is wrong with packet */
  370.             if (Kermit.retries >= KermParams.RetryLimit) {
  371.           /* pretend we have an error packet */
  372.             krmCreatePseudoPacket('E', PS_DONE, IDS_KRM_TOOMANYRETRIES);
  373.             type = 'E';
  374.             }
  375.             else if ((type == 'N') && 
  376.               (krm_rcvpkt.seq == ((Kermit.seq + 1) & 63))) {
  377.           /* this is OK since NAK for next packet is ACK for previous */
  378.             type = 'Y';
  379.             Kermit.retries = 0;
  380.             }
  381.             else {
  382.           /* resend previous packet and try again */
  383.             Kermit.retries += 1;
  384.             Kermit.totalretries += 1;
  385.             krm_resend();
  386.             type = '$';
  387.             }
  388.         }
  389.         else    /* packet is OK; reset retry count */
  390.             Kermit.retries = 0;
  391.     }
  392.     }
  393.     return (type);
  394. }
  395.