home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / yappprot / yappxfer.pas < prev   
Pascal/Delphi Source File  |  1986-12-06  |  11KB  |  522 lines

  1. { BINXFER.INC
  2.  
  3.   (c) 1986  Jeffry B. Jacobsen
  4.  
  5.   This implements the YAPP(tm) binary transfer protocol (or at least
  6.   a subset of the full protocol - this version does not include the
  7.   server commands for automated transfer.)
  8.  
  9.   This is a modified version of the actual code used in YAPP for the
  10.   IBM PC and compatibles.  Some lines have been deleted that handled
  11.   functions such as displaying the status of the transfer, and checking
  12.   for an abort from the keyboard.
  13.  
  14. }
  15.  
  16.  
  17. type
  18.  
  19.   states = (S,S1,SH,SD,SE,ST,R,RH,RD,Abort,CW,C,Start);
  20.   paktype = (UK,RR,RF,SI,HD,DT,EF,ET,NR,CN,CA,RI,TX,UU,TM,AF,AT);
  21.   std    = array[states] of string[11];
  22.  
  23. const stdesc: std = ('SendInit  ',
  24.                      'SendInit  ',
  25.                      'SendHeader',
  26.                      'SendData  ',
  27.                      'SendEof   ',
  28.                      'SendEOT   ',
  29.                      'RcvWait   ',
  30.                      'RcvHeader ',
  31.                      'RcvData   ',
  32.                      'SndABORT  ',
  33.                      'WaitAbtAck',
  34.                      'RcdABORT  ',
  35.                      'Start     ');
  36.  
  37. var
  38.  
  39.   Sendinit_Count : integer;
  40.   xferhdr   : line;
  41.   xfercnt   : real;
  42.   xferok    : boolean;
  43.  
  44.   state     : states;
  45.   ptype     : paktype;
  46.  
  47.   pkbuff    : array [1..256] of char;
  48.   pklen     : integer;
  49.   pkfile    : file of byte;
  50.   pkfname   : string[30];
  51.   txtbuff   : line;
  52.  
  53.  
  54. const
  55.  
  56.   NUL       = #0;
  57.   SOH       = #1;
  58.   STX       = #2;
  59.   ETX       = #3;
  60.   EOT       = #4;
  61.   ENQ       = #5;
  62.   ACK       = #6;
  63.   DLE       = #16;
  64.   NAK       = #21;
  65.   CAN       = #24;
  66.  
  67.  
  68.  
  69.  
  70. function waitready: boolean;
  71. {wait 20 seconds or 120 seconds for a character}
  72.  
  73. begin
  74.   waitready := false;
  75.   if (state = S) or (state = S1) then
  76.     set_timer(20)             { 20 seconds to timeout}
  77.   else
  78.     set_timer(120);           {120 seconds to timeout}
  79.   repeat
  80.     if timeout then begin     {timeout checks timer value which is}
  81.       ptype := TM;            {decremented towards 0 every second }
  82.       waitready := true;
  83.       exit;
  84.       end;
  85.   until inready;              {inready checks for character ready at TNC}
  86. end;
  87.  
  88.  
  89. procedure getpkstr;
  90.  
  91.   var
  92.     i : integer;
  93.     ch : char;
  94.  
  95.   begin
  96.     if waitready then exit;
  97.     ch := recvchar;           {recvchar returns character from TNC}
  98.     pklen := ord(ch);
  99.     if (ptype = DT) and (pklen = 0) then pklen := 256;
  100.     if (pklen = 0) then exit;
  101.     for i := 1 to pklen do
  102.       begin
  103.       if waitready then exit;
  104.       ch := recvchar;
  105.       pkbuff[i] := ch;
  106.       end;
  107.    end;
  108.  
  109.  
  110. procedure Getpack;
  111.  
  112.   var
  113.     ch : char;
  114.  
  115.   begin
  116.     ptype := UK;
  117.     if waitready then exit;
  118.     ch := recvchar;
  119.     case ch of
  120.       ACK:  begin
  121.             if waitready then exit;
  122.             ch := recvchar;
  123.             case ord(ch) of
  124.               1: ptype := RR;
  125.               2: ptype := RF;
  126.               3: ptype := AF;
  127.               4: ptype := AT;
  128.               5: ptype := CA;
  129.               else;
  130.               end;
  131.             end;
  132.       ENQ:  begin
  133.             if waitready then exit;
  134.             ch := recvchar;
  135.             case ord(ch) of
  136.               1: ptype := SI;
  137.               2: ptype := RI;
  138.               else ptype := UU; {unimplemented command}
  139.               end;
  140.             end;
  141.       SOH:  begin
  142.             ptype := HD;
  143.             getpkstr;
  144.             end;
  145.       STX:  begin
  146.             ptype := DT;
  147.             getpkstr;
  148.             end;
  149.       ETX:  begin
  150.             if waitready then exit;
  151.             ch := recvchar;
  152.             if (ord(ch) = 1) then ptype := EF;
  153.             end;
  154.       EOT:  begin
  155.             if waitready then exit;
  156.             ch := recvchar;
  157.             if (ord(ch) = 1) then ptype := ET;
  158.             end;
  159.       NAK:  begin
  160.             ptype := NR;
  161.             getpkstr;
  162.             end;
  163.       CAN:  begin
  164.             ptype := CN;
  165.             getpkstr;
  166.             end;
  167.       DLE:  begin
  168.             ptype := TX;
  169.             getpkstr;
  170.             end;
  171.     else;
  172.     end; {case}
  173.   end;
  174.  
  175.  
  176. procedure Sendinit;
  177.  
  178.   begin
  179.     Sendinit_Count := 0;
  180.     xmitstr(ENQ + #01);          {send string to TNC}
  181.     getpack;
  182.     case ptype of
  183.       TM : state := S1;
  184.       RI : state := S;
  185.       RR : state := SH;
  186.       RF : state := SD;
  187.       CN : state := C;
  188.       NR : state := Start;
  189.       TX : disppacket;
  190.       else begin
  191.            state := Abort;
  192.            showmsg(13);          {error message display}
  193.            end;
  194.       end;
  195.     end;
  196.  
  197.  
  198.  
  199. procedure Sendinit_retry;
  200.  
  201.   begin
  202.     Sendinit_Count := Sendinit_Count + 1;
  203.     if (Sendinit_Count > 6) then begin
  204.       state := Abort;
  205.       showmsg(12);
  206.       exit;
  207.       end;
  208.     xmitstr(ENQ + #01);
  209.     getpack;
  210.     case ptype of
  211.       TM : state := S1;
  212.       RI : state := S;
  213.       RR : state := SH;
  214.       RF : state := SD;
  215.       CN : state := C;
  216.       NR : state := Start;
  217.       TX : disppacket;
  218.       else begin
  219.            state := Abort;
  220.            showmsg(13);
  221.            end;
  222.       end;
  223.     end;
  224.  
  225.  
  226.  
  227. procedure Sendhdr;
  228.  
  229.   var
  230.     stlen : byte;
  231.  
  232.   begin
  233.     temp := pkfname + NUL + filesize + NUL;
  234.     xferhdr := temp;
  235.     showheader;                          {display}
  236.     stlen := length(temp);
  237.     xmitstr(SOH + chr(stlen) + temp);
  238.     getpack;
  239.     case ptype of
  240.       RF : state := SD;
  241.       CN : state := C;
  242.       NR : state := Start;
  243.       TX : disppacket;
  244.       else begin
  245.            state := Abort;
  246.            if (ptype = TM) then showmsg(12)
  247.              else showmsg(13);
  248.            end;
  249.       end;
  250.     end;
  251.  
  252.  
  253.  
  254. procedure Senddata;
  255.  
  256.   var
  257.     i,cnt : integer;
  258.     bte : byte;
  259.     temp : array [1..256] of char;
  260.     ch: char;
  261.     scancode: integer;
  262.  
  263.   begin
  264.     if inready then begin     {we shouldnt be getting a packet   }
  265.       getpack;                {unless they sent a Cancel or Text }
  266.       if (ptype = CN) then begin
  267.         state := C;
  268.         exit;
  269.         end
  270.       else if (ptype = TX) then 
  271.         disppacket
  272.       else begin
  273.         writeln('Unexpected packet type during Send!');
  274.         state := Abort;
  275.         exit;
  276.         end;
  277.       end;
  278.     cnt := 0;
  279.     while (not eof(pkfile)) and (cnt < 256) do
  280.       begin
  281.       cnt := cnt + 1;
  282.       read(pkfile,bte);
  283.       temp[cnt] := chr(bte);
  284.       end;
  285.     if cnt <> 0 then
  286.       begin
  287.       if cnt = 256 then bte := 0 else bte := cnt;
  288.       xmitstr(STX + chr(bte));
  289.       for i := 1 to cnt do
  290.         xmitchar(temp[i]);
  291.       end;
  292.     if cnt < 256 then state := SE;
  293.     xfercnt := xfercnt + cnt;
  294.   end;
  295.  
  296.  
  297. procedure SendEOF;
  298.  
  299.   begin
  300.     xmitstr(ETX + #01);
  301.     getpack;
  302.     case ptype of
  303.       AF : state := ST;
  304.       TX : disppacket;
  305.       else begin
  306.            state := Abort;
  307.            if (ptype = TM) then showmsg(12)
  308.              else showmsg(13);
  309.            end;
  310.       end;
  311.     end;
  312.  
  313.  
  314. procedure SendEOT;
  315.  
  316.   begin
  317.     xmitstr(EOT + #01);
  318.     getpack;
  319.     case ptype of
  320.       AT : state := Start;  {Ack ok}
  321.       TX : disppacket;
  322.       else state := Start;  {They sent AF - so dont worry about it}
  323.     end;
  324.   end;
  325.  
  326.  
  327. procedure Receive;
  328.  
  329.   begin
  330.     getpack;
  331.     case ptype of
  332.       SI : begin
  333.            showmsg(1);
  334.            xmitstr(ACK + #01);
  335.            state := RH;
  336.            end;
  337.       CN : state := C;
  338.       TX : disppacket;
  339.       else begin
  340.            state := Abort;
  341.            if (ptype = TM) then showmsg(12)
  342.              else showmsg(13);
  343.            end;
  344.       end;
  345. end;
  346.  
  347.  
  348. procedure RcvHdr;
  349.  
  350. var
  351.   i : integer;
  352.   temp : line;
  353.  
  354.   begin
  355.     temp := '';
  356.     getpack;
  357.     case ptype of
  358.       HD : begin
  359.            for i := 1 to pklen
  360.              do temp := temp + pkbuff[i];
  361.            xferhdr := temp;
  362.            showheader;
  363.            xmitstr(ACK + #02);
  364.            state := RD;
  365.            end;
  366.       SI : state := RH;
  367.       CN : state := C;
  368.       ET : begin
  369.            xmitstr(ACK + #04);
  370.            state := Start;
  371.            end;
  372.       TX : disppacket;
  373.       else begin
  374.            state := Abort;
  375.            if (ptype = TM) then showmsg(12)
  376.              else showmsg(13);
  377.            end;
  378.       end;
  379.     end;
  380.  
  381.  
  382. procedure RcvData;
  383.  
  384. var
  385.   i : integer;
  386.   bte : byte;
  387.  
  388.   begin
  389.     getpack;
  390.     case ptype of
  391.       DT : begin
  392.            for i := 1 to pklen do
  393.              begin
  394.              bte := ord(pkbuff[i]);
  395.              write(pkfile,bte);
  396.              end;
  397.            xfercnt := xfercnt + pklen;
  398.            showbytes;
  399.            state := RD;
  400.            end;
  401.       EF : begin
  402.            close(pkfile);
  403.            xferok := TRUE;
  404.            showmsg(8);
  405.            xmitstr(ACK + #03);
  406.            state := RH;
  407.            end;
  408.       CN : state := C;
  409.       TX : disppacket;
  410.       else begin
  411.            state := Abort;
  412.            if (ptype = TM) then showmsg(12)
  413.              else showmsg(13);
  414.            end;
  415.       end;
  416.     end;
  417.  
  418.  
  419.  
  420. procedure Cancel;
  421.  
  422.   begin
  423.     xmitstr(CAN + #00);
  424.     state := CW;
  425.   end;
  426.  
  427.  
  428. procedure CanWait;
  429.  
  430.   begin
  431.     escmsg(10);
  432.     getpack;
  433.     case ptype of
  434.       CA : state := Start;
  435.       CN : xmitstr(ACK + #05);
  436.       TM : state := Start;
  437.       UK : state := Start;
  438.       TX : disppacket;
  439.       else;
  440.     end;
  441.   end;
  442.  
  443.  
  444.  
  445. procedure CanRecd;
  446.  
  447. var
  448.   i : integer;
  449.   bte : byte;
  450.  
  451.   begin
  452.     showmsg(11);
  453.     xmitstr(ACK + #05);
  454.     delay(3000);   {see if this helps the stupid TNC-2s problem!}
  455.     state := Start;
  456.   end;
  457.  
  458.  
  459.  
  460. procedure xfer;
  461.  
  462. begin
  463.   xferhdr := '';
  464.   xfercnt := 0;
  465.   xmitline('t');   {put TNC into transparent mode}
  466.   delay(50);
  467.   txtbuff := '';
  468.   repeat
  469.     showstate;     {display state}
  470.     case state of
  471.       S: Sendinit;
  472.      S1: Sendinit_retry;
  473.      SH: Sendhdr;
  474.      SD: Senddata;
  475.      SE: SendEOF;
  476.      ST: SendEOT;
  477.       R: Receive;
  478.      RH: Rcvhdr;
  479.      RD: Rcvdata;
  480.   Abort: Cancel;
  481.      CW: CanWait;
  482.       C: CanRecd;
  483.     else;
  484.     end; {case}
  485.   until (state = Start);
  486.  
  487.   write(#07);     {bell}
  488.   delay(1000);    {give TNC some time}
  489.   cmdmode;        {get into command mode}
  490.   flush;
  491.   xmitline('conv');  {back to converse mode}
  492. end;
  493.  
  494.  
  495. procedure upload;
  496.  
  497.   begin
  498.     pkfname := getfilname('Upload Filename: ');
  499.     Assign(pkfile,pkfname);
  500.     reset(pkfile);
  501.     state := S;
  502.     xfer;
  503.     close(pkfile);
  504.   end;
  505.  
  506.  
  507. procedure download;
  508.  
  509.   begin
  510.     pkfname := getfilname('Enter Filename: ');
  511.     assign(pkfile,pkfname);
  512.     rewrite(pkfile);
  513.     state := R;
  514.     xferok := FALSE;
  515.     xfer;
  516.     if not xferok then begin
  517.       close(pkfile);
  518.       erase(pkfile);
  519.       end;
  520.   end;
  521.  
  522.