separate (NETWORK_PROTOCOLS.KERMIT_PROTOCOL) package body SEND_UTILITIES is use KERMIT_GLOBALS; procedure SEND_INITIALIZATION(CURRENT_SEQUENCE : in out INTEGER) is -- send the S packet DATA_STRING : BYTE_STRING (1..NUM_FEATURES); SI_PACKET : PACKET_TYPE; RESPONSE_PACKET : PACKET_TYPE; COMPATIBLE : BOOLEAN := TRUE; begin -- the default values are in k_constants DATA_STRING(1) := DEFAULT_MAXL; DATA_STRING(2) := DEFAULT_TIME; DATA_STRING(3) := DEFAULT_NPAD; DATA_STRING(4) := DEFAULT_PADC; DATA_STRING(5) := DEFAULT_EOL; DATA_STRING(6) := DEFAULT_QCTL; DATA_STRING(7) := QBIN_REQUEST; CREATE_PACKET(SI_PACKET, S_PACKET, DATA_STRING, NUM_FEATURES, CURRENT_SEQUENCE); -- send_packet will handle waiting, retrying and resending. If no -- ack is ever returned, it raises an error SEND_PACKET(SI_PACKET, CURRENT_SEQUENCE, RESPONSE_PACKET); if RESPONSE_PACKET.KTYPE = E_PACKET then PRINT_ERROR_MSG(RESPONSE_PACKET); raise ERROR_RECEIVED; elsif RESPONSE_PACKET.SEQ /= BYTE'VAL(CURRENT_SEQUENCE) or else RESPONSE_PACKET.KTYPE /= Y_PACKET then -- NAKS are allowed, but are handled by SEND_PACKET raise UNEXPECTED_PACKET; end if; CHECK_SI_RESPONSE(RESPONSE_PACKET, COMPATIBLE); -- check features if not COMPATIBLE then raise INCOMPATIBLE_KERMITS; end if; CURRENT_SEQUENCE := (CURRENT_SEQUENCE + 1) mod 64; exception when others => raise FILE_TRANSFER_ERROR; end SEND_INITIALIZATION; procedure SEND_FILE_HEADER(CURRENT_SEQUENCE : in out INTEGER) is -- send the F packet, after obtaining file name DATA_STRING : BYTE_STRING (1..MAX_LENGTH-3) := (1..MAX_LENGTH-3 => SP); PACKET_TO_SEND : PACKET_TYPE; RESPONSE_PACKET : PACKET_TYPE; NAME_OF_FILE : STRING(1..255) := (others => ' '); NAME_LEN : INTEGER; begin NAME_LEN := NAME_OF_FILE_BEING_TRANSFERRED'LENGTH; if NAME_LEN > MAX_LENGTH - 3 then raise FILE_NAME_ERROR; end if; -- if here, should be able to send the file name NAME_OF_FILE(1..NAME_LEN) := NAME_OF_FILE_BEING_TRANSFERRED; for I in 1..NAME_LEN loop DATA_STRING(I) := BYTE'VAL(CHARACTER'POS(NAME_OF_FILE(I))); end loop; CREATE_PACKET(PACKET_TO_SEND, F_PACKET, DATA_STRING, NAME_LEN, CURRENT_SEQUENCE); SEND_PACKET(PACKET_TO_SEND, CURRENT_SEQUENCE, RESPONSE_PACKET); if RESPONSE_PACKET.KTYPE = E_PACKET then PRINT_ERROR_MSG(RESPONSE_PACKET); raise ERROR_RECEIVED; elsif RESPONSE_PACKET.SEQ /= BYTE'VAL(CURRENT_SEQUENCE) or else RESPONSE_PACKET.KTYPE /= Y_PACKET then -- NAKS are allowed, but are handled by SEND_PACKET raise UNEXPECTED_PACKET; else CURRENT_SEQUENCE := (CURRENT_SEQUENCE + 1) mod 64; end if; exception when others => raise FILE_TRANSFER_ERROR; end SEND_FILE_HEADER; procedure SEND_DATA(CURRENT_SEQUENCE : in out INTEGER) is -- send data packets. AT_END : BOOLEAN := FALSE; PACKET_TO_SEND : PACKET_TYPE; RESPONSE_PACKET : PACKET_TYPE; DATA_STRING: BYTE_STRING (1..MAX_LENGTH-3) := (1..MAX_LENGTH-3 => SP); DSLEN : INTEGER := 0; PREVIOUS_SEQ: INTEGER := CURRENT_SEQUENCE - 1; CHAR_BUFFER : BYTE := SP ; -- used to save char that won't fit in packet IS_CHAR_IN_BUFFER : BOOLEAN := FALSE; DONE : BOOLEAN := FALSE; begin while not DONE loop -- get data from file NEXT_DATA(DATA_STRING, DSLEN, AT_END, CHAR_BUFFER, IS_CHAR_IN_BUFFER); DONE := (AT_END and (DSLEN = 0)); -- just in case file is empty exit when DONE; CREATE_PACKET(PACKET_TO_SEND, D_PACKET, DATA_STRING, DSLEN, CURRENT_SEQUENCE); SEND_PACKET(PACKET_TO_SEND, CURRENT_SEQUENCE, RESPONSE_PACKET); if RESPONSE_PACKET.KTYPE = E_PACKET then PRINT_ERROR_MSG(RESPONSE_PACKET); raise ERROR_RECEIVED; elsif RESPONSE_PACKET.SEQ /= BYTE'VAL(CURRENT_SEQUENCE) or else RESPONSE_PACKET.KTYPE /= Y_PACKET then -- NAKS are allowed, but are handled by SEND_PACKET raise UNEXPECTED_PACKET; elsif RESPONSE_PACKET.KTYPE = Y_PACKET and RESPONSE_PACKET.SEQ = BYTE'VAL(CURRENT_SEQUENCE) then CURRENT_SEQUENCE := (CURRENT_SEQUENCE + 1) mod 64 ; DONE := AT_END; -- if we've sent the last packet we are done end if; end loop; exception when others => raise FILE_TRANSFER_ERROR; end SEND_DATA; procedure SEND_END_OF_FILE(CURRENT_SEQUENCE : in out INTEGER) is -- send the Z packet and B packet DATA_STRING : BYTE_STRING(1..MAX_LENGTH-3) := (1..MAX_LENGTH-3 => SP); PACKET_TO_SEND : PACKET_TYPE; RESPONSE_PACKET : PACKET_TYPE; begin CREATE_PACKET(PACKET_TO_SEND, Z_PACKET, DATA_STRING, 0, CURRENT_SEQUENCE); SEND_PACKET(PACKET_TO_SEND, CURRENT_SEQUENCE, RESPONSE_PACKET); if RESPONSE_PACKET.KTYPE = E_PACKET then PRINT_ERROR_MSG(RESPONSE_PACKET); raise ERROR_RECEIVED; elsif RESPONSE_PACKET.SEQ /= BYTE'VAL(CURRENT_SEQUENCE) or else RESPONSE_PACKET.KTYPE /= Y_PACKET then -- NAKS are allowed, but are handled by SEND_PACKET raise UNEXPECTED_PACKET; end if; CURRENT_SEQUENCE := (CURRENT_SEQUENCE + 1) mod 64; CREATE_PACKET(PACKET_TO_SEND, B_PACKET, DATA_STRING, 0, CURRENT_SEQUENCE); SEND_PACKET(PACKET_TO_SEND, CURRENT_SEQUENCE, RESPONSE_PACKET); -- go ahead and send b packet twice, to try to avoid the irritating case -- when the 2 kermits are one step out of sync. It won't matter if the -- other kermit did get our last B packet and we send another. Don't bother -- to send and wait though (which is what send_packet does); just send the -- B packet out there and go (using put_packet). delay 5.0; PUT_PACKET(PACKET_TO_SEND); if RESPONSE_PACKET.KTYPE = E_PACKET then PRINT_ERROR_MSG(RESPONSE_PACKET); raise ERROR_RECEIVED; elsif RESPONSE_PACKET.SEQ /= BYTE'VAL(CURRENT_SEQUENCE) or else RESPONSE_PACKET.KTYPE /= Y_PACKET then -- NAKS are allowed, but are handled by SEND_PACKET raise UNEXPECTED_PACKET; end if; CURRENT_SEQUENCE := (CURRENT_SEQUENCE + 1) mod 64; exception when others => raise FILE_TRANSFER_ERROR; end SEND_END_OF_FILE; end SEND_UTILITIES;