home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / perqa / kermitsend < prev    next >
Text File  |  2020-01-01  |  14KB  |  459 lines

  1. module KermitSend ;
  2.  
  3. (* 29-Nov-83 Allow eight bit file transfer (c.f. sopen call) [pgt001] *)
  4.  
  5.  
  6. EXPORTS
  7.  
  8. PROCEDURE SendPacket;
  9. PROCEDURE SendACK((* Using *) n:Integer); (* send ACK packet *)
  10. PROCEDURE SendNAK((* Using *) n:Integer); (* send NAK packet *)
  11. PROCEDURE SendSwitch;
  12.  
  13.  
  14.  
  15.  
  16. PRIVATE
  17.  
  18. IMPORTS KermitGlobals   FROM KermitGlobals ;
  19. IMPORTS KermitUtils     FROM KermitUtils ;
  20. IMPORTS Stdio           FROM Stdio ;
  21. IMPORTS KermitError     FROM KermitError ;
  22. IMPORTS KermitRecv      FROM KermitRecv ;    (* for receiving ACKs and NAKs *)
  23. IMPORTS UtilProgress    FROM UtilProgress ;
  24. IMPORTS Sleep           FROM Sleep ;
  25.  
  26.  
  27. {$RANGE-}    (* Range checks off   16-Jan-84 *)
  28.  
  29.  
  30.  
  31.  
  32. VAR
  33.    DataSendCount: Integer ; (* counter for progress *)
  34.  
  35.  
  36. PROCEDURE PutOut( p : Ppack); (* Output Packet *)
  37.    (* Use direct calls to XmtChar to send the characters -pt*)
  38.    VAR
  39.       i : Integer;
  40.    BEGIN
  41.       IF (NumPad > 0) THEN
  42.          FOR i := 1 TO NumPad DO
  43.             XmtChar( Chr(PadChar) );
  44.       WITH Buf[p] DO
  45.          BEGIN
  46.             XmtChar( Chr(mark) );
  47.             XmtChar( Chr(count) );
  48.             XmtChar( Chr(seq) );
  49.             XmtChar( Chr(ptype) );
  50.             FOR i := 1 TO ilength(data) DO
  51.                XmtChar( Chr(data[i]) );
  52.          END;
  53.    END;
  54.  
  55.  
  56. PROCEDURE ReSendPacket;
  57.    (* re -sends previous packet *)
  58.    BEGIN
  59.       NumSendPacks := NumSendPacks+1;
  60.       ChInPack := ChInPack + NumPad + UnChar(Buf[LastPacket].count) + 3 ;
  61.       IF Debug
  62.       THEN DebugPacket('Re-Sending: ',LastPacket);
  63.       PutOut(LastPacket);
  64.    END;
  65.  
  66. PROCEDURE SendPacket;
  67.  
  68.    (* expects count as length of data portion *)
  69.    (* and seq as number of packet *)
  70.    (* builds & sends packet *)
  71.    VAR
  72.       i,len,chksum : Integer;
  73.       temp : Ppack;
  74.    BEGIN
  75.       IF (NumTry <> 1) AND (RunType = Transmit) THEN
  76.          ReSendPacket
  77.       ELSE
  78.          BEGIN
  79.             WITH Buf[ThisPacket] DO
  80.                BEGIN
  81.                   mark :=SOH;               (* mark *)
  82.                   len := count;             (* save length *)
  83.                   count := MakeChar(len+3); (* count = 3+length of data *)
  84.                   seq := MakeChar(seq);     (* seq number *)
  85.                   chksum := count + seq + ptype;
  86.                   IF (len > 0) THEN      (* is there data ? *)
  87.                      FOR i:= 1 TO len DO
  88.                         chksum := chksum + data[i];       (* loop for data *)
  89.                   chksum := CheckFunction(chksum);  (* calculate  checksum *)
  90.                   data[len+1] := MakeChar(chksum);  (* make printable & output *)
  91.                   data[len+2] := SendEOL;                    (* EOL *)
  92.                   data[len+3] := ENDSTR;
  93.                END;
  94.  
  95.             NumSendPacks := NumSendPacks+1;
  96.             IF Debug
  97.             THEN DebugPacket('Sending: ',ThisPacket);
  98.             PutOut(ThisPacket);
  99.  
  100.             IF (RunType = Transmit) THEN
  101.                BEGIN
  102.                   ChInPack := ChInPack + NumPad + len + 6;
  103.                   temp := LastPacket;
  104.                   LastPacket := ThisPacket;
  105.                   ThisPacket := temp;
  106.                END;
  107.          END
  108.  
  109.    END;
  110.  
  111. PROCEDURE SendACK((* Using *) n:Integer); (* send ACK packet *)
  112.    BEGIN
  113.       WITH Buf[ThisPacket] DO
  114.          BEGIN
  115.             count := 0;
  116.             seq := n;
  117.             ptype := TYPEY;
  118.          END;
  119.       SendPacket;
  120.       NumACK := NumACK+1;
  121.    END;
  122.  
  123. PROCEDURE SendNAK((* Using *) n:Integer); (* send NAK packet *)
  124.    BEGIN
  125.       WITH Buf[ThisPacket] DO
  126.          BEGIN
  127.             count := 0;
  128.             seq := n;
  129.             ptype := TYPEN;
  130.          END;
  131.       SendPacket;
  132.       NumNAK := NumNAK+1;
  133.    END;
  134.  
  135.  
  136.  
  137. PROCEDURE GetData((* Returning *)   VAR newstate:KermitStates);
  138.    (* get data from file into ThisPacket *)
  139.    VAR
  140.       (* and return next state - data &  EOF *)
  141.       x,c : CharBytes;
  142.       i: Integer;
  143.    BEGIN
  144.       IF (NumTry = 1) THEN
  145.          BEGIN
  146.             i := 1;
  147.             x := ENDSTR;
  148.             WITH Buf[ThisPacket] DO
  149.                BEGIN
  150.                   WHILE (i< SizeSend - 8 ) AND (x <> ENDFILE)
  151.                   (* leave room for quote  & NEWLINE *)
  152.                   DO
  153.                      BEGIN
  154.                         x := getcf(c,DiskFile);
  155.                         IF (x <> ENDFILE) THEN
  156.                            IF IsControl(x) OR (x = SendQuote) THEN
  157.                               BEGIN           (* control char -- quote *)
  158.                                  IF (x = LF) THEN  (* use proper EOL *)
  159.                                    BEGIN
  160.                                       data[i] := SendQuote;
  161.                                       i := i+1;
  162.                                       data[i] := Ctl(CR);
  163.                                       i := i+1;
  164.                                       (* LF will sent below *)
  165.                                    END;
  166.                                  data[i] := SendQuote;
  167.                                  i := i+1;
  168.                                  IF (x <> SendQuote) THEN  data[i] := Ctl(x)
  169.                                  ELSE  data[i] := SendQuote;
  170.                               END
  171.                            ELSE               (* regular char *)
  172.                               data[i] := x;
  173.  
  174.                         IF (x <> ENDFILE) THEN
  175.                            BEGIN
  176.                               i := i+1;    (* increase count for next char *)
  177.                               ChInFile := ChInFile + 1 ;
  178.                            END;
  179.                      END;
  180.  
  181.                   data[i] := ENDSTR;   (* to terminate string *)
  182.  
  183.                   count := i -1;       (* length *)
  184.                   seq := n;
  185.                   ptype := TYPED;
  186.  
  187.                   IF (x = ENDFILE) THEN
  188.                      BEGIN
  189.                         newstate := EOFile;
  190.                         Sclose(DiskFile);
  191.                         DiskFile := StdIOError;
  192.                      END
  193.                   ELSE
  194.                      newstate := FileData;
  195.                   SaveState := newstate;        (* save state *)
  196.                END
  197.          END
  198.       ELSE
  199.          newstate := SaveState;        (* get old state *)
  200.    END;
  201.  
  202. FUNCTION GetNextFile: (* Returning *) Boolean;
  203.    (* get next file to send in ThisPacket *)
  204.    (* returns true if no more *)
  205.    (*         ----    --      -pt*)
  206.    VAR
  207.       result: Boolean;
  208.    BEGIN
  209.       result := True;
  210.       IF (NumTry = 1) THEN
  211.          WITH Buf[ThisPacket] DO
  212.             BEGIN
  213.                IF GetArgument(data) THEN
  214.                   BEGIN            (* open file  *)
  215.                      IF Exists(data) THEN
  216.                         BEGIN
  217.                            (* Initialise counter for each file to be sent *)
  218.                            DataSendCount := 0 ;
  219.  
  220.                            IF EightBitFile THEN  (* [pgt001] *)
  221.                               DiskFile := Sopen(data,StdIO8Read)
  222.                            ELSE
  223.                               DiskFile := Sopen(data,StdIORead);
  224.  
  225.                            count := ilength(data);
  226.                            ChInFile := ChInFile + count ;
  227.                            seq := n;
  228.                            ptype := TYPEF;
  229.                            Write('[Sending ');
  230.                            PutStr(data,stdout);
  231.                            Writeln(']') ;
  232.                            IF (DiskFile <= StdIOError) THEN
  233.                               ErrorMsg('?Can''t open file');
  234.                            result := False;
  235.                         END
  236.                      ELSE (* file does not exist *)
  237.                         BEGIN
  238.                            ErrorMsg('?Can''t find file: ') ;
  239.                            ErrorStr( data ) ;
  240.                            result := True  (* I.e. fail: state -> abort *)
  241.                         END
  242.                   END;
  243.             END
  244.       ELSE
  245.          result := False; (* for saved packet *)
  246.       GetNextFile := result;
  247.    END;
  248.  
  249. PROCEDURE SendFile; (* send file name packet *)
  250.    BEGIN
  251.       Verbose( 'Sending ');
  252.       IF (NumTry > MaxTry) THEN
  253.          BEGIN
  254.             ErrorMsg ('Send file - Too Many');
  255.             State := Abort;      (* too many tries, abort *)
  256.          END
  257.       ELSE
  258.          BEGIN
  259.             NumTry := NumTry+1;
  260.             IF GetNextFile THEN
  261.                BEGIN
  262.                   State := Break;
  263.                   NumTry := 0;
  264.                END
  265.             ELSE
  266.                BEGIN
  267.                   IF Verbosity THEN
  268.                      IF (NumTry = 1)
  269.                      THEN ErrorStr(Buf[ThisPacket].data)
  270.                      ELSE ErrorStr(Buf[LastPacket].data);
  271.                   SendPacket;     (* send this packet *)
  272.                   IF ReceiveACK THEN
  273.                      BEGIN
  274.                         State := FileData;
  275.                         NumTry := 0;
  276.                         n := (n+1) MOD 64;
  277.                      END
  278.                END;
  279.          END;
  280.    END;
  281.  
  282. PROCEDURE SendData;  (* send file data packets *)
  283.    VAR
  284.       newstate: KermitStates;
  285.    BEGIN
  286.       IF (Land(DataSendCount, #03) = 0) THEN
  287.         WITH OpenList[DiskFile] DO
  288.          StreamProgress( FileVar ) ;
  289.       DataSendCount := DataSendCount + 1 ;  (* next "SendData" *)
  290.  
  291.       IF (NumTry > MaxTry) THEN
  292.          BEGIN
  293.             State := Abort;       (* too many tries, abort *)
  294.             ErrorMsg ('Send data - Too many');
  295.          END
  296.       ELSE
  297.          BEGIN
  298.             NumTry := NumTry+1;
  299.             GetData(newstate);
  300.             SendPacket;
  301.             IF ReceiveACK THEN
  302.                BEGIN
  303.                   State := newstate;
  304.                   NumTry := 0;
  305.                   n := (n+1) MOD 64;
  306.                END
  307.          END;
  308.    END;
  309.  
  310. PROCEDURE SendEOF;    (* send EOF  packet *)
  311.    BEGIN
  312.       Verbose ('Sending EOF');
  313.       IF (NumTry > MaxTry) THEN
  314.          BEGIN
  315.             State := Abort;       (* too many tries, abort *)
  316.             ErrorMsg('Send EOF - Too Many');
  317.          END
  318.       ELSE
  319.          BEGIN
  320.             NumTry := NumTry+1;
  321.             IF (NumTry = 1) THEN
  322.                BEGIN
  323.                   WITH Buf[ThisPacket] DO
  324.                      BEGIN
  325.                         ptype := TYPEZ;
  326.                         seq := n;
  327.                         count := 0;
  328.                      END
  329.                END;
  330.             SendPacket;
  331.             IF ReceiveACK THEN
  332.                BEGIN
  333.                   State := FileHeader;
  334.                   NumTry := 0;
  335.                   n := (n+1) MOD 64;
  336.                END
  337.          END;
  338.    END;
  339.  
  340. PROCEDURE SendBreak; (* send break packet *)
  341.    BEGIN
  342.       Verbose ('Sending break');
  343.       IF (NumTry > MaxTry) THEN
  344.          BEGIN
  345.             State := Abort;       (* too many tries, abort *)
  346.             ErrorMsg('Send break -Too Many');
  347.          END
  348.       ELSE
  349.          BEGIN
  350.             NumTry := NumTry+1;
  351.             (* make up packet  *)
  352.             IF (NumTry = 1) THEN
  353.                BEGIN
  354.                   WITH Buf[ThisPacket] DO
  355.                      BEGIN
  356.                         ptype := TYPEB;
  357.                         seq := n;
  358.                         count := 0;
  359.                      END
  360.                END;
  361.             SendPacket; (* send this packet *)
  362.             IF ReceiveACK THEN
  363.                BEGIN
  364.                   State := Complete;
  365.                END
  366.          END;
  367.    END;
  368.  
  369. PROCEDURE SendInit;  (* send init packet *)
  370.    BEGIN
  371.       Verbose ('Sending Init');
  372.       IF (NumTry > MaxTry) THEN
  373.          BEGIN
  374.             State := Abort;      (* too many tries, abort *)
  375.             ErrorMsg('Cannot Initialize');
  376.          END
  377.       ELSE
  378.          BEGIN
  379.             NumTry := NumTry+1;
  380.             IF (NumTry = 1) THEN
  381.                BEGIN
  382.                   WITH Buf[ThisPacket] DO
  383.                      BEGIN
  384.                         EnCodeParm(data);
  385.                         count := NUMPARAM;
  386.                         seq := n;
  387.                         ptype := TYPES;
  388.                      END
  389.                END;
  390.  
  391.             SendPacket; (* send this packet *)
  392.             IF ReceiveACK THEN
  393.                BEGIN
  394.                   WITH Buf[CurrentPacket] DO
  395.                      BEGIN
  396.                         SizeSend := UnChar(data[1]);
  397.                         TheirTimeOut := UnChar(data[2]);
  398.                         NumPad := UnChar(data[3]);
  399.                         PadChar := Ctl(data[4]);
  400.                         SendEOL := CR;  (* default to CR *)
  401.                         IF (ilength(data) >= 5) THEN
  402.                            IF (data[5] <> 0) THEN  SendEOL := UnChar(data[5]);
  403.                         SendQuote := SHARP;  (* default # *)
  404.                         IF (ilength(data) >= 6) THEN
  405.                            IF (data[6] <> 0) THEN  SendQuote := data[6];
  406.                      END;
  407.  
  408.                   State := FileHeader;
  409.                   NumTry := 0;
  410.                   n := (n+1) MOD 64;
  411.                END;
  412.          END;
  413.    END;
  414.  
  415.  
  416. PROCEDURE SendSwitch;
  417.    (* Send-switch is the state table switcher for sending files.
  418.     * It loops until either it is finished or a fault is encountered.
  419.     * Routines called by sendswitch are responsible for changing the state.
  420.     *)
  421.  
  422.    HANDLER GotErrorPacket(VAR msg: istring) ;
  423.       (* We got an error packet when trying to receive another packet. *)
  424.       (* (possibly an ACK). Write the packet data and exit SEND command *)
  425.       BEGIN
  426.          Inverse( TRUE ) ;
  427.          Writeln ;
  428.          Writeln('?SEND received an error packet from the other Host') ;
  429.          putstr(msg, STDOUT) ;
  430.          Writeln ;
  431.          Inverse( FALSE ) ;
  432.          SClose( DiskFile ) ; (* close the disk file if its open *)
  433.          State := Abort ;
  434.          EXIT( SendSwitch )
  435.       END ;
  436.  
  437.  
  438.    BEGIN
  439.       LoadCurs ; (* Load the progress cursors *)
  440.       State := Init;              (* send initiate is the start state *)
  441.       NumTry := 0;                (* say no tries yet *)
  442.       IF (Delay > 0) THEN Sleep(Delay);
  443.       REPEAT
  444.          CASE State OF
  445.             FileData:     SendData;         (* data-send state *)
  446.             FileHeader:   SendFile;         (* send file name *)
  447.             EOFile:       SendEOF;          (* send end-of-file *)
  448.             Init:         SendInit;         (* send initialize *)
  449.             Break:        SendBreak;        (* send break *)
  450.             Complete:     (* nothing *);
  451.             Abort:        (* nothing *);
  452.             END (* case *);
  453.       UNTIL ( (State = Abort) OR (State=Complete) );
  454.  
  455.       QuitProgress ;  (* Remove progress cursors *)
  456.  
  457.    END.
  458.  
  459.