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::endl ;
00043 using std::flush ;
00044 using std::ostringstream ;
00045 using std::istringstream ;
00046 using std::hex ;
00047 using std::setw ;
00048 using std::setfill ;
00049
00050 #include "PPTConnection.h"
00051 #include "PPTProtocol.h"
00052 #include "Socket.h"
00053 #include "BESInternalError.h"
00054
00089 void
00090 PPTConnection::send( const string &buffer,
00091 map<string,string> &extensions )
00092 {
00093 if( !buffer.empty() )
00094 {
00095 sendChunk( buffer, extensions ) ;
00096
00097
00098 map<string,string> no_extensions ;
00099 sendChunk( "", no_extensions ) ;
00100 }
00101 else
00102 {
00103 sendChunk( "", extensions ) ;
00104 }
00105 }
00106
00109 void
00110 PPTConnection::sendExit()
00111 {
00112 map<string,string> extensions ;
00113 extensions["status"] = PPTProtocol::PPT_EXIT_NOW ;
00114 send( "", extensions ) ;
00115 }
00116
00125 void
00126 PPTConnection::sendChunk( const string &buffer, map<string,string> &extensions )
00127 {
00128 ostringstream strm ;
00129 if( extensions.size() )
00130 {
00131 sendExtensions( extensions ) ;
00132 }
00133 strm << hex << setw( 4 ) << setfill( '0' ) << buffer.length() << "d" ;
00134 if( !buffer.empty() )
00135 {
00136 strm << buffer ;
00137 }
00138 string toSend = strm.str() ;
00139 send( toSend ) ;
00140 }
00141
00146 void
00147 PPTConnection::sendExtensions( map<string,string> &extensions )
00148 {
00149 ostringstream strm ;
00150 if( extensions.size() )
00151 {
00152 ostringstream estrm ;
00153 map<string,string>::const_iterator i = extensions.begin() ;
00154 map<string,string>::const_iterator ie = extensions.end() ;
00155 for( ; i != ie; i++ )
00156 {
00157 estrm << (*i).first ;
00158 string value = (*i).second ;
00159 if( !value.empty() )
00160 {
00161 estrm << "=" << value ;
00162 }
00163 estrm << ";" ;
00164 }
00165 string xstr = estrm.str() ;
00166 strm << hex << setw( 4 ) << setfill( '0' ) << xstr.length() << "x" << xstr ;
00167 string toSend = strm.str() ;
00168 send( toSend ) ;
00169 }
00170 }
00171
00178 void
00179 PPTConnection::send( const string &buffer )
00180 {
00181 _mySock->send( buffer, 0, buffer.length() ) ;
00182 _mySock->sync() ;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00413 int
00414 PPTConnection::readBuffer( char *buffer, unsigned int buffer_size )
00415 {
00416 return _mySock->receive( buffer, buffer_size ) ;
00417 }
00418
00434 bool
00435 PPTConnection::receive( map<string,string> &extensions,
00436 ostream *strm )
00437 {
00438 ostream *use_strm = _out ;
00439 if( strm )
00440 use_strm = strm ;
00441
00442
00443 if( !_inBuff )
00444 _inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+1] ;
00445
00446
00447
00448 int bytesRead = readBuffer( _inBuff, 5 ) ;
00449 if( bytesRead != 5 )
00450 {
00451 string err = "Failed to read length and type of chunk" ;
00452 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00453 }
00454
00455 char lenbuffer[5] ;
00456 lenbuffer[0] = _inBuff[0] ;
00457 lenbuffer[1] = _inBuff[1] ;
00458 lenbuffer[2] = _inBuff[2] ;
00459 lenbuffer[3] = _inBuff[3] ;
00460 lenbuffer[4] = '\0' ;
00461 istringstream lenstrm( lenbuffer ) ;
00462 unsigned short inlen = 0 ;
00463 lenstrm >> hex >> setw(4) >> inlen ;
00464
00465 if( _inBuff[4] == 'x' )
00466 {
00467 ostringstream xstrm ;
00468 receive( xstrm, inlen ) ;
00469 read_extensions( extensions, xstrm.str() ) ;
00470 }
00471 else if( _inBuff[4] == 'd' )
00472 {
00473 if( !inlen )
00474 {
00475
00476
00477 return true ;
00478 }
00479 receive( *use_strm, inlen ) ;
00480 }
00481 else
00482 {
00483 string err = (string)"type of data is " + _inBuff[4]
00484 + ", should be x for extensions or d for data" ;
00485 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00486 }
00487
00488 return false ;
00489 }
00490
00500 void
00501 PPTConnection::receive( ostream &strm, unsigned short len )
00502 {
00503 if( !_inBuff )
00504 {
00505 string err = "buffer has not been initialized" ;
00506 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00507 }
00508
00509
00510
00511
00512
00513 if( len > PPT_PROTOCOL_BUFFER_SIZE )
00514 {
00515 string err = "buffer is not large enough" ;
00516 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00517 }
00518 int bytesRead = readBuffer( _inBuff, len ) ;
00519 if( bytesRead <= 0 )
00520 {
00521 string err = "Failed to read data from socket" ;
00522 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00523 }
00524 _inBuff[bytesRead] = '\0' ;
00525 strm.write( _inBuff, bytesRead ) ;
00526 if( bytesRead < len )
00527 {
00528 receive( strm, len - bytesRead ) ;
00529 }
00530 }
00531
00542 void
00543 PPTConnection::read_extensions( map<string,string> &extensions, const string &xstr )
00544 {
00545
00546
00547
00548 string var ;
00549 string val ;
00550 int index = 0 ;
00551 bool done = false ;
00552 while( !done )
00553 {
00554 string::size_type semi = xstr.find( ';', index ) ;
00555 if( semi == string::npos )
00556 {
00557 string err = "malformed extensions "
00558 + xstr.substr( index, xstr.length() - index )
00559 + ", missing semicolon" ;
00560 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00561 }
00562 string::size_type eq = xstr.find( '=', index ) ;
00563 if( eq == string::npos || eq > semi )
00564 {
00565
00566 var = xstr.substr( index, semi-index ) ;
00567 extensions[var] = "" ;
00568 }
00569 else if( eq == semi-1 )
00570 {
00571 string err = "malformed extensions "
00572 + xstr.substr( index, xstr.length() - index )
00573 + ", missing value after =" ;
00574 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00575 }
00576 else
00577 {
00578 var = xstr.substr( index, eq-index ) ;
00579 val = xstr.substr( eq+1, semi-eq-1 ) ;
00580 extensions[var] = val ;
00581 }
00582 index = semi+1 ;
00583 if( index >= xstr.length() )
00584 {
00585 done = true ;
00586 }
00587 }
00588 }
00589
00599 int
00600 PPTConnection::readBufferNonBlocking( char *inBuff )
00601 {
00602 struct pollfd p ;
00603 p.fd = getSocket()->getSocketDescriptor();
00604 p.events = POLLIN ;
00605 struct pollfd arr[1] ;
00606 arr[0] = p ;
00607
00608
00609
00610 for( int j = 0; j < _timeout; j++ )
00611 {
00612 if( poll( arr, 1, 1000 ) < 0 )
00613 {
00614 string error( "poll error" ) ;
00615 const char* error_info = strerror( errno ) ;
00616 if( error_info )
00617 error += " " + (string)error_info ;
00618 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00619 }
00620 else
00621 {
00622 if (arr[0].revents==POLLIN)
00623 {
00624 return readBuffer( inBuff, PPT_PROTOCOL_BUFFER_SIZE ) ;
00625 }
00626 else
00627 {
00628 cout << " " << j << flush ;
00629 }
00630 }
00631 }
00632 cout << endl ;
00633 return -1 ;
00634 }
00635
00642 void
00643 PPTConnection::dump( ostream &strm ) const
00644 {
00645 strm << BESIndent::LMarg << "PPTConnection::dump - ("
00646 << (void *)this << ")" << endl ;
00647 BESIndent::Indent() ;
00648 Connection::dump( strm ) ;
00649 BESIndent::UnIndent() ;
00650 }
00651