home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / pibterm / pibt41s1.arc / KCHECKAC.MOD < prev    next >
Text File  |  1988-01-29  |  12KB  |  314 lines

  1. (*----------------------------------------------------------------------*)
  2. (*      Check_Sliding_ACK  --- Check ACK State for sliding windows      *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Check_Sliding_ACK( Must_Get : BOOLEAN );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*     Procedure:  Check_Sliding_ACK                                    *)
  10. (*                                                                      *)
  11. (*     Purpose:    Checks ACK status for sliding windows                *)
  12. (*                                                                      *)
  13. (*     Calling Sequence:                                                *)
  14. (*                                                                      *)
  15. (*        Check_Sliding_ACK;                                            *)
  16. (*                                                                      *)
  17. (*----------------------------------------------------------------------*)
  18.  
  19. (* STRUCTURED *) CONST
  20.    Deadlock_Message : STRING[36] = 'Send cancelled -- apparent deadlock.';
  21.  
  22. VAR
  23.    A_Ch: CHAR;
  24.  
  25. (*----------------------------------------------------------------------*)
  26.  
  27. PROCEDURE Handle_Resend;
  28.  
  29. BEGIN (* Handle_Resend *)
  30.  
  31.    WITH Kermit_Queue[Rec_Packet_Num] DO
  32.       BEGIN
  33.  
  34.          INC( Retry_Count );
  35.          Send_Packet_Ptr    := ADDR( Sector_Data[Data_Slot] );
  36.          Send_Packet_Length := Data_Length;
  37. {
  38.          IF Kermit_Debug THEN
  39.             BEGIN
  40.                Write_Log('---Resending packet--- ' + IToS( Rec_Packet_Num ), FALSE, FALSE );
  41.                Write_Log('   Retry_Count = ' + IToS( Retry_Count ), FALSE, FALSE );
  42.                Write_Log('   Data_Length = ' + IToS( Data_Length ), FALSE, FALSE );
  43.             END;
  44. }
  45.          IF ( Retry_Count > Kermit_MaxTry ) THEN
  46.             BEGIN
  47.                Kermit_State       := Send_Break;
  48.                Kermit_Abort       := TRUE;
  49.                Kermit_Abort_Level := One_File;
  50.                Display_Kermit_Message('Too many retries for packet ' + IToS( Rec_Packet_Num ) );
  51.                EXIT;
  52.             END
  53.          ELSE
  54.             BEGIN
  55.                Display_Kermit_Message('Resending packet ' + 
  56.                                        IToS( Rec_Packet_Num ) + 
  57.                                        ' (Try # ' + IToS( Retry_Count ) + ')' );
  58.                Send_Packet;
  59.             END;
  60.       END;
  61.  
  62. END   (* Handle_Resend *);
  63.  
  64. (*----------------------------------------------------------------------*)
  65.  
  66. PROCEDURE Handle_ACK;
  67.  
  68. BEGIN (* Handle_ACK *)
  69.  
  70.    IF PacketInWindow THEN
  71.       BEGIN
  72.                                    (* Note that this packet has been ACKed. *)
  73.                                    (* If it is the lowest packet in the     *)
  74.                                    (* window, rotate the table.  We may     *)
  75.                                    (* need to rotate up more than one       *)
  76.                                    (* packet, depending upon how many of    *)
  77.                                    (* the following blocks have been ACK'd. *)
  78.  
  79.          ACK_OK               := TRUE;
  80.          Kermit_Window_Errors := 0;
  81.  
  82.          Kermit_Queue[Rec_Packet_Num].ACK_Flag := TRUE;
  83.  
  84.          IF ( Rec_Packet_Num = Kermit_Window_Bottom ) THEN
  85.             BEGIN
  86.                Kermit_Window_Bottom := SUCC( Kermit_Window_Bottom ) MOD 64;
  87.                DEC( Kermit_Window_Used );
  88.             END;
  89.  
  90.          WHILE ( ( Kermit_Window_Used > 0 ) AND
  91.                  ( Kermit_Queue[Kermit_Window_Bottom].ACK_Flag ) ) DO
  92.             BEGIN
  93.                Kermit_Window_Bottom := SUCC( Kermit_Window_Bottom ) MOD 64;
  94.                DEC( Kermit_Window_Used );
  95.             END;
  96.                                    (* Also check for interruption flags   *)
  97.                                    (* in data field:                      *)
  98.                                    (* 'X' = quit sending current file;    *)
  99.                                    (* 'Y' = quit batch of files.          *)
  100.  
  101.          IF ( Rec_Packet_Length > 0 ) THEN
  102.             CASE Rec_Packet_Ptr^[1] OF
  103.                'X': BEGIN
  104.                        Display_Kermit_Message_2('Receiver cancelled transfer of current file.');
  105.                        Kermit_Abort       := TRUE;
  106.                        Kermit_Abort_Level := One_File;
  107.                     END;
  108.                'Y': BEGIN
  109.                        Display_Kermit_Message_2('Receiver cancelled transfer of all files.');
  110.                        Kermit_Abort       := TRUE;
  111.                        Kermit_Abort_Level := All_Files;
  112.                     END;
  113.                ELSE;
  114.             END (* CASE *);
  115.  
  116.       END
  117.    ELSE
  118.       BEGIN
  119.          ACK_OK := TRUE;
  120.          INC( Kermit_Window_Errors );
  121.          IF ( Kermit_Window_Errors > Kermit_MaxTry ) THEN
  122.             BEGIN
  123.                Display_Kermit_Message_2( Deadlock_Message );
  124.                Kermit_Abort       := TRUE;
  125.                Kermit_Abort_Level := One_File;
  126.                Kermit_State       := Send_Break;
  127.             END;
  128.       END;
  129.  
  130. END   (* Handle_ACK *);
  131.  
  132. (*----------------------------------------------------------------------*)
  133.  
  134. PROCEDURE Handle_NAK;
  135.  
  136. BEGIN (* Handle_NAK *)
  137.                                    (* Increment retry counter for this *)
  138.                                    (* packet if legitimate and resend  *)
  139.                                    (* it.                              *)
  140.    IF Async_Do_XonXoff THEN
  141.       BEGIN
  142.          Async_Send_Now( CHR( XON ) );
  143.          Clear_XOFF_Received;
  144.       END;
  145.  
  146.    Display_Kermit_Message('NAK for packet ' + IToS( Rec_Packet_Num ) + ' received.');
  147.  
  148.                                    (* If packet in window, try to resend it. *)
  149.                                    (* Else, increment overall error count.   *)
  150.    IF PacketInWindow THEN
  151.       BEGIN
  152.          Kermit_Window_Errors := 0;
  153.          Handle_Resend;
  154.       END
  155.    ELSE IF ( Rec_Packet_Num = ( SUCC( Kermit_Window_Top ) MOD 64 ) ) THEN
  156.       BEGIN
  157.          Rec_Packet_Num := Kermit_Window_Bottom;
  158.          Handle_Resend;
  159.       END
  160.    ELSE
  161.       BEGIN
  162.          INC( Kermit_Window_Errors );
  163.          IF ( Kermit_Window_Errors > Kermit_MaxTry ) THEN
  164.             BEGIN
  165.                Display_Kermit_Message_2( Deadlock_Message );
  166.                Kermit_Abort       := TRUE;
  167.                Kermit_Abort_Level := One_File;
  168.                Kermit_State       := Send_Break;
  169.             END;
  170.       END;
  171.  
  172. END   (* Handle_NAK *);
  173.  
  174. (*----------------------------------------------------------------------*)
  175.  
  176. PROCEDURE Handle_Error;
  177.  
  178. BEGIN (* Handle_Error *)
  179.  
  180.    Display_Kermit_Message('>> Error from remote Kermit <<');
  181.  
  182.    Kermit_Abort         := TRUE;
  183.    Kermit_Window_Errors := 0;
  184.  
  185.    GoToXY( 2 , Kermit_Mess2_Line );
  186.    WRITE( COPY( Rec_Packet_Ptr^, 1, Rec_Packet_Length ) );
  187.    ClrEol;
  188.  
  189.    Write_Log('Error from remote Kermit: ' +
  190.              COPY( Rec_Packet_Ptr^, 1, Rec_Packet_Length ) , FALSE , FALSE );
  191.  
  192.    IF ( Attended_Mode AND ( NOT Script_File_Mode ) ) THEN
  193.       BEGIN
  194.          GoToXY( 2 , Kermit_Mess3_Line );
  195.          WRITE('Hit any key to continue ... ');
  196.          Read_Kbd( A_Ch );
  197.          IF ( ORD( A_Ch ) = ESC ) AND Pibterm_keypressed THEN
  198.             Read_Kbd( A_Ch );
  199.       END;
  200.  
  201. END   (* Handle_Error *);
  202.  
  203. (*----------------------------------------------------------------------*)
  204.  
  205. BEGIN (* Check_Sliding_ACK *)
  206.                                    (* Assume bad packet to start *)
  207.    ACK_OK := FALSE;
  208.                                    (* If already aborted, quit.  *)
  209.    IF Kermit_Abort THEN
  210.       EXIT;
  211.                                    (* Pick up a packet           *)
  212.    Receive_Packet;
  213.  
  214.    Packet_Num := Rec_Packet_Num;
  215.  
  216. {
  217.    IF Kermit_Debug THEN
  218.       BEGIN
  219.  
  220.          Write_Log('---Check-Sliding-Ack---', FALSE, FALSE);
  221.  
  222.          CASE Kermit_Packet_Type OF
  223.             ACK_Pack  : Write_Log('ACK received', FALSE, FALSE);
  224.             NAK_Pack  : Write_Log('NAK received', FALSE, FALSE);
  225.             Error_Pack: Write_Log('Error received', FALSE, FALSE);
  226.             ELSE        Write_Log('Unknown received', FALSE, FALSE);
  227.          END (* CASE *);
  228.  
  229.          Write_Log('Rec_Packet_Num = ' + IToS( Rec_Packet_Num ), FALSE, FALSE);
  230.  
  231.          IF Packet_OK THEN
  232.             Write_Log('Packet_OK = TRUE', FALSE, FALSE)
  233.          ELSE
  234.             Write_Log('Packet_OK = FALSE', FALSE, FALSE);
  235.  
  236.       END;
  237. }
  238.                                    (* If we have to get a packet but *)
  239.                                    (* timed out instead, resend the  *)
  240.                                    (* earliest outstanding packet.   *)
  241.    IF Kermit_Abort THEN
  242.       ACK_OK := FALSE
  243.    ELSE IF ( ( NOT Packet_OK ) AND ( Must_Get ) ) THEN
  244.       BEGIN
  245.                                    (* Check XON/XOFF status here.  *)
  246.                                    (* Clear a received XOFF, since *)
  247.                                    (* it is probably bogus, and    *)
  248.                                    (* send XON to remote in case   *)
  249.                                    (* it received bogus XOFF.      *)
  250.  
  251.          IF Async_Do_XonXoff THEN
  252.             BEGIN
  253.                Async_Send_Now( CHR( XON ) );
  254.                Clear_XOFF_Received;
  255.             END;
  256.  
  257.          Rec_Packet_Num := Kermit_Window_Bottom;
  258.  
  259.          WHILE ( ( Rec_Packet_Num <> Kermit_Window_Top ) AND
  260.                  ( Kermit_Queue[Rec_Packet_Num].ACK_Flag = TRUE ) ) DO
  261.             Rec_Packet_Num := SUCC( Rec_Packet_Num ) MOD 64;
  262.  
  263.          IF ( NOT Kermit_Queue[Rec_Packet_Num].ACK_Flag ) THEN
  264.             Handle_Resend;
  265.  
  266.          ACK_OK := FALSE;
  267.  
  268.          INC( Kermit_Window_Errors );
  269.          IF ( Kermit_Window_Errors > Kermit_MaxTry ) THEN
  270.             BEGIN
  271.                Display_Kermit_Message_2( Deadlock_Message );
  272.                Kermit_Abort       := TRUE;
  273.                Kermit_Abort_Level := One_File;
  274.                Kermit_State       := Send_Break;
  275.             END;
  276.  
  277.       END
  278.    ELSE                            (* We got a packet. *)
  279.       BEGIN
  280.                                    (* Check if ACK or NAK packet received. *)
  281.                                    (* May also be error packet.            *)
  282.  
  283.          CASE Kermit_Packet_Type OF
  284.  
  285.                                    (* Make sure ACK is for legitimate block *)
  286.  
  287.             ACK_Pack   : Handle_ACK;
  288.             NAK_Pack   : Handle_NAK;
  289.             Error_Pack : Handle_Error;
  290.  
  291.                                    (* Something else -- don't ACK it *)
  292.             ELSE         BEGIN
  293.                             ACK_OK := FALSE;
  294.                             Display_Kermit_Message('Garbage packet received.');
  295.                             IF Async_Do_XonXoff THEN
  296.                                BEGIN
  297.                                   IF Async_XOff_Received THEN
  298.                                      Clear_XOFF_Received;
  299.                                   Async_Send_Now( CHR( XON ) );
  300.                                END
  301.                          END;
  302.  
  303.          END (* CASE *)
  304.  
  305.       END;
  306.                                    (* Update count of bad packets *)
  307.    IF ( NOT ACK_OK ) THEN
  308.       Packets_Bad := Packets_Bad + 1;
  309.  
  310.                                    (* Update display *)
  311.    Update_Kermit_Display;
  312.  
  313. END    (* Check_Sliding_ACK *);
  314.