00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <poll.h>
00034
00035 #include <cerrno>
00036 #include <cstring>
00037 #include <iostream>
00038 #include <sstream>
00039 #include <iomanip>
00040
00041 using std::cout ;
00042 using std::cerr ;
00043 using std::endl ;
00044 using std::flush ;
00045 using std::ostringstream ;
00046 using std::istringstream ;
00047 using std::hex ;
00048 using std::setw ;
00049 using std::setfill ;
00050
00051 #include "PPTConnection.h"
00052 #include "PPTProtocol.h"
00053 #include "Socket.h"
00054 #include "BESDebug.h"
00055 #include "BESInternalError.h"
00056
00057 PPTConnection::~PPTConnection()
00058 {
00059 if( _inBuff )
00060 {
00061 delete [] _inBuff ;
00062 _inBuff = 0 ;
00063 }
00064 }
00065
00100 void
00101 PPTConnection::send( const string &buffer,
00102 map<string,string> &extensions )
00103 {
00104 if( !buffer.empty() )
00105 {
00106 sendChunk( buffer, extensions ) ;
00107
00108
00109 map<string,string> no_extensions ;
00110 sendChunk( "", no_extensions ) ;
00111 }
00112 else
00113 {
00114 sendChunk( "", extensions ) ;
00115 }
00116 }
00117
00120 void
00121 PPTConnection::sendExit()
00122 {
00123 map<string,string> extensions ;
00124 extensions["status"] = PPTProtocol::PPT_EXIT_NOW ;
00125 send( "", extensions ) ;
00126 }
00127
00136 void
00137 PPTConnection::sendChunk( const string &buffer, map<string,string> &extensions )
00138 {
00139 ostringstream strm ;
00140 if( extensions.size() )
00141 {
00142 sendExtensions( extensions ) ;
00143 }
00144 strm << hex << setw( 7 ) << setfill( '0' ) << buffer.length() << "d" ;
00145 if( !buffer.empty() )
00146 {
00147 strm << buffer ;
00148 }
00149 string toSend = strm.str() ;
00150 send( toSend ) ;
00151 }
00152
00157 void
00158 PPTConnection::sendExtensions( map<string,string> &extensions )
00159 {
00160 ostringstream strm ;
00161 if( extensions.size() )
00162 {
00163 ostringstream estrm ;
00164 map<string,string>::const_iterator i = extensions.begin() ;
00165 map<string,string>::const_iterator ie = extensions.end() ;
00166 for( ; i != ie; i++ )
00167 {
00168 estrm << (*i).first ;
00169 string value = (*i).second ;
00170 if( !value.empty() )
00171 {
00172 estrm << "=" << value ;
00173 }
00174 estrm << ";" ;
00175 }
00176 string xstr = estrm.str() ;
00177 strm << hex << setw( 7 ) << setfill( '0' ) << xstr.length() << "x" << xstr ;
00178 string toSend = strm.str() ;
00179 send( toSend ) ;
00180 }
00181 }
00182
00189 void
00190 PPTConnection::send( const string &buffer )
00191 {
00192 BESDEBUG( "ppt", "PPTConnection::send - sending " << buffer << endl )
00193 _mySock->send( buffer, 0, buffer.length() ) ;
00194 _mySock->sync() ;
00195 }
00196
00203 int
00204 PPTConnection::readBuffer( char *buffer, unsigned int buffer_size )
00205 {
00206 return _mySock->receive( buffer, buffer_size ) ;
00207 }
00208
00209 int
00210 PPTConnection::readChunkHeader( char *buffer, unsigned int buffer_size )
00211 {
00212 char *temp_buffer = buffer ;
00213 int totalBytesRead = 0 ;
00214 bool done = false ;
00215 while( !done )
00216 {
00217 int bytesRead = readBuffer( temp_buffer, buffer_size ) ;
00218 BESDEBUG( "ppt", "PPTConnection::readChunkHeader - read "
00219 << bytesRead << " bytes" << endl )
00220 if( bytesRead < 0 )
00221 {
00222 return bytesRead ;
00223 }
00224 if( bytesRead < buffer_size )
00225 {
00226 buffer_size = buffer_size - bytesRead ;
00227 temp_buffer = temp_buffer + bytesRead ;
00228 totalBytesRead += bytesRead ;
00229 }
00230 else
00231 {
00232 totalBytesRead += bytesRead ;
00233 done = true ;
00234 }
00235 }
00236 buffer[totalBytesRead] = '\0' ;
00237 return totalBytesRead ;
00238 }
00239
00255 bool
00256 PPTConnection::receive( map<string,string> &extensions,
00257 ostream *strm )
00258 {
00259 ostream *use_strm = _out ;
00260 if( strm )
00261 use_strm = strm ;
00262
00263
00264
00265 BESDEBUG( "ppt", "PPTConnection::receive: buffer size = " << _inBuff_len
00266 << endl )
00267 if( !_inBuff )
00268 {
00269 _inBuff_len = _mySock->getRecvBufferSize() + 1 ;
00270 _inBuff = new char[_inBuff_len+1] ;
00271 }
00272
00273
00274
00275
00276 int bytesRead = readChunkHeader( _inBuff, 8 ) ;
00277 BESDEBUG( "ppt", "Reading header, read " << bytesRead << " bytes" << endl )
00278 if( bytesRead != 8 )
00279 {
00280 string err = "Failed to read length and type of chunk" ;
00281 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00282 }
00283
00284 char lenbuffer[8] ;
00285 lenbuffer[0] = _inBuff[0] ;
00286 lenbuffer[1] = _inBuff[1] ;
00287 lenbuffer[2] = _inBuff[2] ;
00288 lenbuffer[3] = _inBuff[3] ;
00289 lenbuffer[4] = _inBuff[4] ;
00290 lenbuffer[5] = _inBuff[5] ;
00291 lenbuffer[6] = _inBuff[6] ;
00292 lenbuffer[7] = '\0' ;
00293 istringstream lenstrm( lenbuffer ) ;
00294 unsigned long inlen = 0 ;
00295 lenstrm >> hex >> setw(7) >> inlen ;
00296 BESDEBUG( "ppt", "Reading header, chunk length = " << inlen << endl )
00297 BESDEBUG( "ppt", "Reading header, chunk type = " << _inBuff[7] << endl )
00298
00299 if( _inBuff[7] == 'x' )
00300 {
00301 ostringstream xstrm ;
00302 receive( xstrm, inlen ) ;
00303 read_extensions( extensions, xstrm.str() ) ;
00304 }
00305 else if( _inBuff[7] == 'd' )
00306 {
00307 if( !inlen )
00308 {
00309
00310
00311 return true ;
00312 }
00313 receive( *use_strm, inlen ) ;
00314 }
00315 else
00316 {
00317 string err = (string)"type of data is " + _inBuff[7]
00318 + ", should be x for extensions or d for data" ;
00319 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00320 }
00321
00322 return false ;
00323 }
00324
00334 void
00335 PPTConnection::receive( ostream &strm, unsigned int len )
00336 {
00337 BESDEBUG( "ppt", "PPTConnect::receive - len = " << len << endl )
00338 if( !_inBuff )
00339 {
00340 string err = "buffer has not been initialized" ;
00341 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00342 }
00343
00344 unsigned int to_read = len ;
00345 if( len > _inBuff_len )
00346 {
00347 to_read = _inBuff_len ;
00348 }
00349 BESDEBUG( "ppt", "PPTConnect::receive - to_read = " << to_read << endl )
00350
00351
00352 int bytesRead = readBuffer( _inBuff, to_read ) ;
00353 if( bytesRead <= 0 )
00354 {
00355 string err = "Failed to read data from socket" ;
00356 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00357 }
00358 BESDEBUG( "ppt", "PPTConnect::receive - bytesRead = " << bytesRead << endl )
00359
00360
00361 _inBuff[bytesRead] = '\0' ;
00362 strm.write( _inBuff, bytesRead ) ;
00363
00364
00365
00366
00367 if( bytesRead < len )
00368 {
00369 BESDEBUG( "ppt", "PPTConnect::receive - remaining = "
00370 << (len - bytesRead) << endl )
00371 receive( strm, len - bytesRead ) ;
00372 }
00373 }
00374
00385 void
00386 PPTConnection::read_extensions( map<string,string> &extensions, const string &xstr )
00387 {
00388
00389
00390
00391 string var ;
00392 string val ;
00393 int index = 0 ;
00394 bool done = false ;
00395 while( !done )
00396 {
00397 string::size_type semi = xstr.find( ';', index ) ;
00398 if( semi == string::npos )
00399 {
00400 string err = "malformed extensions "
00401 + xstr.substr( index, xstr.length() - index )
00402 + ", missing semicolon" ;
00403 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00404 }
00405 string::size_type eq = xstr.find( '=', index ) ;
00406 if( eq == string::npos || eq > semi )
00407 {
00408
00409 var = xstr.substr( index, semi-index ) ;
00410 extensions[var] = "" ;
00411 }
00412 else if( eq == semi-1 )
00413 {
00414 string err = "malformed extensions "
00415 + xstr.substr( index, xstr.length() - index )
00416 + ", missing value after =" ;
00417 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00418 }
00419 else
00420 {
00421 var = xstr.substr( index, eq-index ) ;
00422 val = xstr.substr( eq+1, semi-eq-1 ) ;
00423 extensions[var] = val ;
00424 }
00425 index = semi+1 ;
00426 if( index >= xstr.length() )
00427 {
00428 done = true ;
00429 }
00430 }
00431 }
00432
00442 int
00443 PPTConnection::readBufferNonBlocking( char *inBuff, unsigned int buffer_size )
00444 {
00445 struct pollfd p ;
00446 p.fd = getSocket()->getSocketDescriptor();
00447 p.events = POLLIN ;
00448 struct pollfd arr[1] ;
00449 arr[0] = p ;
00450
00451
00452
00453 for( int j = 0; j < _timeout; j++ )
00454 {
00455 if( poll( arr, 1, 1000 ) < 0 )
00456 {
00457 string error( "poll error" ) ;
00458 const char* error_info = strerror( errno ) ;
00459 if( error_info )
00460 error += " " + (string)error_info ;
00461 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00462 }
00463 else
00464 {
00465 if (arr[0].revents==POLLIN)
00466 {
00467 return readBuffer( inBuff, buffer_size ) ;
00468 }
00469 else
00470 {
00471 cout << " " << j << flush ;
00472 }
00473 }
00474 }
00475 cout << endl ;
00476 return -1 ;
00477 }
00478
00479 unsigned int
00480 PPTConnection::getRecvChunkSize()
00481 {
00482 return _mySock->getRecvBufferSize() - PPT_CHUNK_HEADER_SPACE ;
00483 }
00484
00485 unsigned int
00486 PPTConnection::getSendChunkSize()
00487 {
00488 return _mySock->getSendBufferSize() - PPT_CHUNK_HEADER_SPACE ;
00489 }
00490
00497 void
00498 PPTConnection::dump( ostream &strm ) const
00499 {
00500 strm << BESIndent::LMarg << "PPTConnection::dump - ("
00501 << (void *)this << ")" << endl ;
00502 BESIndent::Indent() ;
00503 Connection::dump( strm ) ;
00504 BESIndent::UnIndent() ;
00505 }
00506