home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
iclvme2900.tar.gz
/
iclvme2900.tar
/
kmt_ph_module
< prev
next >
Wrap
Text File
|
1987-07-14
|
36KB
|
902 lines
MODULE KMT_PH_MODULE;
@ VME KERMIT PROTOCOL HANDLER @
@ GLOBAL VARIABLES @
@ PKT_TYPE : packet type of current packet @
@ KMT_PH_INPUT_PACKET_DATA : pointer to packet data buffer @
@ (translated to EBCDIC and decoded) @
@ PKT_SEQ : current packet number (expected) @
@ PKT_NO : current packet number (received) @
@ RETRY_COUNT : current retry count @
@ Mode declarations: @
MODE KMT_BUFFER IS (96)BYTE;
MODE KMT_STRING IS REF()BYTE;
MODE KMT_WORD IS REF()BYTE;
MODE KMT_MTUP_VALUES IS ANY
(LONG WORD LW_VALUE,
LONG INT LI_VALUE,
REF WORD RW_VALUE,
REF INT RI_VALUE,
REF LONG WORD RLW_VALUE,
REF LONG INT RLI_VALUE,
REF()BYTE RVB_VALUE,
REF()REF()BYTE RVRVB_VALUE);
MODE KMT_PP_PACKET_STATISTICS_S IS STRUCT
(INT INPUT_TOTAL,
OUTPUT_TOTAL);
MODE KMT_TRACE_FLAGS_S IS WORD STRUCT
(BIT PH_TRACING,
PP_TRACING,
FH_TRACING,
DH_TRACING,
28-BIT SPARE);
@ External procedures @
EXT PROC (INT,RESPONSE) KMT_MESSAGE;
EXT PROC (RESPONSE) KMT_UI;
EXT PROC (REF()BYTE,INT,RESPONSE) KMT_FH_OPEN_FILE,
PROC (RESPONSE) KMT_FH_CLOSE_FILE,
PROC (RESPONSE) KMT_FH_SAVE_FILE,
PROC (REF()BYTE,REF INT,BOOL,RESPONSE) KMT_FH_GIVE_NAME;
EXT PROC () KMT_PP_TRANSLATE_TO_EBCDIC,
PROC (REF()BYTE,RESPONSE) KMT_PP_BUILD_STRING_PACKET_DATA,
PROC (RESPONSE) KMT_PP_PROCESS_PARAM_PACKET_DATA,
PROC () KMT_PP_BUILD_PARAM_PACKET_DATA,
PROC (RESPONSE) KMT_PP_BUILD_FILE_RECORD,
PROC (RESPONSE) KMT_PP_BUILD_FILE_PACKET_DATA,
PROC (REF INT,REF INT,RESPONSE) KMT_PP_GET_PACKET,
PROC (INT,INT,BOOL,RESPONSE) KMT_PP_SEND_PACKET;
@ Any error returned by KMT_PP_SEND_PACKET is fatal and Kermit will exit; @
@ warnings will have been logged already and are ignored @
EXT PROC (REF KMT_STRING) KMT_WORD KMT_SP_GET_WORD,
PROC (REF KMT_WORD,INT) KMT_SP_STANDARDISE_FILENAME,
PROC (INT,REF()KMT_MTUP_VALUES) KMT_SP_LOG_TRACE_MESSAGE;
EXT REF INT PKT_SEQ,PKT_NO,MAXTRY,RETRY_COUNT,RETRY_TOTAL,TIMEOUT_TOTAL,
RC_IGNORED;
EXT REF KMT_STRING KMT_PH_INPUT_PACKET_DATA;
EXT REF KMT_BUFFER KMT_VME_FILE_BUF,KMT_REM_FILE_BUF;
EXT REF KMT_WORD KMT_VME_FILE,KMT_REM_FILE;
EXT INT ENTRY,BREAK_PKT,DATA_PKT,FILE_HDR_PKT,NAK_PKT,SEND_INIT_PKT,ACK_PKT,
EOF_PKT;
EXT INT VME_TERM,VME_STD,KMT_STD; @ forms of name standardisation @
EXT INT REC_SERVER_IDLE,REC_INIT,REC_FILE,REC_DATA,SEND_INIT,SEND_FILE,
SEND_DATA,SEND_EOF,SEND_BREAK,COMPLETE,ABORT;
EXT INT EXIT,LOGOUT,FATAL_ERROR; @ exit states @
EXT INT EOF; @ eof on file data @
EXT INT SERVER_MODE;
EXT REF INT KMT_CURRENT_MODE;
EXT BOOL READ_INT,NO_READ_INT; @ set/don't set read interest after send @
EXT REF INT FILE_OPTION;
EXT REF BOOL DELAY_TIMER;
EXT REF BOOL SAVE_INCOMPLETE_FILE;
EXT REF INT EXIT_STATE;
EXT REF()KMT_MTUP_VALUES KMT_MTM_AREA;
EXT REF KMT_PP_PACKET_STATISTICS_S KMT_PP_PACKET_STATISTICS;
EXT REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS;
STATIC REF KMT_STRING PKT_DATA IS KMT_PH_INPUT_PACKET_DATA;
GLOBAL
STATIC (<STATUS 5>)
PROC
KMT_PH IS (REF INT STATE,INT EVENT,RESPONSE RESULT):
BEGIN
@ procedures for state entry @
SIM PROC KMT_PH_REC_SERVER_IDLE IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Server idle, waiting for message @
BEGIN
RETRY_COUNT := 0; @ try for ever in Rec_Server_Idle state @
RETRY_TOTAL := TIMEOUT_TOTAL := 0;
KMT_PP_PACKET_STATISTICS := (0,0);
PKT_SEQ := 0; @ initialise packet sequence @
RESULT := 0
END
; @ KMT_PH_REC_SERVER_IDLE @
SIM PROC KMT_PH_REC_INIT IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Entry point for non-server RECEIVE command @
BEGIN
PKT_SEQ := 0; @ initialise packet sequence @
RESULT := 0
END
; @ KMT_PH_REC_INIT @
SIM PROC KMT_PH_REC_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Look for a file header or EOT message @
RESULT := 0 @ nothing to do on entry to Rec_File state @
; @ KMT_PH_REC_FILE @
SIM PROC KMT_PH_REC_DATA IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Receive data up to end of file @
RESULT := 0 @ nothing to do on entry to Rec_Data state @
; @ KMT_PH_REC_DATA @
SIM PROC KMT_PH_SEND_INIT IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Server Send Init, also entry for non-server SEND command @
BEGIN
PKT_SEQ := 0; @ initialise packet sequence @
IF KMT_CURRENT_MODE NE SERVER_MODE AND RETRY_COUNT LE 1
THEN @ wait for user to set up remote KERMIT @
INT KMT_EH_SOFTWARE_ERROR IS 80101;
INT X_TYPE,X_NO;
DELAY_TIMER := TRUE; @ set delay timer @
KMT_PP_GET_PACKET(X_TYPE,X_NO,RESULT);@ attempt to read packet @
@ if we get a packet then they're ready to receive @
@ if the timer expires then we send regardless @
DELAY_TIMER := FALSE;
UNLESS RESULT = KMT_EH_SOFTWARE_ERROR
DO
RESULT := 0
FI
ELSE
RESULT := 0
FI;
IF RESULT = 0
THEN
KMT_PP_BUILD_PARAM_PACKET_DATA(); @ send S(0) with parameters @
KMT_PP_SEND_PACKET(SEND_INIT_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
FI
END
; @ KMT_PH_SEND_INIT @
SIM PROC KMT_PH_SEND_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Send file or text header (we don't send text packets!) @
BEGIN @ send F(n) - packet made by KMT_PH_READY_FILE @
KMT_PP_SEND_PACKET(FILE_HDR_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
END
; @ KMT_PH_SEND_FILE @
SIM PROC KMT_PH_SEND_DATA IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Send contents of file or textual information @
@ (we don't send text packets!) @
BEGIN @ send D(n) with current buffer (pkt made by KMT_PH_READY_DATA) @
KMT_PP_SEND_PACKET(DATA_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
END
; @ KMT_PH_SEND_DATA @
SIM PROC KMT_PH_SEND_EOF IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Send end of file indicator (we don't do interrupts) @
BEGIN
KMT_VME_FILE := NIL; @ file has been closed @
KMT_REM_FILE := NIL;
@ send Z(n) - packet made by KMT_PH_READY_DATA @
KMT_PP_SEND_PACKET(EOF_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
END
; @ KMT_PH_SEND_EOF @
SIM PROC KMT_PH_SEND_BREAK IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ End of Transmission @
BEGIN @ send B(n) - packet made by KMT_PH_SENT_FILE @
KMT_PP_SEND_PACKET(BREAK_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
END
; @ KMT_PH_SEND_BREAK @
@ procedures for expected packets @
SIM PROC KMT_PH_INIT_PARAMS IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ A Send_Init or Init packet has arrived. If the packet sequence is @
@ correct, process their parameters and ack with our parameters. @
@ If it's a repeat of their last packet, ack it again with our @
@ parameters. Otherwise, report error and in non-Server modes, abort @
IF (STATE = REC_SERVER_IDLE OR STATE = REC_INIT) AND PKT_NO = 0
THEN @ got right packet, reset retry count @
RETRY_COUNT := 0;
KMT_PP_PROCESS_PARAM_PACKET_DATA(RESULT);
IF RESULT = 0
THEN
KMT_PP_BUILD_PARAM_PACKET_DATA();
KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI;
IF RESULT = 0 AND EVENT = SEND_INIT_PKT
THEN @ increment packet sequence @
PKT_SEQ := PKT_SEQ+1 MOD 64;
STATE := REC_FILE
FI
ELSE @ their params unacceptable @
RESULT := 89070
FI
ELSF STATE = REC_FILE AND PKT_NO+1 MOD 64 = PKT_SEQ @ i.e. P = N-1 @
THEN @ we've picked up their Send_init again, so send ack @
KMT_PP_BUILD_PARAM_PACKET_DATA();
KMT_PP_SEND_PACKET(ACK_PKT,PKT_NO,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
ELSE @ wrong packet sequence, error (abort if non-server) @
RESULT := 89000
FI
; @ KMT_PH_INIT_PARAMS @
SIM PROC KMT_PH_GEN_CMD IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Generic command received - some are implemented and will be @
@ executed and acknowledged - an error packet is sent for the rest @
IF PKT_NO = 0
THEN
BYTE GEN_CMD;
KMT_PP_TRANSLATE_TO_EBCDIC();
GEN_CMD := PKT_DATA(0);
RETRY_COUNT := 0; @ got right packet, reset retry count @
@ check if Generic Command implemented @
IF GEN_CMD = "F" OR GEN_CMD = "L"
THEN @ GF (Finish command): exit Server mode and terminate @
@ GL (Logout command): exit Server mode and log out @
EXIT_STATE := IF GEN_CMD = "F" THEN EXIT ELSE LOGOUT FI;
STATE := COMPLETE;
@ Generic Command successful, ack it @
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
ELSE @ this Generic Command not implemented (or doesn't exist) @
RESULT := 89011
FI
ELSE @ wrong packet number, wait for their next try @
RESULT := 89000
FI
; @ KMT_PH_GEN_CMD @
SIM PROC KMT_PH_KMT_CMD IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Packet contains Kermit command, pass it to user interface (KMT_UI) @
@ for processing @
IF PKT_NO = 0
THEN
RETRY_COUNT := 0; @ got right packet, reset retry count @
@ pass command (in packet) to KMT_UI @
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_TRANSLATE_TO_EBCDIC();
KMT_UI(RESULT);
IF RESULT = 0
THEN @ command has been executed successfully so ack it @
@ if there is a reply, KMT_UI has put it into packet @
KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
FI
ELSE @ wrong packet number, wait for their next try @
RESULT := 89000
FI
; @ KMT_PH_KMT_CMD @
SIM PROC KMT_PH_GOT_FILENAME IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Packet contains name of file to be sent @
IF PKT_NO = 0
THEN @ got right packet, reset retry count @
RETRY_COUNT := 0;
KMT_PP_TRANSLATE_TO_EBCDIC();
KMT_VME_FILE := KMT_SP_GET_WORD(PKT_DATA); @ obtain filename @
IF NOT (KMT_VME_FILE REF NIL) @ must be present @
THEN
KMT_VME_FILE :=
KMT_VME_FILE_BUF(SIZE LENGTH KMT_VME_FILE) :=
KMT_VME_FILE;
STATE := SEND_INIT;
RESULT := 0
ELSE @ no filename, error and abort @
RESULT := 89030
FI
ELSE @ wrong packet number, wait for their next try @
RESULT := 89000
FI
; @ KMT_PH_GOT_FILENAME @
SIM PROC KMT_PH_BREAK IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ End of Transmission received @
IF PKT_NO = PKT_SEQ
THEN @ correct sequence, ack it and complete @
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,NO_READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI;
STATE := COMPLETE
ELSE @ wrong packet sequence, error abort @
RESULT := 89000
FI
; @ KMT_PH_BREAK @
SIM PROC KMT_PH_FILE_HDR IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Packet contains name of file to be received @
IF PKT_NO = PKT_SEQ
THEN @ obtain filename (may have been specified in Receive command)@
KMT_PP_TRANSLATE_TO_EBCDIC();
IF KMT_VME_FILE REF NIL
THEN @ not already set @
KMT_VME_FILE := KMT_SP_GET_WORD(PKT_DATA);
IF KMT_VME_FILE REF NIL
THEN
RESULT := 80931
ELSE
KMT_VME_FILE :=
KMT_VME_FILE_BUF(SIZE LENGTH KMT_VME_FILE) :=
KMT_VME_FILE;
RESULT := 0
FI
ELSE @ already set but verify packet contains filename @
KMT_REM_FILE := KMT_SP_GET_WORD(PKT_DATA);
RESULT := IF KMT_REM_FILE REF NIL THEN 80931 ELSE 0 FI
FI;
IF RESULT = 0
THEN @ open file @
KMT_REM_FILE := @ save copy of VME filename @
KMT_REM_FILE_BUF(SIZE LENGTH KMT_VME_FILE) :=
KMT_VME_FILE;
@ assume filename is name.type, remove type @
KMT_SP_STANDARDISE_FILENAME(KMT_VME_FILE,VME_STD);
KMT_FH_OPEN_FILE(KMT_VME_FILE,FILE_OPTION,RESULT);
IF RESULT <= 0
THEN @ file open, log full name @
INT NAME_LENGTH;
RESULT := 0;
KMT_FH_GIVE_NAME(KMT_VME_FILE_BUF,NAME_LENGTH,TRUE,RESULT);
IF RESULT <= 0
THEN @ set VME filename to full name @
RESULT := 0;
KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE NAME_LENGTH);
KMT_MTM_AREA(3) := KMT_REM_FILE AS
KMT_MTUP_VALUES.RVB_VALUE;
KMT_MTM_AREA(4) := KMT_VME_FILE AS
KMT_MTUP_VALUES.RVB_VALUE;
KMT_MESSAGE(-87002,RC_IGNORED); @ log filename @
@ ack file header including VME filename @
KMT_PP_BUILD_STRING_PACKET_DATA(KMT_VME_FILE,
RC_IGNORED);
KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT);
IF RESULT <= 0
THEN
PKT_SEQ := PKT_SEQ+1 MOD 64;
RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1);
RETRY_COUNT := 0;
STATE := REC_DATA;
RESULT := 0
ELSE
RESULT := -89061
FI
FI
ELSE @ unable to open file, reset result and abort @
RESULT := 89040
FI
FI
ELSE @ wrong packet number, abort @
RESULT := 89000
FI
; @ KMT_PH_FILE_HDR @
SIM PROC KMT_PH_GOT_DATA IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Received data packet @
IF PKT_NO = PKT_SEQ
THEN @ write data to file @
KMT_PP_BUILD_FILE_RECORD(RESULT);
IF RESULT <= 0
THEN @ ack data packet @
RESULT := 0;
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT);
IF RESULT <= 0
THEN
PKT_SEQ := PKT_SEQ+1 MOD 64;
RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1);
RETRY_COUNT := 0;
RESULT := 0
ELSE
RESULT := -89061
FI
ELSE @ error writing data to file, abort @
RESULT := 89046
FI
ELSF PKT_NO+1 MOD 64 = PKT_SEQ @ i.e. P = N-1 @
THEN @ we've picked up their last data packet again, so ack it @
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_SEND_PACKET(ACK_PKT,PKT_NO,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
ELSE @ wrong packet number, error abort @
RESULT := 89000
FI
; @ KMT_PH_GOT_DATA @
SIM PROC KMT_PH_GOT_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ End of file packet received @
IF PKT_NO = PKT_SEQ
THEN
KMT_PP_TRANSLATE_TO_EBCDIC();
KMT_FH_CLOSE_FILE(RESULT); @ close file we've just rec'd @
RESULT := IF RESULT <= 0
THEN 0 @ ignore -ve warning code @
ELSE 89042 @ error closing file, abort @
FI;
IF (RESULT = 0 OR SAVE_INCOMPLETE_FILE)
AND (LENGTH PKT_DATA = 0 OR PKT_DATA(0) NE "D")
THEN @ no discard signal in packet so save file @
INT RC;
KMT_FH_SAVE_FILE(RC);
IF RC > 0
THEN RESULT := 89044 @ error saving file, abort @
FI
FI;
IF RESULT = 0
THEN
KMT_VME_FILE := NIL;
KMT_REM_FILE := NIL;
@ no problems closing file, so ack eof @
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_SEND_PACKET(ACK_PKT,PKT_SEQ,READ_INT,RESULT);
IF RESULT <= 0
THEN
PKT_SEQ := PKT_SEQ+1 MOD 64;
RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1);
RETRY_COUNT := 0;
STATE := REC_FILE;
RESULT := 0
ELSE
RESULT := -89061
FI
FI
ELSE @ wrong packet number, abort @
RESULT := 89000
FI
; @ KMT_PH_GOT_FILE @
SIM PROC KMT_PH_READY_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Send Init has been acknowledged, open file for transfer @
IF PKT_NO = 0
THEN
KMT_PP_PROCESS_PARAM_PACKET_DATA(RESULT);
IF RESULT = 0
THEN @ open file in READ mode @
@ assume filename is name.type, remove type @
KMT_SP_STANDARDISE_FILENAME(KMT_VME_FILE,VME_STD);
KMT_FH_OPEN_FILE(KMT_VME_FILE,0,RESULT);
IF RESULT <= 0
THEN @ set up filename for file hdr packet @
INT NAME_LENGTH;
RESULT := 0;
KMT_FH_GIVE_NAME(KMT_VME_FILE_BUF,NAME_LENGTH,TRUE,RESULT);
IF RESULT <= 0
THEN
KMT_VME_FILE := KMT_VME_FILE_BUF(SIZE NAME_LENGTH);
IF KMT_REM_FILE REF NIL
THEN @ set remote filename to VME terminal name @
KMT_REM_FILE :=
KMT_REM_FILE_BUF(SIZE NAME_LENGTH) :=
KMT_VME_FILE;
KMT_SP_STANDARDISE_FILENAME(KMT_REM_FILE,VME_TERM)
ELSE @ set remote filename to Kermit Normal-Form @
KMT_SP_STANDARDISE_FILENAME(KMT_REM_FILE,KMT_STD)
FI;
@ log filenames @
KMT_MTM_AREA(3) :=
KMT_VME_FILE AS KMT_MTUP_VALUES.RVB_VALUE;
KMT_MTM_AREA(4) :=
KMT_REM_FILE AS KMT_MTUP_VALUES.RVB_VALUE;
KMT_MESSAGE(-87003,RC_IGNORED);
@ put filename in file header packet @
KMT_PP_BUILD_STRING_PACKET_DATA(KMT_REM_FILE,RC_IGNORED);
PKT_SEQ := PKT_SEQ+1 MOD 64;
RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1);
RETRY_COUNT := 0;
STATE := SEND_FILE;
RESULT := 0
FI
ELSE @ unable to open file, reset result and abort @
RESULT := 89041
FI
ELSE @ their params unacceptable @
RESULT := 89070
FI
FI
; @ KMT_PH_READY_FILE @
SIM PROC KMT_PH_READY_DATA IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Get data ready for transfer @
IF (EVENT = ACK_PKT AND PKT_NO = PKT_SEQ)
OR (EVENT = NAK_PKT AND PKT_NO = PKT_SEQ+1 MOD 64)
THEN
PKT_SEQ := PKT_SEQ+1 MOD 64;
RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1);
RETRY_COUNT := 0;
KMT_PP_TRANSLATE_TO_EBCDIC();
IF (LENGTH PKT_DATA = 1 AND STATE = SEND_DATA)
AND (PKT_DATA(0) = "X" OR PKT_DATA(0) = "Z")
THEN @ their ack packet requested interrupt transfer @
KMT_FH_CLOSE_FILE(RESULT); @ closing file shouldn't fail @
RESULT := IF RESULT <= 0 THEN 0 ELSE 89043 FI;
KMT_MESSAGE(-87000,RC_IGNORED); @ log cancellation of xfer @
@ set up eof packet data @
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
STATE := SEND_EOF
ELSE @ check for ack of file header, it may have filename @
IF STATE = SEND_FILE @ used by remote Kermit, if so log it @
THEN
STATE := SEND_DATA;
KMT_MTM_AREA(3) :=
KMT_VME_FILE AS KMT_MTUP_VALUES.RVB_VALUE;
IF LENGTH PKT_DATA > 0
THEN
KMT_MTM_AREA(4) :=
PKT_DATA AS KMT_MTUP_VALUES.RVB_VALUE
ELSE
KMT_MTM_AREA(4) :=
KMT_REM_FILE AS KMT_MTUP_VALUES.RVB_VALUE
FI;
KMT_MESSAGE(-87001,RC_IGNORED)
FI;
@ set up next data packet @
KMT_PP_BUILD_FILE_PACKET_DATA(RESULT);
IF RESULT = EOF
THEN @ all data sent, close file and send eof next @
KMT_FH_CLOSE_FILE(RESULT); @ shouldn't fail @
RESULT := IF RESULT <= 0 THEN 0 ELSE 89043 FI;
STATE := SEND_EOF @ all data sent @
ELSE @ error reading from file? @
RESULT := IF RESULT <= 0 THEN 0 ELSE 89047 FI
FI
FI
ELSE
RESULT := 0
FI
; @ KMT_PH_MAKE_DATA @
SIM PROC KMT_PH_SENT_FILE IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ File sent, check ack @
BEGIN
IF (EVENT = ACK_PKT AND PKT_NO = PKT_SEQ)
OR (EVENT = NAK_PKT AND PKT_NO = PKT_SEQ+1 MOD 64)
THEN @ any more files? no - we only allow 1 per send so: @
PKT_SEQ := PKT_SEQ+1 MOD 64;
RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1);
RETRY_COUNT := 0;
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED); @ set up break @
STATE := SEND_BREAK @ packet data @
@ (ditto if previous pkt_data(0) was "Z") @
FI;
RESULT := 0
END
; @ KMT_PH_SENT_FILE @
SIM PROC KMT_PH_SEND_DONE IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Break sent, check ack @
BEGIN
IF EVENT = ACK_PKT
THEN
IF PKT_NO = PKT_SEQ
THEN
STATE := COMPLETE
FI
ELSF PKT_NO = PKT_SEQ+1 MOD 64 OR PKT_NO = 0
THEN @ they've sent nak(n+1) or nak(0) @
STATE := COMPLETE
FI;
RESULT := 0
END
; @ KMT_PH_SEND_DONE @
@ procedures for unexpected packets @
SIM PROC KMT_PH_REPORT_ERR IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ unexpected pkt type, send error pkt and remain in same state @
RESULT := 89000
; @ KMT_PH_REPORT_ERR @
SIM PROC KMT_PH_GOT_ERROR IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ they've reported an error to us, log error message and abort @
BEGIN @ decode packet data and set up message text area for logging @
KMT_PP_TRANSLATE_TO_EBCDIC();
KMT_MTM_AREA(3) := PKT_DATA AS KMT_MTUP_VALUES.RVB_VALUE;
RESULT := -87010
END
; @ KMT_PH_GOT_ERROR @
SIM PROC KMT_PH_SEND_NAK IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ send nak packet @
BEGIN
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_SEND_PACKET(NAK_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
END
; @ KMT_PH_SEND_NAK @
SIM PROC KMT_PH_NAK_ABORT IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Send NAK and abort @
BEGIN
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_SEND_PACKET(NAK_PKT,PKT_SEQ,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI;
STATE := ABORT
END
; @ KMT_PH_NAK_ABORT @
SIM PROC KMT_PH_ACK_LAST IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ if current packet is repeat of last packet then send ack @
IF PKT_NO+1 MOD 64 = PKT_SEQ @ i.e. P = N-1 @
THEN
KMT_PP_BUILD_STRING_PACKET_DATA(NIL,RC_IGNORED);
KMT_PP_SEND_PACKET(ACK_PKT,PKT_NO,READ_INT,RESULT);
RESULT := IF RESULT <= 0 THEN 0 ELSE -89061 FI
ELSE @ wrong packet sequence, error abort @
RESULT := 89000
FI
; @ KMT_PH_ACK_LAST @
SIM PROC KMT_PH_ERR_ABORT IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Send error packet and abort @
RESULT := 89001
; @ KMT_PH_ERR_ABORT @
SIM PROC KMT_PH_SEND_IDLE IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ the wrong type of packet (or a bad packet) has arrived while @
@ sending a file - in this case it doesn't matter @
RESULT := 0
; @ KMT_PH_SEND_IDLE @
SIM PROC KMT_PH_SET_ABORT IS GROUP KMT_PH_GRP (RESPONSE RESULT):
@ Set ABORT state @
BEGIN
STATE := ABORT;
RESULT := 0
END
; @ KMT_PH_SET_ABORT @
@ protocol handler state event table @
(9)(15)SIM PROC GROUP KMT_PH_GRP(RESPONSE) KMT_PH_ACTION IS
((KMT_PH_REC_SERVER_IDLE , KMT_PH_REPORT_ERR , KMT_PH_REPORT_ERR ,
KMT_PH_GOT_ERROR , KMT_PH_REPORT_ERR , KMT_PH_GEN_CMD ,
KMT_PH_INIT_PARAMS , KMT_PH_KMT_CMD , KMT_PH_REPORT_ERR ,
KMT_PH_GOT_FILENAME , KMT_PH_INIT_PARAMS , KMT_PH_REPORT_ERR ,
KMT_PH_REPORT_ERR , KMT_PH_SEND_NAK , KMT_PH_REPORT_ERR),
(KMT_PH_REC_INIT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT ,
KMT_PH_GOT_ERROR , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT ,
KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT ,
KMT_PH_NAK_ABORT , KMT_PH_INIT_PARAMS , KMT_PH_NAK_ABORT ,
KMT_PH_NAK_ABORT , KMT_PH_SEND_NAK , KMT_PH_NAK_ABORT ),
(KMT_PH_REC_FILE , KMT_PH_BREAK , KMT_PH_NAK_ABORT ,
KMT_PH_GOT_ERROR , KMT_PH_FILE_HDR , KMT_PH_NAK_ABORT ,
KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT , KMT_PH_NAK_ABORT ,
KMT_PH_NAK_ABORT , KMT_PH_INIT_PARAMS , KMT_PH_NAK_ABORT ,
KMT_PH_ACK_LAST , KMT_PH_SEND_NAK , KMT_PH_NAK_ABORT ),
(KMT_PH_REC_DATA , KMT_PH_ERR_ABORT , KMT_PH_GOT_DATA ,
KMT_PH_GOT_ERROR , KMT_PH_ACK_LAST , KMT_PH_ERR_ABORT ,
KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT ,
KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT , KMT_PH_ERR_ABORT ,
KMT_PH_GOT_FILE , KMT_PH_SEND_NAK , KMT_PH_ERR_ABORT ),
(KMT_PH_SEND_INIT , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE ,
KMT_PH_GOT_ERROR , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE ,
KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE ,
KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_READY_FILE ,
KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE , KMT_PH_SEND_IDLE ),
(KMT_PH_SEND_FILE , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT ,
KMT_PH_GOT_ERROR , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT ,
KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_READY_DATA ,
KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_READY_DATA ,
KMT_PH_SET_ABORT , KMT_PH_SEND_IDLE , KMT_PH_SET_ABORT ),
(KMT_PH_SEND_DATA , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT ,
KMT_PH_GOT_ERROR , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT ,
KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_READY_DATA ,
KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_READY_DATA ,
KMT_PH_SET_ABORT , KMT_PH_SEND_IDLE , KMT_PH_SET_ABORT ),
(KMT_PH_SEND_EOF , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT ,
KMT_PH_GOT_ERROR , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT ,
KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SENT_FILE ,
KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SENT_FILE ,
KMT_PH_SET_ABORT , KMT_PH_SEND_IDLE , KMT_PH_SET_ABORT ),
(KMT_PH_SEND_BREAK , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT ,
KMT_PH_GOT_ERROR , KMT_PH_SET_ABORT , KMT_PH_SET_ABORT ,
KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SEND_DONE ,
KMT_PH_SET_ABORT , KMT_PH_SET_ABORT , KMT_PH_SEND_DONE ,
KMT_PH_SET_ABORT , KMT_PH_SEND_IDLE , KMT_PH_SET_ABORT ));
@ PROTOCOL HANDLER @
IF KMT_TRACE_FLAGS.PH_TRACING
THEN
() KMT_MTUP_VALUES PARAMS := (STATE AS KMT_MTUP_VALUES.RI_VALUE,
(L'EVENT) AS KMT_MTUP_VALUES.LI_VALUE);
KMT_SP_LOG_TRACE_MESSAGE(300,PARAMS)
FI;
IF EVENT = ENTRY
THEN @ increment retry count and test against maximum @
RETRY_COUNT := RETRY_COUNT+1;
IF RETRY_COUNT > MAXTRY
THEN
RETRY_TOTAL := RETRY_TOTAL + (RETRY_COUNT - 1);
RESULT := 89050
ELSE
KMT_PH_ACTION(STATE,EVENT)(RESULT)
FI
ELSE
KMT_PH_ACTION(STATE,EVENT)(RESULT)
FI;
IF RESULT NE 0
THEN
IF RESULT = -89061
THEN @ unable to send packet - fatal error @
STATE := ABORT;
EXIT_STATE := FATAL_ERROR
ELSF (RESULT NE 89000) OR (STATE NE REC_SERVER_IDLE)
THEN @ abort unless wrong seq no in Rec_Server_Idle state @
STATE := ABORT
FI
FI
END
; @ KMT_PH @
ENDMODULE @ KMT_PH_MODULE @