00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdnet.h"
00027
00028 #include "nel/net/message_recorder.h"
00029 #include "nel/net/inet_address.h"
00030
00031 using namespace NLMISC;
00032 using namespace std;
00033
00034
00035 namespace NLNET {
00036
00037
00039 string EventToString( TNetworkEvent e )
00040 {
00041 switch ( e )
00042 {
00043 case Sending: return "SEND";
00044 case Receiving: return "RECV";
00045 case Connecting: return "CONN";
00046 case ConnFailing: return "CNFL";
00047 case Accepting: return "ACCP";
00048 case Disconnecting: return "DISC";
00049 default: nlstop; return "-ERR-";
00050 }
00051 }
00052
00054 TNetworkEvent StringToEvent( string& s )
00055 {
00056 if ( s == "RECV" )
00057 return Receiving;
00058 else if ( s == "SEND" )
00059 return Sending;
00060 else if ( s == "DISC" )
00061 return Disconnecting;
00062 else if ( s == "ACCP" )
00063 return Accepting;
00064 else if ( s == "CONN" )
00065 return Connecting;
00066 else if ( s == "CNFL" )
00067 return ConnFailing;
00068 else
00069 {
00070 nlstop;
00071 return Error;
00072 }
00073 }
00074
00075
00076
00077
00078
00079 CMessageRecorder::CMessageRecorder() : _RecordAll(true)
00080 {
00081 #ifndef MESSAGES_PLAIN_TEXT
00082 nlerror( "The message recorder works only with plain text messages. Please #define MESSAGES_PLAIN_TEXT" );
00083 #endif
00084 }
00085
00086
00087
00088
00089
00090 CMessageRecorder::~CMessageRecorder()
00091 {
00092 if ( _Filename != "" )
00093 {
00094 nldebug( "MR:%s: End of recording", _Filename.c_str() );
00095 }
00096 stopRecord();
00097 stopReplay();
00098 }
00099
00100
00101
00102
00103
00104 bool CMessageRecorder::startRecord( const std::string& filename, bool recordall )
00105 {
00106 _Filename = filename;
00107 _File.open( _Filename.c_str(), ios_base::out );
00108 _File << endl;
00109 _RecordAll = recordall;
00110 if ( _File.fail() )
00111 {
00112 nlwarning( "MR: Record: Cannot open file %s", _Filename.c_str() );
00113 return false;
00114 }
00115 else
00116 {
00117 nldebug( "MR: Start recording into %s", _Filename.c_str() );
00118 return true;
00119 }
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 void CMessageRecorder::recordNext( sint64 updatecounter, TNetworkEvent event, TSockId sockid, CMessage& message )
00142 {
00143 nlassert( _File.is_open() );
00144
00145 if ( (_RecordAll) || (event != Sending) )
00146 {
00147
00148 TMessageRecord rec ( event, sockid, message, updatecounter );
00149 CMemStream stream ( false, true );
00150 rec.serial( stream );
00151 char c = '\0';
00152 stream.serial( c );
00153
00154
00155 nldebug( "MR:%s: Recording [%s]", _Filename.c_str(), stream.buffer() );
00156 int len = (int)(stream.length()-2);
00157 _File << "* ";
00158 _File << len;
00159 _File << " ";
00160 _File << (char*)stream.buffer() << endl;
00161 }
00162 }
00163
00164
00165
00166
00167
00168 void CMessageRecorder::stopRecord()
00169 {
00170 _File.close();
00171 _Filename = "";
00172 }
00173
00174
00175
00176
00177
00178 bool CMessageRecorder::startReplay( const std::string& filename )
00179 {
00180 _Filename = filename;
00181 _File.open( _Filename.c_str(), ios_base::in );
00182 if ( _File.fail() )
00183 {
00184 nlerror( "MR: Replay: Cannot open file %s", _Filename.c_str() );
00185 return false;
00186 }
00187 else
00188 {
00189 nldebug( "MR: Start replaying from %s", _Filename.c_str() );
00190 return true;
00191 }
00192 }
00193
00194
00195
00196
00197
00198 bool CMessageRecorder::loadNext( TMessageRecord& record )
00199 {
00200
00201 nlstop;
00202 return false;
00203
00204 nlassert( _File.is_open() );
00205
00206
00207 CMemStream stream ( true, true );
00208 uint32 len;
00209 char c;
00210 _File >> c;
00211 _File >> (int&)len;
00212 _File.ignore();
00213 if ( ! _File.fail() )
00214 {
00215 _File.get( (char*)stream.bufferToFill( len+1 ), len+1, '\0' );
00216
00217 nldebug( "MR:%s: Reading [%s]", _Filename.c_str(), stream.buffer() );
00218
00219
00220 record.serial( stream );
00221 }
00222
00223 return ! _File.fail();
00224 }
00225
00226
00227
00228
00229
00230 bool CMessageRecorder::getNext( TMessageRecord& record, sint64 updatecounter )
00231 {
00232 if ( ! _PreloadedRecords.empty() )
00233 {
00234 if ( _PreloadedRecords.front().UpdateCounter == updatecounter )
00235 {
00236
00237 record = _PreloadedRecords.front();
00238 _PreloadedRecords.pop_front();
00239 return true;
00240 }
00241 else
00242 {
00243
00244 nlassert( updatecounter < _PreloadedRecords.front().UpdateCounter ); // not >
00245 return false;
00246 }
00247 }
00248 else
00249 {
00250 if ( loadNext( record ) )
00251 {
00252 if ( record.UpdateCounter == updatecounter )
00253 {
00254
00255 return true;
00256 }
00257 else
00258 {
00259
00260 nlassert( updatecounter < record.UpdateCounter ); // not >
00261 _PreloadedRecords.push_back( record );
00262 return false;
00263 }
00264 }
00265 else
00266 {
00267 return false;
00268 }
00269 }
00270 }
00271
00272
00273
00274
00275
00276 void CMessageRecorder::replayNextDataAvailable( sint64 updatecounter )
00277 {
00278 TMessageRecord rec( true );
00279
00280 while ( getNext( rec, updatecounter ) )
00281 {
00282 switch ( rec.Event )
00283 {
00284 case Receiving :
00285 case Accepting :
00286 case Disconnecting :
00287 ReceivedMessages.push( rec );
00288 break;
00289
00290 case Sending :
00291 break;
00292
00293 case Connecting :
00294 case ConnFailing :
00295 _ConnectionAttempts.push_back( rec );
00296 break;
00297
00298 default :
00299 nlstop;
00300 }
00301 }
00302 }
00303
00304
00305
00306
00307
00308 TNetworkEvent CMessageRecorder::checkNextOne( sint64 updatecounter )
00309 {
00310 TMessageRecord record;
00311 if ( getNext( record, updatecounter ) )
00312 {
00313 nldebug( "MR: Check next one: %s at update %"NL_I64"u", EventToString(record.Event).c_str(), updatecounter );
00314 return record.Event;
00315 }
00316 else
00317 {
00318 return Error;
00319 }
00320 }
00321
00322
00323
00324
00325
00326 TNetworkEvent CMessageRecorder::replayConnectionAttempt( const CInetAddress& addr )
00327 {
00328 TNetworkEvent event;
00329 deque<TMessageRecord>::iterator ipr;
00330
00331 if ( ! _ConnectionAttempts.empty() )
00332 {
00333
00334 for ( ipr=_ConnectionAttempts.begin(); ipr!=_ConnectionAttempts.end(); ++ipr )
00335 {
00336 CInetAddress stored_addr;
00337 (*ipr).Message.serial( stored_addr );
00338 if ( stored_addr == addr )
00339 {
00340
00341 event = (*ipr).Event;
00342 nldebug( "MR: Connection attempt found at update %"NL_I64"u", (*ipr).UpdateCounter );
00343 _ConnectionAttempts.erase( ipr );
00344 return event;
00345 }
00346 }
00347 }
00348
00349
00350 for ( ipr=_PreloadedRecords.begin(); ipr!=_PreloadedRecords.end(); ++ipr )
00351 {
00352 event = (*ipr).Event;
00353 if ( (event == Connecting) || (event == ConnFailing) )
00354 {
00355 CInetAddress stored_addr;
00356 (*ipr).Message.serial( stored_addr );
00357 if ( stored_addr == addr )
00358 {
00359
00360 nldebug( "MR: Connection attempt found at update %"NL_I64"u", (*ipr).UpdateCounter );
00361 _PreloadedRecords.erase( ipr );
00362 return event;
00363 }
00364 }
00365 }
00366 if ( ipr==_PreloadedRecords.end() )
00367 {
00368
00369 TMessageRecord rec( true );
00370 while ( loadNext( rec ) )
00371 {
00372 if ( ( rec.Event == Connecting ) || ( rec.Event == ConnFailing ) )
00373 {
00374 CInetAddress stored_addr;
00375 rec.Message.serial( stored_addr );
00376 if ( stored_addr == addr )
00377 {
00378
00379 nldebug( "MR: Connection attempt found at update %"NL_I64"u", rec.UpdateCounter );
00380 return rec.Event;
00381 }
00382 else
00383 {
00384 _PreloadedRecords.push_back( rec );
00385 }
00386 }
00387 else
00388 {
00389 _PreloadedRecords.push_back( rec );
00390 }
00391 }
00392
00393 nldebug( "MR: Connection attempt not found" );
00394 return Error;
00395 }
00396 nlstop;
00397 return Error;
00398 }
00399
00400
00401
00402
00403
00404 void CMessageRecorder::stopReplay()
00405 {
00406 _File.close();
00407 _Filename = "";
00408 }
00409
00410
00411 }