/* PROT_REC.C by Louis Guzik, 2061 Fall 1996 */ #include #include #include #include #include #include #include #include "serial.h" #include "protocol.h" /* ** Variables found in driver.c */ extern char *buffer_start; /* beginning of buffer */ extern char *buffer_end; /* end of the buffer */ extern char *buffer_in; /* pointer to next place to put character in */ extern char *buffer_out; /* place to get next character from */ extern int count; /* number of characters in buffer */ extern int max_count; /* max value of count */ /* ** Variables found in protocol.h */ extern int line_speed; extern int window_size; extern int packet_size; extern int timeout; /* ** My functions */ int receive_file( void ); int recv_packet( char char_ptr[] ); int fill_recv_window( void ); /* ** My gobal vars */ int total_bytes; int total_data_bytes; int total_pkts; int total_pkt_errs; int total_dup_pkts; int DEBUG; // FLAG FOR PRINTF TO DISPLAY VARABLES extern error_count; extern error_flag[TN_MSG_TYPES][TN_ERROR_TYPES]; // BUFFER FOR RECEIVED DATA PACKETS FROM THE SERIAL LINE WAITING TO BE PROCESSED char recv_window[ MAX_WINDOW_SIZE+2 ][ MAX_PACKET_SIZE+2 ]; char save_bcc[ MAX_WINDOW_SIZE+2]; /*******************************************************************/ int receive_file( void ) { int x=0; // ALL PROGRAMS HAVE A VARABLE X int i; // USED IN ARRARY TRAVERSING int j; // USED IN ARRARY TRAVERSING int OK; char bcc; // THE CALULATED BLOCK CHECK COUNT CHARACTER int done; // FLAG IF DONE IN RETRANSMISSION STATE int size; // THE SIZE, IN CHARACTER OF THE RECEIVED PACKET int status; // THE OUT COME OF THE LAST ACTION. POS=SUCCESFUL. NULL=UNSUCCESSFUL int seq_num; // THE CURRENT SEQUENCE NUMBER IN RECV_WINDOW BEING PROCESSED int len; // LENGTH OF THE RECEIVED PACKET int datalen; // LENGTH OF THE DATA FIELD OF THE RECEIVED PACKET int file_desc = 0; // THE FILE TO WRITE THE RECEIVED DATA TOO char ch = NULL; // KEYBOARD INPUT FROM USER char view = NULL; // FLAG FOR DISPLAY TO SCREEN OR WRITE TO FILE char ack_pkt[ 128 ]; // OUTGOING POS OR NEG ACK PACKET char init_pkt[ 128 ]; // INCOMING INITIALIZATION PACKET char filename_pkt[ 128 ]; // INCOMING FILE NAME PACKET char filename[ 16 ]; // THE FILE NAME STRING int EOF_pkt; // FLAG FOR THE EOF PACKED BEING RECEIVED CORRECTLY time_t start_time1, start_time2, end_time1, end_time2; // ZERO OUT COUNTERS FOR STATS total_bytes = 0; total_data_bytes = 0; total_pkts = 0; total_pkt_errs = 0; total_dup_pkts = 0; start_time1 = 0; start_time2 = 0; end_time1 = 0; end_time2 = 0; DEBUG = 0; // CLEAR OUT THE SERIAL LINE BECAUSE PROCESSING IS NOW STARTING count = 0; buffer_in = buffer_start; buffer_out = buffer_start; max_count = 0; // CLEAR THE RECV_WINDOW ARRAY for(i=0; i" ); ch = toupper( getche() ); if( ch == 'Y' ) DEBUG = TRUE; else DEBUG = FALSE; } while( view != 'S' && view != 'F' ) { printf( "\n Output receive file to S)creen or F)ile? ==>" ); view = toupper( getche() ); } printf("\n Output will be to"); if( view == 'S' ) printf( " Screen. \n" ); else printf( " File. " ); printf( "\n* RECV MODE * by Lou Guzik * Window Size: %d * Pkt Size: %d\n", window_size, packet_size ); /* ** Receive init frame */ status = 0; time( &start_time1 ); while( ! status ) { status = 0; size = recv_packet( init_pkt ); if( DEBUG ) { printf(">%d< ", size ); } /* USER PRESSED THE ESC KEY TO ABORT */ if( size == -1) { printf( "\nESC key pressed, Aborting !" ); goto leave; } total_pkts++; total_bytes += size; len = from_char(init_pkt[1])-3; bcc = calc_check_sum( &init_pkt[4], (char) len, init_pkt[2], init_pkt[3] ); init_pkt[1] = from_char( init_pkt[1] ); init_pkt[2] = from_char( init_pkt[2] ); init_pkt[4] = from_char( init_pkt[4] ); init_pkt[5] = from_char( init_pkt[5] ); init_pkt[6] = from_char( init_pkt[6] ); init_pkt[7] = from_char( init_pkt[7] ); if( bcc == init_pkt[ init_pkt[1]+1 ] ) { if( init_pkt[3] == 'I' ) // INIT PACKET { ack_pkt[3] = 'A'; status++; } else if( init_pkt[3] == 'F' ) // FATAL PACKET { printf( "\nRECV FATAL PACKET. ABORTING\n" ); goto leave; } else { ack_pkt[3] = 'N'; total_pkt_errs++; if( DEBUG ) { printf( "\nERROR GETTING INIT TYPE ->%d<-\n", init_pkt[3] ); } } } else { ack_pkt[3] = 'N'; total_pkt_errs++; if( DEBUG ) { printf( "\nERROR GETTING INIT BCC: %d \n", init_pkt[ init_pkt[1]+1 ] ); } } ack_pkt[0] = BEGIN_CHAR; ack_pkt[1] = to_char( 6 ); ack_pkt[2] = to_char( 0 ); ack_pkt[4] = to_char( init_pkt[4] ); ack_pkt[5] = to_char( init_pkt[5] ); ack_pkt[6] = to_char( init_pkt[6] ); ack_pkt[7] = to_char( calc_check_sum(&ack_pkt[4], from_char( ack_pkt[1]-3 ), ack_pkt[2], ack_pkt[3]) ); ack_pkt[8] = END_CHAR; if( error_flag[INIT_MSG_TYPE][CHECKSUM_ERROR] && (error_count < 5) ) { ack_pkt[7]++; error_count++; } if( error_flag[INIT_MSG_TYPE][TIMEOUT_ERROR] && (error_count < 5) ) { error_count++; } else { output_bytes( ack_pkt, 9 ); // size = 9 chars in a INIT ACK pkt } } /* ** END of Receive init frame */ /* ** Receive file header */ status = 0; while( ! status ) { status = 0; size = recv_packet( filename_pkt ); if( DEBUG ) { printf("->%d<- ", size ); } /* USER PRESSED THE ESC KEY TO ABORT */ if( size == -1) { printf( "\nESC key pressed, Aborting !" ); goto leave; } total_pkts++; total_bytes += size; len = from_char(filename_pkt[1]); datalen = from_char(filename_pkt[1])-3; bcc = calc_check_sum( &filename_pkt[4], (char) datalen, filename_pkt[2], filename_pkt[3] ); filename_pkt[1] = from_char( filename_pkt[1] ); // length filename_pkt[2] = from_char( filename_pkt[2] ); // seq # filename_pkt[len+1] = from_char( filename_pkt[len+1] ); // bcc if( bcc == filename_pkt[ len+1 ] ) { if( filename_pkt[3] == 'H' ) { if( view == 'F' ) { for(i=4; i%s<- Exists, Enter New file name ==>", filename ); gets( filename ); file_desc = open( filename, O_RDONLY ); } close( file_desc ); } ack_pkt[3] = 'A'; status++; } else if( init_pkt[3] == 'F' ) // FATAL PACKET { printf( "\nRECV FATAL PACKET. ABORTING" ); goto leave; } else { ack_pkt[3] = 'N'; total_pkt_errs++; if( DEBUG ) { printf( "\nERROR GETTING FILE HEADER TYPE ->%d<-\n", init_pkt[3] ); } } } else { ack_pkt[3] = 'N'; total_pkt_errs++; if( DEBUG ) { printf( "\nERROR GETTING FILE HEADER BCC: %d \n", filename_pkt[ filename_pkt[1]+1 ] ); } } ack_pkt[0] = BEGIN_CHAR; ack_pkt[1] = to_char( 4 ); ack_pkt[2] = to_char( 1 ); ack_pkt[4] = 'H'; ack_pkt[5] = to_char( calc_check_sum(&ack_pkt[4], 1, ack_pkt[2], ack_pkt[3]) ); ack_pkt[6] = END_CHAR; if( error_flag[HEADER_MSG_TYPE][CHECKSUM_ERROR] && (error_count < 5) ) { ack_pkt[5]++; error_count++; } if( error_flag[HEADER_MSG_TYPE][TIMEOUT_ERROR] && (error_count <5 ) ) { error_count++; } else { output_bytes( ack_pkt, 7 ); // size = 7 chars in a HEADER ACK pkt } } time( &end_time1 ); /* ** END of Receive file header */ /* ** Receive data packets */ if( view == 'F' ) { // OPEN THE FILE TO WRITE TOO OR DIE file_desc = open( filename, O_CREAT | O_TEXT, S_IWRITE ); if( file_desc == -1 ) { printf( "\n\n FATAL ERROR OPENING RECV FILE. EXITING !\n" ); goto leave; //exit(0); } } EOF_pkt = 0; seq_num = 0; status = 0; time( &start_time2 ); while( ! EOF_pkt ) // WHILE NOT AT END OF FILE { /* USER PRESSED THE ESC KEY TO ABORT */ if( kbhit() ) { ch = getche(); if( ch == ESC ) { printf( "\nESC key pressed, Aborting !" ); goto leave; } } // GET ALL PACKETS ON SERIAL LINE while( count ) { size = fill_recv_window(); /* USER PRESSED THE ESC KEY TO ABORT */ if( size == -1) { printf( "\nESC key pressed, Aborting !" ); goto leave; } } // while( count ) OK = TRUE; while( OK ) { /* USER PRESSED THE ESC KEY TO ABORT */ if( kbhit() ) { ch = getche(); if( ch == ESC ) { printf( "\nESC key pressed, Aborting !" ); goto leave; } } if( recv_window[seq_num][0] == 0 ) { // NO PACKET TO PROCESS OK = FALSE; status = 0; if( DEBUG ) { // printf( "\nNO DATA PACKET TO PROCESS SEQ#: %d \n", seq_num ); // sleep( 2 ); } } else // PROCESS GOOD BCC PACKET. { if( recv_window[seq_num][3] == 'D' ) { // DATA PACKET OK = TRUE; status = 1; ack_pkt[4] = 'D'; done = from_char( recv_window[seq_num][1] ) + 1; if(done > packet_size ) done = packet_size; if( DEBUG ) { printf( "\nPROCESSING DATA PACKET SEQ#: %d LEN:%d \n", seq_num, done ); // sleep( 2 ); } if( view == 'S' ) { for(i=4; i 0 ) close( file_desc ); // CLEAR OUT THE SERIAL LINE BECAUSE PROCESSING IS DONE count = 0; buffer_in = buffer_start; buffer_out = buffer_start; // PRINT OUT STATISTICS printf( "\n" ); printf( "\n process init and header time: %d", end_time1 - start_time1 ); printf( "\n process data time: %d", end_time2 - start_time2 ); printf( "\n total processing time: %d", end_time2 - start_time1 ); printf( "\n\n total bytes received: %d", total_bytes ); printf( "\n total data bytes recv: %d", total_data_bytes ); printf( "\n total overhead bytes recv: %d", total_bytes-total_data_bytes ); printf( "\n\n total pkts received: %d", total_pkts ); printf( "\n total pkts with errors: %d", total_pkt_errs ); printf( "\n total dup. pkts: %d", total_dup_pkts ); printf( "\n\n transfer rate (bytes/sec): "); if( end_time2 == 0 || start_time2 == 0) printf( "0" ); else printf( "%d", total_data_bytes/(end_time2-start_time2) ); printf( "\n\n serial buffer max count: %d", max_count); printf( "\n final recv status: %d ", status ); printf("\n\n Press any key to continue. "); while( ! kbhit() ) ; ch = getche(); return( status ); } /* int recv_file( void ) */ /*******************************************************************/ int fill_recv_window( void ) { int j; int pkt_size; char data_pkt[ MAX_PACKET_SIZE+2 ]; int len; int bcc; int datalen; int bcc_ck; int seq_ck; char type_ck; // FILL THE RECV_BUFFER WITH WINDOW_SIZE PACKETS pkt_size = recv_packet( data_pkt ); if( DEBUG ) { printf("-->%d<-- ", pkt_size ); } /* USER PRESSED THE ESC KEY TO ABORT */ if( pkt_size == -1) { return( pkt_size ); } total_pkts++; total_bytes += pkt_size; // STORE THE PACKET IN THE RECV_WINDOW IF GOOD BCC // char recv_window[MAX_WINDOW_SIZE][MAX_PACKET_SIZE] len = from_char(data_pkt[1]); datalen = len-3; type_ck = data_pkt[3]; if( type_ck == 'R' ) data_pkt[3] = 'D'; bcc = calc_check_sum( &data_pkt[4], (char) datalen, data_pkt[2], data_pkt[3] ); seq_ck = from_char( data_pkt[2] ); // seq # bcc_ck = from_char( data_pkt[len+1] ); // bcc if( bcc == bcc_ck ) { if( DEBUG ) { printf( "\nWRITING DATA PACKET SEQ_CK#: %d \n", seq_ck ); } if( recv_window[seq_ck][0] == 0 ) { if( (type_ck != 'R') || (save_bcc[seq_ck] != bcc_ck) ) { for( j=0; j 0 ) { char_ptr[0] = get_char_from_buffer(); if( DEBUG ) { printf( "%d ", (int) char_ptr[0]); } /* check for start char */ if( char_ptr[0] == BEGIN_CHAR ) done++; } } /* THE NEXT CHAR SHOULD BE THE LENGTH */ while( count == 0 ) { if( kbhit() ) { button = getche(); if( button == ESC ) { char_ptr[0] = NULL; return(-1); } } } char_ptr[1] = get_char_from_buffer(); if( DEBUG ) { printf( "%d ", (int) char_ptr[1]); } // CHECK FOR OUT OF BOUNDS PACKET SIZE if( from_char(char_ptr[1]) < 0 || from_char(char_ptr[1]) > packet_size ) { char_ptr[1] = to_char(packet_size) - 1; if( DEBUG ) { printf( "(CORRECTED%d) ", from_char( char_ptr[1]) ); } } stop_value = from_char( char_ptr[1] ); i = 2; done = 0; while( done < stop_value+1 ) { if( kbhit() ) { button = getche(); if( button == ESC ) { char_ptr[0] = NULL; return(-1); } } if( count > 0 ) { char_ptr[i] = get_char_from_buffer(); if( DEBUG ) { printf( "%d ", (int) char_ptr[i]); } if( char_ptr[i] == END_CHAR ) done = stop_value+1; i++; done++; } } /* return number of chars in packet */ return( i ); } // int recv_packet( char char_ptr[] ) /*******************************************************************/ /* END OF FILE - PROT_REC.C */