// // File name: tcpstream.C // // This file is written by Ee-Chien Chang. // #include // #include // for cout #include #include #include // for send() close() #include #include #include "tcpstream.h" //--------------- L Z R W h e a d e r ----------------- extern "C" int lzrw1_compress ( unsigned char *, long, unsigned char*, long *); extern "C" int lzrw1_decompress ( unsigned char *, long, unsigned char*, long *); //--------------- G Z I P h e a d e r ------------------- #include "zlib.h" //extern "C" // int recv ( int, char *, int ,int ); // //============================================================ // T C P _ S T R E A M //------------------------------------------------------------ // // maintain a iostream. // // include lossless compression //------------------------------------------------------------ // // //-------------- I M P O R T A N T ------------------------ // 1) POSSIBILITY for improvment? // reserve a large buffer size // 2) break the input/output stream into small pieces. //--------------------------------------------------------- //-------------------------------------------------------- // w r i t e i n t //-------------------------------------------------------- // write a four byte integer // // b_0, b_1, b_2, b_3 // // suppose we send b_0, follow by b_1, b_2, b_3. // This correspond to the value // // b_0 << 24 | b_1 << 16 | b_2 << 8 | b_3 //--------------------------------------------------------- // N O T E // * no negative value. // should be ok, but i have not test it yet // * not an efficient implementation, as we don't // need this very oftan. //--------------------------------------------------------- // return 0 if fail else return 1 //--------------------------------------------------------- int tcp_Stream::write_int ( int value ) { unsigned char b [4]; b[3] = (value ) & 0xff; b[2] = (value >> 8) & 0xff; b[1] = (value >>16) & 0xff; b[0] = (value >>24) & 0xff; total_byte_write += 4; // cout << "................ TCP : sending integer " << value << endl; if ( send(stream_fd, (char *)b, 4,0) !=4 ) { cout << "Error (write_int ): number not tally" << endl; return 0; } else return 1; } int tcp_Stream::write_integers ( int * a, long total ) { int total_byte = total *4; unsigned char b[ total_byte ]; total_byte_write += total_byte; int curr =0; for (int i = 0; i< total_byte; i++) { b[curr++] = ( a[i] >>24) & 0xff; b[curr++] = ( a[i] >>16) & 0xff; b[curr++] = ( a[i] >> 8) & 0xff; b[curr++] = ( a[i] ) & 0xff; } if ( send ( stream_fd, ( char * ) b, total_byte,0 ) != total_byte ) { cout << " write_integers:: Error " << endl; return 0; } else { return 1; } } int tcp_Stream::read_int ( int *value ) { unsigned char b[4]; total_byte_read +=4; int curr = 0; while ( curr <4 ) { int tmp = recv ( stream_fd, (char *)&b[curr], 4-curr, 0 ) ; if (tmp <0) { cout << "Error (read_int ):" << endl; return 0; } curr += tmp; } *value = ( b[0] << 24 ) | ( b[1] << 16 ) | ( b[2] << 8 ) | ( b[3] ) ; return 1; } int tcp_Stream:: read_integers ( int *value, long nos_int ) { long nos_byte = nos_int *4; unsigned char b[ nos_byte]; int curr =0; total_byte_read += nos_byte; while ( curr < nos_byte ) { int tmp = recv ( stream_fd, (char *)&b[curr], nos_byte-curr,0 ); curr += tmp; if (tmp <0) { cout << "Error (read_int ):" << endl; return 0; } } curr =0; for (int i=0; i< nos_int; i++ ) { value[i] = 0; value[i] = value[i] | ( (b[curr++]) << 24 ) ; value[i] = value[i] | ( (b[curr++]) << 16 ) ; value[i] = value[i] | ( (b[curr++]) << 8 ) ; value[i] = value[i] | ( (b[curr++]) ) ; } return nos_int; } //------------------------------ // read a string. // if successful, return number of byte (including \00 ) // else return 0 // // It will not allocated space for the string s // max is the size of s //-------------------------------------------------------- // Very inefficient routine. // This routine is not meant for reading long string. // It is created (on-the-fly) for reading filename // //------------------------------ int tcp_Stream:: read_string ( char * s, int max ) { int curr =0; int count=0; int done =0; while ( (count < max) && ( !done ) ) { while (curr <1) { int curr = recv ( stream_fd, &s[count], 1,0 ); if (curr <= 0) { cout << "Error (read_int ):" << endl; return 0; } } if (s[count] == 0) { done = 1; count++; } else { count ++; } } total_byte_read += count; if (!done) count = 0; return count; } int tcp_Stream:: write_string ( char *s ) { int count =0; int done =0; int i ; for (i =0; (i<255) && (!done);i++) { done = ( s[i] ==0 ); } total_byte_write += i; if (!done) { cout << " write_integers:: Error " << endl; return 0; } else if ( send(stream_fd, s, i,0) != i ) { cout << " write_integers:: Error " << endl; return 0; } else { return i; } } //--------------------------------------------------------- // w r i t e b y t e //--------------------------------------------------------- // // format of output. // // (length of compressed data) (compressed data) // where length of compressed data is a four byte integer // in the format we used in tcp_Stream::write_int. //--------------------------------------------------------- int tcp_Stream::write_byte ( unsigned char *buf, unsigned long len ) { cout << " ......... TCP writing "<< len << " bytes " << endl; // compression unsigned long tmpsize = (unsigned long) (len * 1.01 +12 ); unsigned long compressed_len; unsigned char *tmp = new unsigned char [tmpsize]; if (!tmp) cout << " A L L O C A T I O N E R R O R : " << " tcp_Stream::read_byte " << endl; cout << "tmp buffer lenght " << tmpsize << endl; if ( COMPRESSION_TYPE == COMPRESS_LZW ) { //-------- l z r w ----------------------------------------- // Som how, also buggy //---------------------------------------------------------- long dummy; lzrw1_compress (buf, len , tmp, &dummy); compressed_len = dummy; //------------------------------------------------------ } else if ( COMPRESSION_TYPE == COMPRESS_GZ ) { //-------- G Z I P -------------------------- // Some how the compress routine doesnot run well. // it will (definitely) corrupt the memory following the // soruce buffer, by setting them to zeros. //--- // I allocated twice another buffer to avoid these. // Work need to be done here. // revisit next time. //--- // No problem in decompression. //----------------------------------------------- compressed_len =tmpsize; int err = compress ( tmp, &compressed_len, buf, len ); if (err<0) cout << "ERROR in compression " << err << endl; } else if (COMPRESSION_TYPE == COMPRESS_NON ) { //---- no compression ... for debuging ----------------- for (int i=0; i len ) { cout << " WARNING..... compressed len greater than original lenght" << endl << "this might cause overflow " << endl; if (compressed_len > len +8 ) cout << "you are in trouble.... **************** " << endl; } write_int ( (int) compressed_len); int nos_byte_send = send ( stream_fd, (char *)tmp, compressed_len, 0); cout << " ......... TCP writing "<< compressed_len << " compressed bytes " << endl; total_byte_write += nos_byte_send; if (nos_byte_send != compressed_len ) { cout << "ERROR... nos_byte_send not tally " << nos_byte_send << " " << compressed_len << endl; perror ("hmm: " ); } delete [] tmp; return nos_byte_send; } //------------------------------------------------------- // nos_byte : is the number of byte after decompression, // NOT before. // it is the user responsibility to reserve the storage space. //------------------------------------------------------- // // return the number of byte actually send across // for statistical purpose //------------------------------------------------------- int tcp_Stream::read_byte ( unsigned char *buf, unsigned long nos_byte ) { int nos_byte_to_received; read_int( &nos_byte_to_received); unsigned char *tmp = new unsigned char [nos_byte_to_received]; if (!tmp) cout << " A L L O C A T I O N E R R O R : " << " tcp_Stream::read_byte " << endl; unsigned long nos = 0; while (nos < nos_byte_to_received ) { nos += recv ( stream_fd,(char *)&(tmp[nos]), nos_byte_to_received-nos,0); } total_byte_read += nos; if (nos != nos_byte_to_received) { cout << "ERROR (read_byte).... number not tally " << nos << " and " << nos_byte_to_received << endl; while (1) {} } unsigned long actual_no_byte; if (COMPRESSION_TYPE == COMPRESS_GZ ) { //--------- G Z I P ------------------ actual_no_byte = nos_byte; int err = uncompress ( buf, &actual_no_byte, tmp, nos_byte_to_received); if (err<0) cout << " uncompression error " << err << endl; //---------------------------------------- } else if (COMPRESSION_TYPE == COMPRESS_LZW ) { //--------- L Z R W ------------- long dummy; lzrw1_decompress (tmp, nos_byte_to_received, buf, &dummy ); actual_no_byte = dummy; //--------------------------------------- } else if (COMPRESSION_TYPE == COMPRESS_NON ) { //-------- N O C O M P R E S S I O N ----------- for (int i=0;i