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, const 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 "
00278 << bytesRead << " bytes" << endl ) ;
00279 if( bytesRead != 8 )
00280 {
00281 string err = "Failed to read length and type of chunk" ;
00282 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00283 }
00284
00285 char lenbuffer[8] ;
00286 lenbuffer[0] = _inBuff[0] ;
00287 lenbuffer[1] = _inBuff[1] ;
00288 lenbuffer[2] = _inBuff[2] ;
00289 lenbuffer[3] = _inBuff[3] ;
00290 lenbuffer[4] = _inBuff[4] ;
00291 lenbuffer[5] = _inBuff[5] ;
00292 lenbuffer[6] = _inBuff[6] ;
00293 lenbuffer[7] = '\0' ;
00294 istringstream lenstrm( lenbuffer ) ;
00295 unsigned long inlen = 0 ;
00296 lenstrm >> hex >> setw(7) >> inlen ;
00297 BESDEBUG( "ppt", "Reading header, chunk length = " << inlen << endl ) ;
00298 BESDEBUG( "ppt", "Reading header, chunk type = " << _inBuff[7] << endl ) ;
00299
00300 if( _inBuff[7] == 'x' )
00301 {
00302 ostringstream xstrm ;
00303 receive( xstrm, inlen ) ;
00304 read_extensions( extensions, xstrm.str() ) ;
00305 }
00306 else if( _inBuff[7] == 'd' )
00307 {
00308 if( !inlen )
00309 {
00310
00311
00312 return true ;
00313 }
00314 receive( *use_strm, inlen ) ;
00315 }
00316 else
00317 {
00318 string err = (string)"type of data is " + _inBuff[7]
00319 + ", should be x for extensions or d for data" ;
00320 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00321 }
00322
00323 return false ;
00324 }
00325
00335 void
00336 PPTConnection::receive( ostream &strm, const unsigned int len )
00337 {
00338 BESDEBUG( "ppt", "PPTConnect::receive - len = " << len << endl ) ;
00339 if( !_inBuff )
00340 {
00341 string err = "buffer has not been initialized" ;
00342 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00343 }
00344
00345 unsigned int to_read = len ;
00346 if( len > _inBuff_len )
00347 {
00348 to_read = _inBuff_len ;
00349 }
00350 BESDEBUG( "ppt", "PPTConnect::receive - to_read = " << to_read << endl ) ;
00351
00352
00353 int bytesRead = readBuffer( _inBuff, to_read ) ;
00354 if( bytesRead <= 0 )
00355 {
00356 string err = "Failed to read data from socket" ;
00357 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00358 }
00359 BESDEBUG( "ppt", "PPTConnect::receive - bytesRead = "
00360 << bytesRead << endl ) ;
00361
00362
00363 _inBuff[bytesRead] = '\0' ;
00364 strm.write( _inBuff, bytesRead ) ;
00365
00366
00367
00368
00369 if( bytesRead < len )
00370 {
00371 BESDEBUG( "ppt", "PPTConnect::receive - remaining = "
00372 << (len - bytesRead) << endl ) ;
00373 receive( strm, len - bytesRead ) ;
00374 }
00375 }
00376
00387 void
00388 PPTConnection::read_extensions( map<string,string> &extensions, const string &xstr )
00389 {
00390
00391
00392
00393 string var ;
00394 string val ;
00395 int index = 0 ;
00396 bool done = false ;
00397 while( !done )
00398 {
00399 string::size_type semi = xstr.find( ';', index ) ;
00400 if( semi == string::npos )
00401 {
00402 string err = "malformed extensions "
00403 + xstr.substr( index, xstr.length() - index )
00404 + ", missing semicolon" ;
00405 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00406 }
00407 string::size_type eq = xstr.find( '=', index ) ;
00408 if( eq == string::npos || eq > semi )
00409 {
00410
00411 var = xstr.substr( index, semi-index ) ;
00412 extensions[var] = "" ;
00413 }
00414 else if( eq == semi-1 )
00415 {
00416 string err = "malformed extensions "
00417 + xstr.substr( index, xstr.length() - index )
00418 + ", missing value after =" ;
00419 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00420 }
00421 else
00422 {
00423 var = xstr.substr( index, eq-index ) ;
00424 val = xstr.substr( eq+1, semi-eq-1 ) ;
00425 extensions[var] = val ;
00426 }
00427 index = semi+1 ;
00428 if( index >= xstr.length() )
00429 {
00430 done = true ;
00431 }
00432 }
00433 }
00434
00445 int
00446 PPTConnection::readBufferNonBlocking( char *inBuff,
00447 const unsigned int buffer_size )
00448 {
00449 struct pollfd p ;
00450 p.fd = getSocket()->getSocketDescriptor();
00451 p.events = POLLIN ;
00452 struct pollfd arr[1] ;
00453 arr[0] = p ;
00454
00455
00456
00457 for( int j = 0; j < _timeout; j++ )
00458 {
00459 if( poll( arr, 1, 1000 ) < 0 )
00460 {
00461 string error( "poll error" ) ;
00462 const char* error_info = strerror( errno ) ;
00463 if( error_info )
00464 error += " " + (string)error_info ;
00465 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00466 }
00467 else
00468 {
00469 if (arr[0].revents==POLLIN)
00470 {
00471 return readBuffer( inBuff, buffer_size ) ;
00472 }
00473 else
00474 {
00475 cout << " " << j << flush ;
00476 }
00477 }
00478 }
00479 cout << endl ;
00480 return -1 ;
00481 }
00482
00483 unsigned int
00484 PPTConnection::getRecvChunkSize()
00485 {
00486 return _mySock->getRecvBufferSize() - PPT_CHUNK_HEADER_SPACE ;
00487 }
00488
00489 unsigned int
00490 PPTConnection::getSendChunkSize()
00491 {
00492 return _mySock->getSendBufferSize() - PPT_CHUNK_HEADER_SPACE ;
00493 }
00494
00501 void
00502 PPTConnection::dump( ostream &strm ) const
00503 {
00504 strm << BESIndent::LMarg << "PPTConnection::dump - ("
00505 << (void *)this << ")" << endl ;
00506 BESIndent::Indent() ;
00507 Connection::dump( strm ) ;
00508 BESIndent::UnIndent() ;
00509 }
00510