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/misc/string_id_array.h"
00029 #include "nel/misc/hierarchical_timer.h"
00030
00031 #include "nel/net/buf_sock.h"
00032 #include "nel/net/callback_net_base.h"
00033
00034 #ifdef USE_MESSAGE_RECORDER
00035 #ifdef NL_OS_WINDOWS
00036 #pragma message ( "NeL Net layer 3: message recorder enabled" )
00037 #endif // NL_OS_WINDOWS
00038 #include "nel/net/message_recorder.h"
00039 #else
00040 #ifdef NL_OS_WINDOWS
00041 #pragma message ( "NeL Net layer 3: message recorder disabled" )
00042 #endif // NL_OS_WINDOWS
00043 #endif
00044
00045
00046 using namespace std;
00047 using namespace NLMISC;
00048
00049 namespace NLNET {
00050
00051
00052
00053
00054
00055 void cbnbMessageRecvAssociations (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00056 {
00057
00058
00059 CStringIdArray::TStringId size;
00060 msgin.serial (size);
00061
00062 nldebug ("LNETL3NB_ASSOC: The other side gave me %d association strings", size);
00063
00064 for (CStringIdArray::TStringId i = 0; i < size; i++)
00065 {
00066 std::string name;
00067 CStringIdArray::TStringId id;
00068
00069 msgin.serial (name);
00070 msgin.serial (id);
00071
00072
00073
00074
00075
00076
00077 nlassert (id != -1);
00078
00079 nldebug ("LNETL3NB_ASSOC: association '%s' -> %d", name.c_str (), id);
00080 netbase.getSIDA().addString (name, id);
00081 }
00082 }
00083
00084
00085
00086
00087
00088 void cbnbMessageAskAssociations (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00089 {
00090 CMessage msgout (netbase.getSIDA(), "RA");
00091 CStringIdArray::TStringId size;
00092 msgin.serial (size);
00093
00094 nldebug ("LNETL3NB_ASSOC: The other side want %d string associations", size);
00095
00096 msgout.serial (size);
00097
00098 for (sint i = 0; i < size; i++)
00099 {
00100 string name;
00101 msgin.serial (name);
00102 nldebug ("LNETL3NB_ASSOC: sending association '%s' -> %d", name.c_str (), netbase._OutputSIDA.getId(name));
00103
00104
00105
00106 nlassert(netbase._OutputSIDA.getId(name) != -1);
00107
00108 msgout.serial (name);
00109
00110 CStringIdArray::TStringId id = netbase._OutputSIDA.getId (name);
00111 msgout.serial (id);
00112 }
00113
00114 netbase.send (msgout, from);
00115 }
00116
00117 static TCallbackItem cbnbMessageAssociationArray[] =
00118 {
00119 { "AA", cbnbMessageAskAssociations },
00120 { "RA", cbnbMessageRecvAssociations },
00121 };
00122
00123
00124
00125
00126
00127 void cbnbNewDisconnection (TSockId from, void *data)
00128 {
00129 nlassert (data != NULL);
00130 CCallbackNetBase *base = (CCallbackNetBase *)data;
00131
00132 nldebug("LNETL3NB: cbnbNewDisconnection()");
00133
00134 #ifdef USE_MESSAGE_RECORDER
00135
00136 base->noticeDisconnection( from );
00137 #endif
00138
00139
00140 if (base->_DisconnectionCallback != NULL)
00141 base->_DisconnectionCallback (from, base->_DisconnectionCbArg);
00142 }
00143
00144
00145
00146
00147
00148 CCallbackNetBase::CCallbackNetBase( TRecordingState rec, const string& recfilename, bool recordall ) :
00149 _FirstUpdate (true), _DisconnectionCallback(NULL), _DisconnectionCbArg(NULL)
00150 #ifdef USE_MESSAGE_RECORDER
00151 , _MR_RecordingState(rec), _MR_UpdateCounter(0)
00152 #endif
00153 {
00154 _ThreadId = getThreadId ();
00155 _NewDisconnectionCallback = cbnbNewDisconnection;
00156
00157 _BytesSent = 0;
00158 _BytesReceived = 0;
00159
00160 createDebug();
00161
00162
00163 addCallbackArray (cbnbMessageAssociationArray, sizeof (cbnbMessageAssociationArray) / sizeof (cbnbMessageAssociationArray[0]));
00164
00165 #ifdef USE_MESSAGE_RECORDER
00166 switch ( _MR_RecordingState )
00167 {
00168 case Record :
00169 _MR_Recorder.startRecord( recfilename, recordall );
00170 break;
00171 case Replay :
00172 _MR_Recorder.startReplay( recfilename );
00173 break;
00174 default:;
00175
00176 }
00177 #endif
00178 }
00179
00180
00181
00182
00183
00184 void CCallbackNetBase::addCallbackArray (const TCallbackItem *callbackarray, CStringIdArray::TStringId arraysize)
00185 {
00186 checkThreadId ();
00187
00188
00189 nlassert (_CallbackArray.size () == (uint)_OutputSIDA.size ());
00190
00191 if (arraysize == 1 && callbackarray[0].Callback == NULL && string("") == callbackarray[0].Key)
00192 {
00193
00194 return;
00195 }
00196
00197
00198 sint oldsize = _CallbackArray.size();
00199
00200 _CallbackArray.resize (oldsize + arraysize);
00201 _OutputSIDA.resize (oldsize + arraysize);
00202
00203
00204
00205 for (sint i = 0; i < arraysize; i++)
00206 {
00207 CStringIdArray::TStringId ni = oldsize + i;
00208
00209
00210
00211 _CallbackArray[ni] = callbackarray[i];
00212
00213 _OutputSIDA.addString (callbackarray[i].Key, ni);
00214
00215 }
00216
00217 }
00218
00219
00220
00221
00222
00223 void CCallbackNetBase::processOneMessage ()
00224 {
00225 checkThreadId ();
00226
00227
00228
00229 CMessage msgin (_OutputSIDA, "", true);
00230 TSockId tsid;
00231 receive (msgin, &tsid);
00232
00233 _BytesReceived += msgin.length ();
00234
00235
00236 NLMISC::CStringIdArray::TStringId pos = -1;
00237 if (msgin.TypeHasAnId)
00238 {
00239 pos = msgin.getId ();
00240 }
00241 else
00242 {
00243 std::string name = msgin.getName ();
00244 sint16 i;
00245 for (i = 0; i < (sint16) _CallbackArray.size (); i++)
00246 {
00247 if (name == _CallbackArray[i].Key)
00248 {
00249 pos = i;
00250 break;
00251 }
00252 }
00253 }
00254
00255 TMsgCallback cb = NULL;
00256 if (pos < 0 || pos >= (sint16) _CallbackArray.size ())
00257 {
00258 if (_DefaultCallback == NULL)
00259 {
00260 nlwarning ("LNETL3NB_CB: Callback %s not found in _CallbackArray", msgin.toString().c_str());
00261 }
00262 else
00263 {
00264 cb = _DefaultCallback;
00265 }
00266 }
00267 else
00268 {
00269 cb = _CallbackArray[pos].Callback;
00270 }
00271
00272 TSockId realid = getSockId (tsid);
00273
00274 if (!realid->AuthorizedCallback.empty() && msgin.getName() != realid->AuthorizedCallback)
00275 {
00276 nlwarning ("LNETL3NB_CB: %s try to call the callback %s but only %s is authorized. Disconnect him!", tsid->asString().c_str(), msgin.toString().c_str(), tsid->AuthorizedCallback.c_str());
00277 disconnect (tsid);
00278 }
00279 else if (cb == NULL)
00280 {
00281 nlwarning ("LNETL3NB_CB: Callback %s is NULL, can't call it", msgin.toString().c_str());
00282 }
00283 else
00284 {
00285 nldebug ("LNETL3NB_CB: Calling callback (%s)%s", msgin.getName().c_str(), (cb==_DefaultCallback)?" DEFAULT_CB":"");
00286 cb(msgin, realid, *this);
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 void CCallbackNetBase::baseUpdate (sint32 timeout)
00329 {
00330 checkThreadId ();
00331
00332
00333
00334 nlassert( timeout >= -1 );
00335 TTime t0 = CTime::getLocalTime();
00336
00337
00338
00339
00340 if (_FirstUpdate)
00341 {
00342
00343 _FirstUpdate = false;
00344 _LastUpdateTime = t0;
00345 _LastMovedStringArray = t0;
00346 }
00347
00348
00349
00350
00351 if (t0 - _LastUpdateTime > 1000)
00352 {
00353
00354 _LastUpdateTime = t0;
00355
00356 const set<string> &sa = _InputSIDA.getNeedToAskedStringArray ();
00357 if (!sa.empty ())
00358 {
00359 CMessage msgout (_InputSIDA, "AA");
00360
00361 CStringIdArray::TStringId size = sa.size ();
00362 nldebug ("LNETL3NB_ASSOC: I need %d string association, ask them to the other side", size);
00363 msgout.serial (size);
00364 for (set<string>::iterator it = sa.begin(); it != sa.end(); it++)
00365 {
00366 nldebug ("LNETL3NB_ASSOC: what is the id of '%s'?", (*it).c_str ());
00367 string str(*it);
00368 msgout.serial (str);
00369 }
00370
00371 send (msgout, 0);
00372 _InputSIDA.moveNeedToAskToAskedStringArray();
00373 _LastMovedStringArray = t0;
00374 }
00375 }
00376
00377
00378
00379
00380 if (!_InputSIDA.getAskedStringArray().empty() && t0 - _LastMovedStringArray > 60000)
00381 {
00382
00383 const set<string> sa = _InputSIDA.getAskedStringArray ();
00384 CMessage msgout (_InputSIDA, "AA");
00385
00386 CStringIdArray::TStringId size = sa.size ();
00387 nldebug ("LNETL3NB_ASSOC: client didn't answer my asked association, retry! I need %d string association, ask them to the other side", size);
00388 msgout.serial (size);
00389 for (set<string>::iterator it = sa.begin(); it != sa.end(); it++)
00390 {
00391 nldebug ("LNETL3NB_ASSOC: what is the id of '%s'?", (*it).c_str ());
00392 string str(*it);
00393 msgout.serial (str);
00394 }
00395
00396 send (msgout, 0);
00397 _LastMovedStringArray = t0;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 bool exit = false;
00407
00408 while (!exit)
00409 {
00410
00411 while (dataAvailable ())
00412 {
00413 processOneMessage ();
00414 if (timeout == -1)
00415 {
00416 exit = true;
00417 break;
00418 }
00419 }
00420
00421
00422 if (timeout == 0 || (sint32)(CTime::getLocalTime() - t0) > timeout)
00423 {
00424 exit = true;
00425 }
00426 else
00427 {
00428
00429
00430 nlSleep (10);
00431 }
00432 }
00433
00434 #ifdef USE_MESSAGE_RECORDER
00435 _MR_UpdateCounter++;
00436 #endif
00437
00438 }
00439
00440
00441 const CInetAddress& CCallbackNetBase::hostAddress (TSockId hostid)
00442 {
00443
00444 nlstop;
00445 static CInetAddress tmp;
00446 return tmp;
00447 }
00448
00449 void CCallbackNetBase::setOtherSideAssociations (const char **associationarray, NLMISC::CStringIdArray::TStringId arraysize)
00450 {
00451 checkThreadId ();
00452
00453 nldebug ("LNETL3NB_ASSOC: setOtherSideAssociations() sets %d association strings", arraysize);
00454
00455 for (sint i = 0; i < arraysize; i++)
00456 {
00457 nldebug ("LNETL3NB_ASSOC: association '%s' -> %d", associationarray[i], i);
00458 getSIDA().addString (associationarray[i], i);
00459 }
00460 }
00461
00462 void CCallbackNetBase::displayAllMyAssociations ()
00463 {
00464 checkThreadId ();
00465
00466 _OutputSIDA.display ();
00467 }
00468
00469 void CCallbackNetBase::authorizeOnly (const char *callbackName, TSockId hostid)
00470 {
00471 checkThreadId ();
00472
00473 nldebug ("LNETL3NB: authorizeOnly (%s, %s)", callbackName, hostid->asString().c_str());
00474
00475 hostid = getSockId (hostid);
00476
00477 nlassert (hostid != InvalidSockId);
00478
00479 hostid->AuthorizedCallback = (callbackName == NULL)?"":callbackName;
00480 }
00481
00482
00483 #ifdef USE_MESSAGE_RECORDER
00484
00485
00486
00487
00488 bool CCallbackNetBase::replayDataAvailable()
00489 {
00490 nlassert( _MR_RecordingState == Replay );
00491
00492 if ( _MR_Recorder.ReceivedMessages.empty() )
00493 {
00494
00495 _MR_Recorder.replayNextDataAvailable( _MR_UpdateCounter );
00496 }
00497
00498 return replaySystemCallbacks();
00499 }
00500
00501
00502
00503
00504
00505 void CCallbackNetBase::noticeDisconnection( TSockId hostid )
00506 {
00507 nlassert (hostid != InvalidSockId);
00508 if ( _MR_RecordingState != Replay )
00509 {
00510 if ( _MR_RecordingState == Record )
00511 {
00512
00513 CMessage emptymsg;
00514 _MR_Recorder.recordNext( _MR_UpdateCounter, Disconnecting, hostid, emptymsg );
00515 }
00516 }
00517 else
00518 {
00519
00520 hostid->disconnect( false );
00521 }
00522 }
00523
00524 #endif // USE_MESSAGE_RECORDER
00525
00526
00527
00528
00529
00530
00531 void CCallbackNetBase::checkThreadId () const
00532 {
00533
00534
00535
00536
00537
00538
00539
00540 }
00541
00542
00543 }
00544