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/unified_network.h"
00029
00030 using namespace std;
00031 using namespace NLMISC;
00032
00033
00034 namespace NLNET {
00035
00036 CLog test(CLog::LOG_INFO);
00037 CFileDisplayer fd;
00038
00039 static uint ThreadCreator = 0;
00040
00041 static const uint64 AppIdDeadConnection = 0xDEAD;
00042
00043 #define AUTOCHECK_DISPLAY nlwarning
00044
00045
00046
00047 static string allstuffs;
00048
00049
00050
00051
00052
00053
00054 void uNetRegistrationBroadcast(const string &name, TServiceId sid, const vector<CInetAddress> &addr)
00055 {
00056 nldebug ("HNETL5: + naming %s-%hu '%s'", name.c_str(), (uint16)sid, vectorCInetAddressToString(addr).c_str ());
00057
00058 allstuffs += "+naming "+name+"-"+toString(sid)+"\n";
00059 test.displayNL ("+naming %s-%hu", name.c_str (), (uint16)sid);
00060
00061 CUnifiedNetwork *uni= CUnifiedNetwork::getInstance();
00062
00063 if (uni->_SId == sid)
00064 {
00065 allstuffs += "itsme!!!\n";
00066 test.displayNL ("itsme!!!");
00067
00068 return;
00069 }
00070
00071
00072
00073 if(sid >= uni->_IdCnx.size ())
00074 uni->_IdCnx.resize (sid+1);
00075
00076 if (uni->_IdCnx[sid].State == CUnifiedNetwork::CUnifiedConnection::NotUsed)
00077 {
00078 uni->_IdCnx[sid] = CUnifiedNetwork::CUnifiedConnection(name, sid, false);
00079 uni->_UsedConnection.push_back (sid);
00080 }
00081
00082 if (!uni->_IdCnx[sid].ExtAddress.empty ()) AUTOCHECK_DISPLAY ("HNETL5: %s-%hu already inserted in the table with '%s'", name.c_str(), (uint16)sid, vectorCInetAddressToString (uni->_IdCnx[sid].ExtAddress).c_str ());
00083
00084
00085
00086
00087 nlassert (!addr.empty());
00088
00089 uni->_IdCnx[sid].ExtAddress = addr;
00090
00091
00092 uni->_IdCnx[sid].setupNetworkAssociation (uni->_NetworkAssociations, uni->_DefaultNetwork);
00093 }
00094
00095
00096 void uNetUnregistrationBroadcast(const string &name, TServiceId sid, const vector<CInetAddress> &addr)
00097 {
00098 nldebug ("HNETL5: - naming %s-%hu '%s'", name.c_str(), (uint16)sid, vectorCInetAddressToString (addr).c_str ());
00099
00100 allstuffs += "-naming "+name+"-"+toString(sid)+"\n";
00101 test.displayNL ("-naming %s-%hu", name.c_str (), (uint16)sid);
00102
00103
00104 CUnifiedNetwork *uni = CUnifiedNetwork::getInstance();
00105
00106 CUnifiedNetwork::CUnifiedConnection *uc = uni->getUnifiedConnection (sid);
00107 if (uc == 0) return;
00108
00109
00110 CUnifiedNetwork::TNameMappedCallback::iterator it2 = uni->_DownCallbacks.find(uc->ServiceName);
00111
00112 if (it2 != uni->_DownCallbacks.end())
00113 {
00114
00115 TUnifiedNetCallback cb = (*it2).second.first;
00116 cb(uc->ServiceName, uc->ServiceId, (*it2).second.second);
00117 }
00118
00119 for (uint c = 0; c < uni->_DownUniCallback.size (); c++)
00120 {
00121 if (uni->_DownUniCallback[c].first != NULL)
00122 uni->_DownUniCallback[c].first(uc->ServiceName, uc->ServiceId, uni->_DownUniCallback[c].second);
00123 }
00124
00125 if(!uc->Connection.empty ())
00126 {
00127
00128 for (uint i = 0; i < uc->Connection.size (); ++i)
00129 {
00130 if (uc->Connection[i].valid())
00131 uc->Connection[i].setAppId (AppIdDeadConnection);
00132 }
00133
00134
00135
00136
00137
00138
00139 uni->removeNamedCnx (uc->ServiceName, uc->ServiceId);
00140 }
00141
00142
00143 bool found = false;
00144 for (vector<uint16>::iterator it = uni->_UsedConnection.begin (); it != uni->_UsedConnection.end(); it++)
00145 {
00146 if (*it == uc->ServiceId)
00147 {
00148 found = true;
00149 uni->_UsedConnection.erase (it);
00150 break;
00151 }
00152 }
00153 if (!found) AUTOCHECK_DISPLAY ("HNETL5: can't find the sid %hu in the _UsedConnection", uc->ServiceId);
00154
00155
00156 uc->reset ();
00157 }
00158
00159
00160
00161
00162
00163
00164 void uncbConnection(TSockId from, void *arg)
00165 {
00166 nlinfo ("HNETL5: + connec '%s'", from->asString().c_str());
00167
00168 from->setAppId (AppIdDeadConnection);
00169 }
00170
00171 void uncbDisconnection(TSockId from, void *arg)
00172 {
00173 if(from->appId () == AppIdDeadConnection)
00174 {
00175 nlinfo ("HNETL5: - connec '%s'", from->asString().c_str());
00176 test.displayNL ("-connect dead conenction");
00177 }
00178 else
00179 {
00180 CUnifiedNetwork *uni = CUnifiedNetwork::getInstance();
00181 uint16 sid = (uint16)from->appId();
00182 CUnifiedNetwork::CUnifiedConnection *uc = uni->getUnifiedConnection (sid);
00183 if (uc == 0)
00184 {
00185 nlinfo ("HNETL5: - connec '%s' sid %hu", from->asString().c_str(), sid);
00186 test.displayNL ("-connect '%s' %hu", from->asString ().c_str (), sid);
00187 }
00188 else
00189 {
00190 nlinfo ("HNETL5: - connec '%s' %s-%hu", from->asString().c_str(), uc->ServiceName.c_str (), sid);
00191 allstuffs += "-connect "+uc->ServiceName+"-"+toString(sid)+"\n";
00192 test.displayNL ("-connect %s-%hu", uc->ServiceName.c_str (), (uint16)(uc->ServiceId));
00193
00194 if (uc->IsExternal)
00195 {
00196 if (!uc->AutoRetry)
00197 {
00198
00199
00200
00201 CUnifiedNetwork::TNameMappedCallback::iterator it2 = uni->_DownCallbacks.find(uc->ServiceName);
00202
00203 if (it2 != uni->_DownCallbacks.end())
00204 {
00205
00206 TUnifiedNetCallback cb = (*it2).second.first;
00207 cb(uc->ServiceName, uc->ServiceId, (*it2).second.second);
00208 }
00209
00210 for (uint c = 0; c < uni->_DownUniCallback.size (); c++)
00211 {
00212 if (uni->_DownUniCallback[c].first != NULL)
00213 uni->_DownUniCallback[c].first(uc->ServiceName, uc->ServiceId, uni->_DownUniCallback[c].second);
00214 }
00215
00216 uni->removeNamedCnx (uc->ServiceName, uc->ServiceId);
00217
00218
00219 bool found = false;
00220 for (vector<uint16>::iterator it = uni->_UsedConnection.begin (); it != uni->_UsedConnection.end(); it++)
00221 {
00222 if (*it == uc->ServiceId)
00223 {
00224 found = true;
00225 uni->_UsedConnection.erase (it);
00226 break;
00227 }
00228 }
00229 if (!found) AUTOCHECK_DISPLAY ("HNETL5: can't find the sid %hu in the _UsedConnection", uc->ServiceId);
00230
00231 uc->reset ();
00232 }
00233 }
00234 else
00235 {
00236
00237 uint i;
00238 for (i = 0; i < uc->Connection.size (); i++)
00239 {
00240 if (uc->Connection[i].valid() && uc->Connection[i].CbNetBase->getSockId(uc->Connection[i].HostId) == from)
00241 {
00242 if (uc->Connection[i].IsServerConnection)
00243 {
00244
00245 uc->Connection[i].reset();
00246 }
00247 else
00248 {
00249
00250
00251 if(uc->Connection[i].CbNetBase->connected ())
00252 {
00253 uc->Connection[i].CbNetBase->disconnect (uc->Connection[i].HostId);
00254 }
00255 }
00256 break;
00257 }
00258 }
00259 if (i == uc->Connection.size ())
00260 {
00261 AUTOCHECK_DISPLAY ("HNETL5: received a disconnection from a service but the connection is not in my list!");
00262 }
00263 }
00264 }
00265
00266 from->setAppId (AppIdDeadConnection);
00267 }
00268 }
00269
00270
00271
00272
00273
00274 void uncbServiceIdentification(CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00275 {
00276 string inSName;
00277 uint16 inSid;
00278
00279 if (from->appId () != AppIdDeadConnection)
00280 AUTOCHECK_DISPLAY ("HNETL5: received a connec ident from an unknown connection 0x%"NL_I64"X", from->appId ());
00281
00282
00283 msgin.serial(inSName);
00284 msgin.serial(inSid);
00285 uint8 pos;
00286 msgin.serial (pos);
00287 bool isExternal;
00288 msgin.serial (isExternal);
00289
00290 nlinfo ("HNETL5: + connec ident '%s' %s-%hu pos %hu ext %d", from->asString().c_str(), inSName.c_str(), inSid, (uint16)pos, (uint8)isExternal);
00291
00292 allstuffs += "+rconnect "+inSName+"-"+toString(inSid)+" pos "+toString((uint16)pos)+"\n";
00293 test.displayNL ("+rconnect %s-%hu pos %hu", inSName.c_str (), (uint16)inSid, (uint16)pos);
00294
00295 if(isExternal)
00296 {
00297 nlassert (pos == 0);
00298 }
00299
00300 if (inSid == 0)
00301 {
00302 if (isExternal)
00303 {
00304 inSid = CUnifiedNetwork::getInstance ()->_ExtSId++;
00305 nlwarning ("HNETL5: Received a connection from a service with a SId 0, we give him the SId %d", inSid);
00306 }
00307 else
00308 {
00309 nlwarning ("HNETL5: Received a connection from a service with a SId 0 and wasn't external, disconnecting it");
00310 netbase.disconnect();
00311 return;
00312 }
00313 }
00314
00315 from->setAppId(inSid);
00316
00317
00318 CUnifiedNetwork *uni= CUnifiedNetwork::getInstance();
00319
00320 if(inSid >= uni->_IdCnx.size ())
00321 {
00322 uni->_IdCnx.resize (inSid+1);
00323 }
00324
00325 switch(uni->_IdCnx[inSid].State)
00326 {
00327 case CUnifiedNetwork::CUnifiedConnection::NotUsed:
00328 uni->_IdCnx[inSid] = CUnifiedNetwork::CUnifiedConnection(inSName, inSid, isExternal);
00329 uni->_UsedConnection.push_back (inSid);
00330 break;
00331 default:
00332 break;
00333 }
00334
00335 if (uni->_IdCnx[inSid].IsExternal != isExternal)
00336 {
00337 AUTOCHECK_DISPLAY ("HNETL5: Receive a connection that is not totally external %d %d", uni->_IdCnx[inSid].IsExternal, isExternal);
00338 return;
00339 }
00340
00341
00342
00343 if (pos >= uni->_IdCnx[inSid].Connection.size ())
00344 uni->_IdCnx[inSid].Connection.resize(pos+1);
00345 uni->_IdCnx[inSid].Connection[pos] = CUnifiedNetwork::CUnifiedConnection::TConnection(&netbase, from);
00346
00347
00348 if (isExternal)
00349 {
00350 uni->_IdCnx[inSid].ExtAddress.push_back (netbase.hostAddress (from));
00351 uni->_IdCnx[inSid].setupNetworkAssociation (uni->_NetworkAssociations, uni->_DefaultNetwork);
00352 }
00353
00354
00355
00356 if (uni->_IdCnx[inSid].Connection.size() == 3)
00357 {
00358 CUnifiedNetwork::CUnifiedConnection *uc = &uni->_IdCnx[inSid];
00359 nlstop;
00360 nlinfo ("ext addr %s", vectorCInetAddressToString (uc->ExtAddress).c_str ());
00361 for(uint i = 0; i < uc->Connection.size(); i++)
00362 nlinfo ("cnx %s", uc->Connection[i].HostId->asString ().c_str ());
00363 nlinfo ("%s", allstuffs.c_str ());
00364 }
00365
00366
00367 if (uni->_IdCnx[inSid].Connection.size () == 1)
00368 {
00369
00370 uni->addNamedCnx (inSName, inSid);
00371
00372
00373 CUnifiedNetwork::TNameMappedCallback::iterator it = uni->_UpCallbacks.find(inSName);
00374 if (it != uni->_UpCallbacks.end())
00375 {
00376
00377 TUnifiedNetCallback cb = (*it).second.first;
00378 cb(inSName, inSid, (*it).second.second);
00379 }
00380
00381 for (uint c = 0; c < uni->_UpUniCallback.size (); c++)
00382 {
00383 if (uni->_UpUniCallback[c].first != NULL)
00384 uni->_UpUniCallback[c].first (inSName, inSid, uni->_UpUniCallback[c].second);
00385 }
00386 }
00387 }
00388
00389
00390 void uncbMsgProcessing(CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00391 {
00392 if (from->appId() == AppIdDeadConnection)
00393 {
00394 AUTOCHECK_DISPLAY ("HNETL5: Receive a message from a dead connection");
00395 return;
00396 }
00397
00398 CUnifiedNetwork *uni = CUnifiedNetwork::getInstance();
00399 uint16 sid = (uint16)from->appId();
00400 CUnifiedNetwork::TMsgMappedCallback::iterator itcb;
00401
00402 itcb = uni->_Callbacks.find(msgin.getName());
00403 if (itcb == uni->_Callbacks.end())
00404 {
00405
00406 nlwarning ("HNETL5: Can't find callback '%s' called by service %hu", msgin.getName().c_str(), sid);
00407 }
00408 else
00409 {
00410 CUnifiedNetwork::CUnifiedConnection *uc = uni->getUnifiedConnection (sid);
00411
00412 if (uc == 0)
00413 {
00414 nlwarning ("HNETL5: Received a message from a service %hu that is not ready (bad appid? 0x%"NL_I64"X)", sid, from->appId ());
00415 return;
00416 }
00417 if((*itcb).second == 0)
00418 {
00419 nlwarning ("HNETL5: Received message %s from a service %hu but the associated callback is NULL", msgin.getName ().c_str(), sid);
00420 return;
00421 }
00422 (*itcb).second (msgin, uc->ServiceName, sid);
00423 }
00424 }
00425
00426
00427 TCallbackItem unServerCbArray[] =
00428 {
00429 { "UN_SIDENT", uncbServiceIdentification }
00430 };
00431
00432
00433
00434
00435
00436
00437 void CUnifiedNetwork::init(const CInetAddress *addr, CCallbackNetBase::TRecordingState rec,
00438 const string &shortName, uint16 port, TServiceId &sid)
00439 {
00440
00441
00442 if (_Initialised)
00443 {
00444 AUTOCHECK_DISPLAY ("HNETL5: Unified network layer already initialized");
00445 return;
00446 }
00447
00448 ThreadCreator = NLMISC::getThreadId();
00449
00450 vector<CInetAddress> laddr = CInetAddress::localAddresses();
00451
00452 _RecordingState = rec;
00453 _Name = shortName;
00454 _SId = sid;
00455
00456 if (addr != 0)
00457 _NamingServiceAddr = *addr;
00458
00459
00460 if (_NamingServiceAddr.isValid ())
00461 {
00462
00463 CNamingClient::setRegistrationBroadcastCallback(uNetRegistrationBroadcast);
00464 CNamingClient::setUnregistrationBroadcastCallback(uNetUnregistrationBroadcast);
00465
00466
00467 CNamingClient::connect(_NamingServiceAddr, _RecordingState, laddr);
00468
00469 if (port == 0)
00470 port = CNamingClient::queryServicePort ();
00471 }
00472
00473
00474 _ServerPort = port;
00475
00476 if(_ServerPort != 0)
00477 {
00478 nlassert (_CbServer == 0);
00479 _CbServer = new CCallbackServer;
00480 _CbServer->init(port);
00481 _CbServer->addCallbackArray(unServerCbArray, 1);
00482 _CbServer->setDefaultCallback(uncbMsgProcessing);
00483 _CbServer->setConnectionCallback(uncbConnection, NULL);
00484 _CbServer->setDisconnectionCallback(uncbDisconnection, NULL);
00485 }
00486 else
00487 {
00488 nlinfo ("HNETL5: ServerPort is 0 so I don't create a CCallbackServer");
00489 }
00490
00491 if (CNamingClient::connected())
00492 {
00493
00494 for (uint i = 0; i < laddr.size(); i++)
00495 laddr[i].setPort(_ServerPort);
00496
00497 if (_SId == 0)
00498 {
00499 CNamingClient::registerService(_Name, laddr, _SId);
00500 }
00501 else
00502 {
00503 CNamingClient::registerServiceWithSId(_Name, laddr, _SId);
00504 }
00505
00506 sid = _SId;
00507
00508 nlinfo ("HNETL5: Server '%s' added, registered and listen to port %hu", _Name.c_str (), _ServerPort);
00509 }
00510
00511 string fn = _Name+"_"+toString(_SId)+".log";
00512 fd.setParam (fn);
00513 test.addDisplayer (&fd);
00514 test.displayNL ("**************INIT***************");
00515
00516 _Initialised = true;
00517 }
00518
00519 void CUnifiedNetwork::connect()
00520 {
00521 nlassertex(_Initialised == true, ("Try to CUnifiedNetwork::connect() whereas it is not initialised yet"));
00522
00523 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
00524
00525
00526 if (CNamingClient::connected())
00527 {
00528
00529 const list<CNamingClient::CServiceEntry> &services = CNamingClient::getRegisteredServices();
00530
00531
00532 list<CNamingClient::CServiceEntry>::const_iterator its;
00533
00534
00535 for (its = services.begin(); its != services.end(); ++its)
00536 {
00537 if (_SId != (*its).SId)
00538 {
00539
00540
00541 addService((*its).Name, (*its).Addr, true, false, (*its).SId, false, true);
00542 }
00543 else
00544 {
00545
00546 break;
00547 }
00548 }
00549 }
00550 }
00551
00552 void CUnifiedNetwork::release()
00553 {
00554 if (!_Initialised)
00555 return;
00556
00557 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
00558
00559
00560 if(_CbServer)
00561 {
00562 _CbServer->disconnect(InvalidSockId);
00563 delete _CbServer;
00564 _CbServer = 0;
00565 }
00566
00567
00568 for (uint i = 0; i<_IdCnx.size(); ++i)
00569 {
00570 if (_IdCnx[i].State != CUnifiedNetwork::CUnifiedConnection::NotUsed)
00571 {
00572 for(uint j = 0 ; j < _IdCnx[i].Connection.size (); j++)
00573 {
00574 if (_IdCnx[i].Connection[j].valid() && !_IdCnx[i].Connection[j].IsServerConnection)
00575 {
00576 if (_IdCnx[i].Connection[j].CbNetBase->connected ())
00577 _IdCnx[i].Connection[j].CbNetBase->disconnect();
00578
00579 delete _IdCnx[i].Connection[j].CbNetBase;
00580 }
00581 }
00582 _IdCnx[i].Connection.clear ();
00583 }
00584 }
00585
00586
00587 _IdCnx.clear();
00588 _UsedConnection.clear ();
00589 _NamedCnx.clear();
00590 _UpCallbacks.clear();
00591 _DownCallbacks.clear();
00592 _Callbacks.clear();
00593
00594
00595 if (CNamingClient::connected ())
00596 CNamingClient::disconnect ();
00597 }
00598
00599 void CUnifiedNetwork::addService(const string &name, const CInetAddress &addr, bool sendId, bool external, uint16 sid, bool autoRetry, bool shouldBeAlreayInserted)
00600 {
00601 vector <CInetAddress> addrs;
00602 addrs.push_back (addr);
00603 addService (name, addrs, sendId, external, sid, autoRetry, shouldBeAlreayInserted);
00604 }
00605
00606 void CUnifiedNetwork::addService(const string &name, const vector<CInetAddress> &addr, bool sendId, bool external, uint16 sid, bool autoRetry, bool shouldBeAlreayInserted)
00607 {
00608 nlassertex(_Initialised == true, ("Try to CUnifiedNetwork::addService() whereas it is not initialised yet"));
00609
00610 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
00611
00612 if (external)
00613 sid = _ExtSId++;
00614
00615 nlinfo("HNETL5: addService %s-%hu '%s'", name.c_str(), sid, vectorCInetAddressToString(addr).c_str());
00616
00617 allstuffs += "addService "+name+"-"+toString(sid)+"\n";
00618 test.displayNL ("+service %s-%hu", name.c_str (), (uint16)sid);
00619
00620 if (external && addr.size () != 1)
00621 {
00622 AUTOCHECK_DISPLAY ("HNETL5: Can't add external service with more than one connection");
00623 }
00624
00625
00626
00627 if (sid >= _IdCnx.size())
00628 _IdCnx.resize(sid+1);
00629
00630 CUnifiedConnection *uc = &_IdCnx[sid];
00631
00632
00633
00634 if (shouldBeAlreayInserted && _IdCnx[sid].State == CUnifiedNetwork::CUnifiedConnection::NotUsed) AUTOCHECK_DISPLAY ("HNETL5: the unified connection should already set by the naming reg broadcast and is not (%hu)", sid);
00635 if (!shouldBeAlreayInserted && _IdCnx[sid].State == CUnifiedNetwork::CUnifiedConnection::Ready) AUTOCHECK_DISPLAY ("HNETL5: the unified connection should not already set but is (%hu)", sid);
00636
00637 if (_IdCnx[sid].State == CUnifiedNetwork::CUnifiedConnection::NotUsed)
00638 {
00639 *uc = CUnifiedConnection(name, sid, external);
00640 _UsedConnection.push_back (sid);
00641 }
00642 else
00643 {
00644
00645 if (name != uc->ServiceName) AUTOCHECK_DISPLAY ("HNETL5: name are different in addService %s %s", name.c_str (), uc->ServiceName.c_str ());
00646 if (sid != uc->ServiceId) AUTOCHECK_DISPLAY ("HNETL5: sid are different in addService %hu %hu", sid, uc->ServiceId);
00647 if (addr != uc->ExtAddress) AUTOCHECK_DISPLAY ("HNETL5: external addr are different in addService '%s' '%s'", vectorCInetAddressToString(addr).c_str(), vectorCInetAddressToString(uc->ExtAddress).c_str ());
00648 }
00649 uc->AutoRetry = autoRetry;
00650 uc->SendId = sendId;
00651 uc->ExtAddress = addr;
00652 nlassert (!addr.empty());
00653
00654
00655 uc->setupNetworkAssociation (_NetworkAssociations, _DefaultNetwork);
00656
00657
00658 bool connectSuccess;
00659
00660 if (uc->Connection.size () < addr.size ())
00661 {
00662 uc->Connection.resize (addr.size ());
00663 }
00664
00665 vector<CInetAddress> laddr = CInetAddress::localAddresses();
00666
00667 for (uint i = 0; i < addr.size(); i++)
00668 {
00669
00670
00671 uint j = 0;
00672
00673 if (!addr[i].is127001 ())
00674 {
00675 for (j = 0; j < laddr.size (); j++)
00676 {
00677 if (laddr[j].internalNetAddress () == addr[i].internalNetAddress ())
00678 {
00679
00680 break;
00681 }
00682 }
00683
00684
00685
00686 if (j == laddr.size ())
00687 {
00688 nlwarning ("I can't access '%s' because I haven't a net card on this network, we'll use the first network", addr[i].asString ().c_str ());
00689 j = 0;
00690 }
00691 }
00692
00693
00694 CCallbackClient *cbc = new CCallbackClient();
00695 cbc->setDisconnectionCallback(uncbDisconnection, NULL);
00696 cbc->setDefaultCallback(uncbMsgProcessing);
00697 cbc->getSockId()->setAppId(sid);
00698
00699 try
00700 {
00701 cbc->connect(addr[i]);
00702 connectSuccess = true;
00703
00704 allstuffs += "+lconnect "+name+"-"+toString(sid)+"\n";
00705 test.displayNL ("+lconnect %s-%hu", name.c_str (), (uint16)sid);
00706 }
00707 catch (ESocketConnectionFailed &e)
00708 {
00709 nlwarning ("HNETL5: can't connect to %s (sid %u) now (%s) '%s'", name.c_str(), sid, e.what (), addr[i].asString ().c_str());
00710 connectSuccess = false;
00711
00712 allstuffs += "+lconnect failed "+name+"-"+toString((uint16)sid)+"\n";
00713 test.displayNL ("+lconnect failed %s-%hu", name.c_str (), (uint16)sid);
00714 }
00715
00716 if (!connectSuccess && !autoRetry)
00717 {
00718 nlwarning ("HNETL5: Can't add service because no retry and can't connect");
00719 delete cbc;
00720 }
00721 else
00722 {
00723 uc->Connection[i] = CUnifiedNetwork::CUnifiedConnection::TConnection(cbc);
00724
00725 nlinfo ("%s", allstuffs.c_str ());
00726 }
00727
00728 if (connectSuccess && sendId)
00729 {
00730
00731 CMessage msg("UN_SIDENT");
00732 msg.serial(_Name);
00733 uint16 ssid = _SId;
00734 if (uc->IsExternal)
00735 {
00736
00737
00738
00739 ssid = 0;
00740 }
00741 msg.serial(ssid);
00742 uint8 pos = j;
00743 msg.serial(pos);
00744 msg.serial (uc->IsExternal);
00745 cbc->send (msg);
00746 }
00747 }
00748
00749 if (addr.size () != uc->Connection.size())
00750 {
00751 nlwarning ("HNETL5: Can't connect to all connections to the service %d/%d", addr.size (), uc->Connection.size());
00752 }
00753
00754 bool cntok = false;
00755 for (uint j = 0; j < uc->Connection.size(); j++)
00756 {
00757 if (uc->Connection[j].CbNetBase != NULL)
00758 {
00759 if (uc->Connection[j].CbNetBase->connected ())
00760 {
00761 cntok = true;
00762 break;
00763 }
00764 }
00765 }
00766
00767 if (cntok)
00768 {
00769
00770 addNamedCnx (name, sid);
00771
00772
00773 TNameMappedCallback::iterator itcb = _UpCallbacks.find(name);
00774 if (itcb != _UpCallbacks.end() && (*itcb).second.first != NULL)
00775 {
00776 TUnifiedNetCallback cb = (*itcb).second.first;
00777 cb(name, sid, (*itcb).second.second);
00778 }
00779
00780 if (!external)
00781 {
00782 for (uint i = 0; i < _UpUniCallback.size (); i++)
00783 {
00784 if (_UpUniCallback[i].first != NULL)
00785 _UpUniCallback[i].first (name, sid, _UpUniCallback[i].second);
00786 }
00787 }
00788 }
00789
00790 nldebug ("HNETL5: addService was successful");
00791 }
00792
00793
00794
00795
00796 #define TIME_BLOCK(tick, instr) \
00797 { \
00798 TTicks _time_block_before = CTime::getPerformanceTime(); \
00799 instr ; \
00800 TTicks _time_block_after = CTime::getPerformanceTime(); \
00801 tick += (_time_block_after - _before); \
00802 }
00803
00804 void CUnifiedNetwork::update(TTime timeout)
00805 {
00806 nlassertex(_Initialised == true, ("Try to CUnifiedNetwork::update() whereas it is not initialised yet"));
00807
00808 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
00809
00810 bool enableRetry;
00811
00812
00813 TTime t0 = CTime::getLocalTime ();
00814
00815 if (timeout > 0)
00816 {
00817 if (_NextUpdateTime == 0)
00818 {
00819 _NextUpdateTime = t0 + timeout;
00820 }
00821 else
00822 {
00823 TTime err = t0 - _NextUpdateTime;
00824 _NextUpdateTime += timeout;
00825
00826
00827 while (err > timeout)
00828 {
00829 err -= timeout;
00830 _NextUpdateTime += timeout;
00831 }
00832
00833 timeout -= err;
00834 if (timeout < 0) timeout = 0;
00835 }
00836 }
00837
00838
00839 if ((enableRetry = (t0-_LastRetry > 5000)))
00840 _LastRetry = t0;
00841
00842
00843 if (_NamingServiceAddr.isValid ())
00844 {
00845 if (CNamingClient::connected ())
00846 {
00847 CNamingClient::update ();
00848 }
00849 else if (enableRetry)
00850 {
00851 try
00852 {
00853 vector<CInetAddress> laddr = CInetAddress::localAddresses();
00854 CNamingClient::connect (_NamingServiceAddr, _RecordingState, laddr);
00855
00856 for (uint i = 0; i < laddr.size(); i++)
00857 laddr[i].setPort(_ServerPort);
00858 CNamingClient::resendRegisteration (_Name, laddr, _SId);
00859 }
00860 catch (ESocketConnectionFailed &)
00861 {
00862 nlwarning ("HNETL5: Could not connect to the Naming Service (%s). Retrying in a few seconds...", _NamingServiceAddr.asString().c_str());
00863 }
00864 }
00865 }
00866
00867 while (true)
00868 {
00869
00870 if (_CbServer)
00871 _CbServer->update(0);
00872
00873
00874 for (uint k = 0; k<_UsedConnection.size(); ++k)
00875 {
00876 CUnifiedConnection &uc = _IdCnx[_UsedConnection[k]];
00877 nlassert (uc.State == CUnifiedNetwork::CUnifiedConnection::Ready);
00878 for (uint j = 0; j < uc.Connection.size (); j++)
00879 {
00880 if (!uc.Connection[j].valid())
00881 continue;
00882
00883 if (uc.Connection[j].IsServerConnection)
00884 continue;
00885
00886 if (uc.Connection[j].CbNetBase->connected ())
00887 {
00888 uc.Connection[j].CbNetBase->update(0);
00889 }
00890 else if (enableRetry && uc.AutoRetry)
00891 {
00892 try
00893 {
00894 CCallbackClient *cbc = (CCallbackClient *)uc.Connection[j].CbNetBase;
00895 cbc->connect(uc.ExtAddress[j]);
00896 uc.Connection[j].CbNetBase->getSockId()->setAppId(uc.ServiceId);
00897 nlinfo ("HNETL5: reconnection to %s-%hu success", uc.ServiceName.c_str(), uc.ServiceId);
00898
00899
00900
00901 if (!haveNamedCnx (uc.ServiceName, uc.ServiceId))
00902 addNamedCnx (uc.ServiceName, uc.ServiceId);
00903
00904
00905 if (uc.SendId)
00906 {
00907
00908 CMessage msg("UN_SIDENT");
00909 msg.serial(_Name);
00910
00911 uint16 ssid = _SId;
00912 msg.serial(ssid);
00913 uint8 pos = j;
00914 msg.serial(pos);
00915 msg.serial (uc.IsExternal);
00916 uc.Connection[j].CbNetBase->send (msg, uc.Connection[j].HostId);
00917 }
00918
00919
00920 CUnifiedNetwork::TNameMappedCallback::iterator it = _UpCallbacks.find(uc.ServiceName);
00921 if (it != _UpCallbacks.end())
00922 {
00923
00924 TUnifiedNetCallback cb = (*it).second.first;
00925 cb(uc.ServiceName, uc.ServiceId, (*it).second.second);
00926 }
00927
00928 for (uint c = 0; c < _UpUniCallback.size (); c++)
00929 {
00930 if (_UpUniCallback[c].first != NULL)
00931 _UpUniCallback[c].first (uc.ServiceName, uc.ServiceId, _UpUniCallback[c].second);
00932 }
00933
00934 }
00935 catch (ESocketConnectionFailed &e)
00936 {
00937 nlinfo ("HNETL5: can't connect to %s-%hu now (%s)", uc.ServiceName.c_str(), uc.ServiceId, e.what ());
00938 }
00939 }
00940 }
00941 }
00942
00943 enableRetry = false;
00944
00945
00946 if (CTime::getLocalTime() - t0 > timeout)
00947 break;
00948
00949
00950 nlSleep (1);
00951 }
00952
00953 autoCheck();
00954 }
00955
00956
00957
00958
00959 uint8 CUnifiedNetwork::findConnectionId (uint16 sid, uint8 nid)
00960 {
00961 if (_IdCnx[sid].Connection.size () == 0)
00962 {
00963 nlwarning ("HNETL5: Can't send message to %s because no connection are available", _IdCnx[sid].ServiceName.c_str ());
00964 return 0xFF;
00965 }
00966
00967
00968 uint8 connectionId = _IdCnx[sid].DefaultNetwork;
00969
00970 if (nid == 0xFF)
00971 {
00972
00973
00974 }
00975 else if (nid >= _IdCnx[sid].NetworkConnectionAssociations.size())
00976 {
00977 nlwarning ("HNETL5: No net association for nid %hu, use the default connection %hu", (uint16)nid, (uint16)connectionId);
00978 }
00979 else
00980 {
00981 if (_IdCnx[sid].NetworkConnectionAssociations[nid] >= _IdCnx[sid].Connection.size ())
00982 {
00983 nlwarning ("HNETL5: Can't send message to %s because nid %d point on a bad connection (%d and only have %d cnx), use default connection", _IdCnx[sid].ServiceName.c_str (), nid, connectionId, _IdCnx[sid].Connection.size ());
00984 }
00985 else
00986 {
00987 connectionId = _IdCnx[sid].NetworkConnectionAssociations[nid];
00988 }
00989 }
00990
00991 if (connectionId >= _IdCnx[sid].Connection.size() || !_IdCnx[sid].Connection[connectionId].valid() || !_IdCnx[sid].Connection[connectionId].CbNetBase->connected())
00992 {
00993
00994 nlwarning ("HNETL5: Can't find selected connection id %hu to send message to %s because connection is not valid or connected, find a valid connection id", (uint16)connectionId, _IdCnx[sid].ServiceName.c_str ());
00995
00996 for (connectionId = 0; connectionId < _IdCnx[sid].Connection.size(); connectionId++)
00997 {
00998 if (_IdCnx[sid].Connection[connectionId].valid() && _IdCnx[sid].Connection[connectionId].CbNetBase->connected())
00999 {
01000
01001
01002 break;
01003 }
01004 }
01005
01006 if (connectionId == _IdCnx[sid].Connection.size())
01007 {
01008 nlwarning ("HNETL5: Can't send message to %s because default connection is not exist, valid or connected", _IdCnx[sid].ServiceName.c_str ());
01009 return 0xFF;
01010 }
01011 }
01012 return connectionId;
01013 }
01014
01015
01016
01017
01018
01019
01020 bool CUnifiedNetwork::send(const string &serviceName, const CMessage &msgout, uint8 nid)
01021 {
01022 nlassertex(_Initialised == true, ("Try to CUnifiedNetwork::send(const string&, const CMessage&) whereas it is not initialised yet"));
01023
01024 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
01025
01026 TNameMappedConnection::const_iterator it;
01027 pair<TNameMappedConnection::const_iterator,TNameMappedConnection::const_iterator> range;
01028 range = _NamedCnx.equal_range(serviceName);
01029
01030 bool found = false;
01031 if (range.first != _NamedCnx.end())
01032 {
01033 for (it=range.first; it!=range.second; ++it)
01034 {
01035 uint16 sid = (*it).second;
01036 if (sid >= _IdCnx.size () || _IdCnx[sid].State != CUnifiedNetwork::CUnifiedConnection::Ready)
01037 {
01038
01039
01040 nlwarning ("HNETL5: Can't send to the service '%s' because it was in the _NamedCnx but not in _IdCnx (means that the service is down)", serviceName.c_str ());
01041 return false;
01042 }
01043
01044 found = true;
01045
01046 uint8 connectionId = findConnectionId (sid, nid);
01047 if (connectionId == 0xff)
01048 {
01049 nlwarning ("HNETL5: Can't send message to %hu because no connection available", sid);
01050 found = false;
01051 continue;
01052 }
01053
01054
01055 _IdCnx[sid].Connection[connectionId].CbNetBase->send (msgout, _IdCnx[sid].Connection[connectionId].HostId);
01056 }
01057 }
01058
01059 if (!found)
01060 nlwarning ("HNETL5: can't find service %s to send message %s", serviceName.c_str(), msgout.getName().c_str());
01061
01062 return found;
01063 }
01064
01065 bool CUnifiedNetwork::send(uint16 sid, const CMessage &msgout, uint8 nid)
01066 {
01067 nlassertex(_Initialised == true, ("Try to CUnifiedNetwork::send(uint16, const CMessage&) whereas it is not initialised yet"));
01068
01069 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
01070
01071 if (sid >= _IdCnx.size () || _IdCnx[sid].State != CUnifiedNetwork::CUnifiedConnection::Ready)
01072 {
01073
01074 nlwarning ("HNETL5: Can't send to the service '%hu' because not in _IdCnx", sid);
01075 return false;
01076 }
01077
01078 uint8 connectionId = findConnectionId (sid, nid);
01079 if (connectionId == 0xff)
01080 {
01081 nlwarning ("HNETL5: Can't send to the service '%hu' because no connection available", sid);
01082 return false;
01083 }
01084
01085 _IdCnx[sid].Connection[connectionId].CbNetBase->send (msgout, _IdCnx[sid].Connection[connectionId].HostId);
01086 return true;
01087 }
01088
01089 void CUnifiedNetwork::send(const CMessage &msgout, uint8 nid)
01090 {
01091 nlassertex(_Initialised == true, ("Try to CUnifiedNetwork::send(const CMessage&) whereas it is not initialised yet"));
01092
01093 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
01094
01095 uint i;
01096 for (i=0; i<_IdCnx.size(); ++i)
01097 {
01098 if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::Ready)
01099 {
01100 uint8 connectionId = findConnectionId (i, nid);
01101 if (connectionId == 0xff)
01102 {
01103 nlwarning ("HNETL5: Can't send message to %u because no connection available", i);
01104 continue;
01105 }
01106
01107 _IdCnx[i].Connection[connectionId].CbNetBase->send (msgout, _IdCnx[i].Connection[connectionId].HostId);
01108 }
01109 }
01110 }
01111
01112
01113
01114
01115
01116
01117 void CUnifiedNetwork::addCallbackArray (const TUnifiedCallbackItem *callbackarray, CStringIdArray::TStringId arraysize)
01118 {
01119 uint i;
01120
01121 for (i=0; i<(uint)arraysize; ++i)
01122 _Callbacks.insert(make_pair(string(callbackarray[i].Key),callbackarray[i].Callback));
01123 }
01124
01125
01126 void CUnifiedNetwork::setServiceUpCallback (const string &serviceName, TUnifiedNetCallback cb, void *arg, bool back)
01127 {
01128 if (serviceName == "*")
01129 {
01130 nlassert (cb != NULL);
01131 if (back)
01132 _UpUniCallback.push_back (make_pair(cb, arg));
01133 else
01134 _UpUniCallback.insert (_UpUniCallback.begin(), make_pair(cb, arg));
01135
01136 return;
01137 }
01138
01139 TNameMappedCallback::iterator it = _UpCallbacks.find(serviceName);
01140 if (it == _UpCallbacks.end())
01141 {
01142 TCallbackArgItem ncb;
01143 ncb.first = NULL;
01144 ncb.second = NULL;
01145 it = _UpCallbacks.insert(make_pair(serviceName, ncb));
01146 }
01147
01148 (*it).second.first = cb;
01149 (*it).second.second = arg;
01150 }
01151
01152 void CUnifiedNetwork::setServiceDownCallback (const string &serviceName, TUnifiedNetCallback cb, void *arg, bool back)
01153 {
01154 if (serviceName == "*")
01155 {
01156 nlassert (cb != NULL);
01157 if (back)
01158 _DownUniCallback.push_back (make_pair(cb, arg));
01159 else
01160 _DownUniCallback.insert (_DownUniCallback.begin(), make_pair(cb, arg));
01161
01162 return;
01163 }
01164
01165 TNameMappedCallback::iterator it = _DownCallbacks.find(serviceName);
01166 if (it == _DownCallbacks.end())
01167 {
01168 TCallbackArgItem ncb;
01169 ncb.first = NULL;
01170 ncb.second = NULL;
01171 it = _DownCallbacks.insert(make_pair(serviceName, ncb));
01172 }
01173
01174 (*it).second.first = cb;
01175 (*it).second.second = arg;
01176 }
01177
01178
01179
01180
01181
01182 uint64 CUnifiedNetwork::getBytesSent ()
01183 {
01184 uint64 sent = 0;
01185 uint j;
01186
01187 for (vector<uint16>::iterator it = _UsedConnection.begin (); it != _UsedConnection.end(); it++)
01188 {
01189 if (_IdCnx[(*it)].State == CUnifiedNetwork::CUnifiedConnection::Ready)
01190 for (j=0; j<_IdCnx[(*it)].Connection.size (); ++j)
01191 if(_IdCnx[(*it)].Connection[j].valid () && !_IdCnx[(*it)].Connection[j].IsServerConnection)
01192 sent += _IdCnx[(*it)].Connection[j].CbNetBase->getBytesSent();
01193 }
01194
01195
01196
01197
01198
01199
01200
01201 if(_CbServer)
01202 sent += _CbServer->getBytesSent();
01203 return sent;
01204 }
01205
01206 uint64 CUnifiedNetwork::getBytesReceived ()
01207 {
01208 uint64 received = 0;
01209 uint j;
01210
01211 for (vector<uint16>::iterator it = _UsedConnection.begin (); it != _UsedConnection.end(); it++)
01212 {
01213 if (_IdCnx[(*it)].State == CUnifiedNetwork::CUnifiedConnection::Ready)
01214 for (j=0; j<_IdCnx[(*it)].Connection.size (); ++j)
01215 if(_IdCnx[(*it)].Connection[j].valid () && !_IdCnx[(*it)].Connection[j].IsServerConnection)
01216 received += _IdCnx[(*it)].Connection[j].CbNetBase->getBytesReceived();
01217 }
01218
01219
01220
01221
01222
01223
01224
01225 if (_CbServer)
01226 received += _CbServer->getBytesReceived();
01227 return received;
01228 }
01229
01230 uint64 CUnifiedNetwork::getSendQueueSize ()
01231 {
01232 uint64 sent = 0;
01233 uint j;
01234
01235 for (vector<uint16>::iterator it = _UsedConnection.begin (); it != _UsedConnection.end(); it++)
01236 {
01237 if (_IdCnx[(*it)].State == CUnifiedNetwork::CUnifiedConnection::Ready)
01238 for (j=0; j<_IdCnx[(*it)].Connection.size (); ++j)
01239 if(_IdCnx[(*it)].Connection[j].valid () && !_IdCnx[(*it)].Connection[j].IsServerConnection)
01240 sent += _IdCnx[(*it)].Connection[j].CbNetBase->getSendQueueSize();
01241 }
01242
01243
01244
01245
01246
01247
01248
01249 if (_CbServer)
01250 sent += _CbServer->getSendQueueSize();
01251 return sent;
01252 }
01253
01254 uint64 CUnifiedNetwork::getReceiveQueueSize ()
01255 {
01256 uint64 received = 0;
01257 uint j;
01258
01259 for (vector<uint16>::iterator it = _UsedConnection.begin (); it != _UsedConnection.end(); it++)
01260 {
01261 if (_IdCnx[(*it)].State == CUnifiedNetwork::CUnifiedConnection::Ready)
01262 for (j=0; j<_IdCnx[(*it)].Connection.size (); ++j)
01263 if(_IdCnx[(*it)].Connection[j].valid () && !_IdCnx[(*it)].Connection[j].IsServerConnection)
01264 received += _IdCnx[(*it)].Connection[j].CbNetBase->getReceiveQueueSize();
01265 }
01266
01267
01268
01269
01270
01271
01272
01273 if (_CbServer)
01274 received += _CbServer->getReceiveQueueSize();
01275 return received;
01276 }
01277
01278 CCallbackNetBase *CUnifiedNetwork::getNetBase(const std::string &name, TSockId &host, uint8 nid)
01279 {
01280 nlassertex(_Initialised == true, ("Try to CUnifiedNetwork::getNetBase() whereas it is not initialised yet"));
01281
01282 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
01283
01284 sint count = _NamedCnx.count(name);
01285
01286 if (count <= 0)
01287 {
01288 nlwarning ("HNETL5: couldn't access the service %s", name.c_str());
01289 host = InvalidSockId;
01290 return NULL;
01291 }
01292 else if (count > 1)
01293 {
01294 nlwarning ("HNETL5: %d services %s to getNetBase, returns the first valid", count, name.c_str());
01295 }
01296
01297 TNameMappedConnection::const_iterator itnmc = _NamedCnx.find(name);
01298
01299 uint8 connectionId = findConnectionId ((*itnmc).second, nid);
01300 if (connectionId == 0xff)
01301 {
01302 nlwarning ("Can't getNetBase %s because no connection available", name.c_str());
01303 host = InvalidSockId;
01304 return NULL;
01305 }
01306
01307 host = _IdCnx[(*itnmc).second].Connection[connectionId].HostId;
01308 return _IdCnx[(*itnmc).second].Connection[connectionId].CbNetBase;
01309 }
01310
01311 CCallbackNetBase *CUnifiedNetwork::getNetBase(uint16 sid, TSockId &host, uint8 nid)
01312 {
01313 nlassertex(_Initialised == true, ("Try to CUnifiedNetwork::getNetBase() whereas it is not initialised yet"));
01314
01315 if (ThreadCreator != NLMISC::getThreadId()) nlwarning ("HNETL5: Multithread access but this class is not thread safe thread creator = %u thread used = %u", ThreadCreator, NLMISC::getThreadId());
01316
01317 if (sid >= _IdCnx.size () || _IdCnx[sid].State != CUnifiedNetwork::CUnifiedConnection::Ready)
01318 {
01319 nlwarning ("HNETL5: Can't get net base to the service '%hu' because not in _IdCnx", sid);
01320 host = InvalidSockId;
01321 return NULL;
01322 }
01323
01324 uint8 connectionId = findConnectionId (sid, nid);
01325 if (connectionId == 0xff)
01326 {
01327 nlwarning ("Can't getNetBase %hu because no connection available", sid);
01328 host = InvalidSockId;
01329 return NULL;
01330 }
01331
01332 host = _IdCnx[sid].Connection[connectionId].HostId;
01333 return _IdCnx[sid].Connection[connectionId].CbNetBase;
01334 }
01335
01336 TUnifiedMsgCallback CUnifiedNetwork::findCallback (const std::string &callbackName)
01337 {
01338 TMsgMappedCallback::iterator itcb = _Callbacks.find(callbackName);
01339 if (itcb == _Callbacks.end())
01340 return NULL;
01341 else
01342 return (*itcb).second;
01343 }
01344
01345 bool CUnifiedNetwork::isServiceLocal (const std::string &serviceName)
01346 {
01347
01348 if (serviceName == _Name)
01349 return true;
01350
01351 pair<TNameMappedConnection::const_iterator,TNameMappedConnection::const_iterator> range;
01352 range = _NamedCnx.equal_range(serviceName);
01353
01354 bool found = false;
01355 if (range.first != _NamedCnx.end())
01356 {
01357 uint16 sid = (*(range.first)).second;
01358 return isServiceLocal (sid);
01359 }
01360
01361 return false;
01362 }
01363
01364 bool CUnifiedNetwork::isServiceLocal (uint16 sid)
01365 {
01366
01367 if (sid == _SId)
01368 return true;
01369
01370 if (sid >= _IdCnx.size () || _IdCnx[sid].State != CUnifiedNetwork::CUnifiedConnection::Ready)
01371 {
01372 return false;
01373 }
01374
01375 vector<CInetAddress> laddr = CInetAddress::localAddresses();
01376
01377 for (uint i = 0; i < laddr.size(); i++)
01378 {
01379 for (uint j = 0; j < _IdCnx[sid].ExtAddress.size(); j++)
01380 {
01381 if (_IdCnx[sid].ExtAddress[j].is127001 ())
01382 return true;
01383
01384 if (_IdCnx[sid].ExtAddress[j].internalIPAddress () == laddr[i].internalIPAddress ())
01385 return true;
01386 }
01387 }
01388 return false;
01389 }
01390
01391
01392
01393
01394
01395 CUnifiedNetwork *CUnifiedNetwork::_Instance = NULL;
01396
01397 CUnifiedNetwork *CUnifiedNetwork::getInstance ()
01398 {
01399 if (_Instance == NULL)
01400 _Instance = new CUnifiedNetwork();
01401
01402 return _Instance;
01403 }
01404
01405 bool CUnifiedNetwork::isUsed ()
01406 {
01407 return (_Instance != NULL);
01408 }
01409
01410
01411
01412
01413
01414 CUnifiedNetwork::CUnifiedConnection *CUnifiedNetwork::getUnifiedConnection (uint16 sid)
01415 {
01416 if (sid < _IdCnx.size () && _IdCnx[sid].State == CUnifiedConnection::Ready)
01417 {
01418 if (sid != _IdCnx[sid].ServiceId)
01419 {
01420 AUTOCHECK_DISPLAY ("Sid index %hu is not the same that in the entry %hu", sid, _IdCnx[sid].ServiceId);
01421 return NULL;
01422 }
01423 return &_IdCnx[sid];
01424 }
01425 else
01426 {
01427 nlwarning ("Try to get a bad unified connection (sid %hu is not in the table)", sid);
01428 return NULL;
01429 }
01430 }
01431
01432 void CUnifiedNetwork::autoCheck()
01433 {
01434 uint i, j;
01435
01436 for (i = 0; i < _IdCnx.size (); i++)
01437 {
01438 if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::Ready)
01439 {
01440 _IdCnx[i].AutoCheck = 1;
01441 }
01442 else
01443 {
01444 _IdCnx[i].AutoCheck = 0;
01445 }
01446 }
01447
01448 TNameMappedConnection::iterator itn;
01449 for (itn = _NamedCnx.begin(); itn != _NamedCnx.end(); ++itn)
01450 {
01451 if ((*itn).first != _IdCnx[(*itn).second].ServiceName) AUTOCHECK_DISPLAY ("HLNET5: problem with name syncro between _NameCnx and _IdCnx '%s' '%s' '%d'", (*itn).first.c_str(), _IdCnx[(*itn).second].ServiceName.c_str (), (*itn).second);
01452 if (_IdCnx[(*itn).second].AutoCheck == 0) AUTOCHECK_DISPLAY ("HLNET5: problem with name syncro between _NameCnx '%s' and _IdCnx '%s' '%d'", (*itn).first.c_str(), _IdCnx[(*itn).second].ServiceName.c_str (), (*itn).second);
01453 if (_IdCnx[(*itn).second].AutoCheck > 1) AUTOCHECK_DISPLAY ("HLNET5: problem with name syncro between _NameCnx and _IdCnx '%s' '%d' more than one entry in named with the same name", (*itn).first.c_str(), _IdCnx[(*itn).second].ServiceName.c_str (),(*itn).second);
01454 _IdCnx[(*itn).second].AutoCheck++;
01455 }
01456
01457 for (i = 0; i < _UsedConnection.size (); i++)
01458 {
01459 if (_IdCnx[_UsedConnection[i]].State != CUnifiedNetwork::CUnifiedConnection::Ready) AUTOCHECK_DISPLAY ("HLNET5: problem with the _UsedConnection syncro sid %d is not used in _IdCnx", _UsedConnection[i]);
01460 }
01461
01462 for (i = 0; i < _IdCnx.size (); i++)
01463 {
01464 if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::Ready)
01465 {
01466 for (j = 0; j < _UsedConnection.size (); j++)
01467 {
01468 if (_UsedConnection[j] == i) break;
01469 }
01470 if (j == _UsedConnection.size ()) AUTOCHECK_DISPLAY ("HLNET5: problem with the _UsedConnection syncro sid %d is not in _UsedConnection", i);
01471 }
01472 }
01473
01474 for (i = 0; i < _IdCnx.size (); i++)
01475 {
01476 if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::NotUsed)
01477 {
01478 if (_IdCnx[i].ServiceName != "DEAD") AUTOCHECK_DISPLAY ("HLNET5: sid %d name should be DEAD and is '%s'", i, _IdCnx[i].ServiceName.c_str ());
01479 if (_IdCnx[i].ServiceId != 0xDEAD) AUTOCHECK_DISPLAY ("HLNET5: sid %d sid should be 0xDEAD and is 0x%X", i, _IdCnx[i].ServiceId);
01480 if (!_IdCnx[i].Connection.empty ()) AUTOCHECK_DISPLAY ("HLNET5: sid %d connection size should be 0 and is %d", i, _IdCnx[i].Connection.size ());
01481 if (!_IdCnx[i].ExtAddress.empty ()) AUTOCHECK_DISPLAY ("HLNET5: sid %d ext addr size should be 0 and is %d", i, _IdCnx[i].ExtAddress.size ());
01482 if (_IdCnx[i].AutoCheck != 0) AUTOCHECK_DISPLAY ("HLNET5: sid %d prob with syncro with _NamedCnx", i);
01483 }
01484 else if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::Ready)
01485 {
01486 if (_IdCnx[i].ServiceId != i) AUTOCHECK_DISPLAY ("HNETL5: Bad syncro sid index sid entry for %d %d", i, _IdCnx[i].ServiceId);
01487
01488 if (_IdCnx[i].ServiceName == "DEAD") AUTOCHECK_DISPLAY ("HLNET5: sid %d name should not be DEAD and is '%s'", i, _IdCnx[i].ServiceName.c_str ());
01489 if (_IdCnx[i].ServiceId == 0xDEAD) AUTOCHECK_DISPLAY ("HLNET5: sid %d sid should not be 0xDEAD and is 0x%X", i, _IdCnx[i].ServiceId);
01490 if (!_IdCnx[i].ExtAddress.empty () && _IdCnx[i].Connection.size () > _IdCnx[i].ExtAddress.size()) AUTOCHECK_DISPLAY ("HLNET5: sid %d ext addr size should not be 0 and is %d", i, _IdCnx[i].ExtAddress.size ());
01491
01492 if (_IdCnx[i].AutoRetry == true && _IdCnx[i].Connection.size () > 1) AUTOCHECK_DISPLAY ("HLNET5: sid %d auto retry with more than one connection %d", i, _IdCnx[i].Connection.size ());
01493 if (_IdCnx[i].AutoRetry == true && _IdCnx[i].IsExternal == false) AUTOCHECK_DISPLAY ("HLNET5: sid %d auto retry with internal connection", i);
01494 if (_IdCnx[i].AutoRetry == true && _IdCnx[i].Connection[0].valid() == false) AUTOCHECK_DISPLAY ("HLNET5: sid %d auto retry with invalid connection", i);
01495
01496 for (j = 0; j < _IdCnx[i].Connection.size (); j++)
01497 {
01498 if (_IdCnx[i].Connection[j].valid() && !_IdCnx[i].Connection[j].IsServerConnection && _IdCnx[i].Connection[j].CbNetBase->connected () && _IdCnx[i].Connection[j].getAppId() != i) AUTOCHECK_DISPLAY ("HLNET5: sid %d bad appid %"NL_I64"X", i, _IdCnx[i].Connection[j].getAppId());
01499 }
01500
01501 for (j = 0; j < _IdCnx[i].NetworkConnectionAssociations.size (); j++)
01502 {
01503 if (_IdCnx[i].NetworkConnectionAssociations[j] != 0)
01504 {
01505 if (_NetworkAssociations[j] != _IdCnx[i].ExtAddress[_IdCnx[i].NetworkConnectionAssociations[j]].internalNetAddress ()) AUTOCHECK_DISPLAY ("HLNET5: sid %d nid %d have address 0x%08x and is not the good connection net 0x%08x", i, j, _NetworkAssociations[j], _IdCnx[i].ExtAddress[_IdCnx[i].NetworkConnectionAssociations[j]].internalNetAddress ());
01506 }
01507 }
01508 }
01509 }
01510 }
01511
01512
01513 void CUnifiedNetwork::displayInternalTables (NLMISC::CLog *log)
01514 {
01515 uint i, j;
01516 log->displayNL ("%d Named Connections:", _NamedCnx.size ());
01517 for (TNameMappedConnection::iterator it = _NamedCnx.begin(); it != _NamedCnx.end (); it++)
01518 {
01519 log->displayNL ("> '%s' -> %hu", (*it).first.c_str(), (*it).second);
01520 }
01521
01522 uint nbused = 0;
01523 for (i = 0; i < _IdCnx.size (); i++)
01524 {
01525 if(_IdCnx[i].State != CUnifiedNetwork::CUnifiedConnection::NotUsed)
01526 nbused++;
01527 }
01528
01529 log->displayNL ("%u/%u Unified Connections:", nbused, _IdCnx.size ());
01530 for (i = 0; i < _IdCnx.size (); i++)
01531 {
01532 if(_IdCnx[i].State != CUnifiedNetwork::CUnifiedConnection::NotUsed)
01533 {
01534 log->displayNL ("> %s-%hu %s %s %s (%d extaddr %d cnx)", _IdCnx[i].ServiceName.c_str (), _IdCnx[i].ServiceId, _IdCnx[i].IsExternal?"ext":"int", _IdCnx[i].AutoRetry?"autoretry":"noautoretry", _IdCnx[i].SendId?"sendid":"nosendid", _IdCnx[i].ExtAddress.size (), _IdCnx[i].Connection.size ());
01535 uint maxc = _IdCnx[i].Connection.size ();
01536 if(_IdCnx[i].Connection.size () <= _IdCnx[i].ExtAddress.size ())
01537 maxc = _IdCnx[i].ExtAddress.size ();
01538
01539 for (j = 0; j < maxc; j++)
01540 {
01541 string base;
01542 if(j < _IdCnx[i].ExtAddress.size ())
01543 {
01544 base += _IdCnx[i].ExtAddress[j].asString ();
01545 }
01546 else
01547 {
01548 base += "notvalid";
01549 }
01550
01551 string ext;
01552 if(j < _IdCnx[i].Connection.size () && _IdCnx[i].Connection[j].valid())
01553 {
01554 if(_IdCnx[i].Connection[j].IsServerConnection)
01555 {
01556 ext += "server ";
01557 }
01558 else
01559 {
01560 ext += "client ";
01561 }
01562 ext += _IdCnx[i].Connection[j].CbNetBase->getSockId (_IdCnx[i].Connection[j].HostId)->asString ();
01563 ext += " appid:" + toString(_IdCnx[i].Connection[j].getAppId());
01564 if (_IdCnx[i].Connection[j].CbNetBase->connected ())
01565 ext += " connected";
01566 else
01567 ext += " notconnected";
01568 }
01569 else
01570 {
01571 ext += "notvalid";
01572 }
01573
01574 log->displayNL (" - %s %s", base.c_str (), ext.c_str ());
01575 }
01576 for (j = 0; j < _IdCnx[i].NetworkConnectionAssociations.size (); j++)
01577 {
01578 log->displayNL (" * nid %d -> cnxn %hu", j, (uint16)_IdCnx[i].NetworkConnectionAssociations[j]);
01579 }
01580 }
01581 }
01582
01583 log->displayNL ("%u Used Unified Connections:", _UsedConnection.size());
01584 for (i = 0; i < _UsedConnection.size (); i++)
01585 {
01586 log->displayNL ("> %hu", _UsedConnection[i]);
01587 }
01588
01589 log->displayNL ("%u Network Associations:", _NetworkAssociations.size());
01590 for (i = 0; i < _NetworkAssociations.size (); i++)
01591 {
01592 log->displayNL ("> 0x%08x -> '%s'", _NetworkAssociations[i], internalIPAddressToString (_NetworkAssociations[i]).c_str ());
01593 }
01594 }
01595
01596 bool CUnifiedNetwork::haveNamedCnx (const std::string &name, uint16 sid)
01597 {
01598 CUnifiedNetwork::TNameMappedConnection::iterator it;
01599 pair<CUnifiedNetwork::TNameMappedConnection::iterator,CUnifiedNetwork::TNameMappedConnection::iterator> range;
01600 range = _NamedCnx.equal_range(name);
01601
01602 if (range.first != range.second)
01603 {
01604 for (it=range.first; it!=range.second && (*it).second!=sid; ++it)
01605 ;
01606
01607 return (it != range.second);
01608 }
01609 return false;
01610 }
01611
01612 void CUnifiedNetwork::addNamedCnx (const std::string &name, uint16 sid)
01613 {
01614
01615 CUnifiedNetwork::TNameMappedConnection::iterator it;
01616 pair<CUnifiedNetwork::TNameMappedConnection::iterator,CUnifiedNetwork::TNameMappedConnection::iterator> range;
01617 range = _NamedCnx.equal_range(name);
01618
01619 if (range.first != range.second)
01620 {
01621 for (it=range.first; it!=range.second && (*it).second!=sid; ++it)
01622 ;
01623
01624 if (it != range.second)
01625 {
01626 AUTOCHECK_DISPLAY ("Try to add 2 times the same connection %s-%hu", name.c_str(), sid);
01627 return;
01628 }
01629 }
01630
01631
01632
01633 _NamedCnx.insert(make_pair(name, sid));
01634
01635 allstuffs += "+name "+name+"-"+toString(sid)+"\n";
01636 test.displayNL ("+name %s-%hu", name.c_str (), sid);
01637 }
01638
01639 void CUnifiedNetwork::removeNamedCnx (const std::string &name, uint16 sid)
01640 {
01641
01642 CUnifiedNetwork::TNameMappedConnection::iterator it;
01643 pair<CUnifiedNetwork::TNameMappedConnection::iterator,CUnifiedNetwork::TNameMappedConnection::iterator> range;
01644 range = _NamedCnx.equal_range(name);
01645
01646
01647 if (range.first == range.second)
01648 {
01649 AUTOCHECK_DISPLAY ("The unified connection %s-%hu wasn't on the _NamedCnx", name.c_str(), sid);
01650 return;
01651 }
01652
01653
01654 for (it=range.first; it!=range.second && (*it).second!=sid; ++it)
01655 ;
01656
01657
01658 if (it == range.second)
01659 {
01660 AUTOCHECK_DISPLAY ("The unified connection %s-%hu wasn't on the _NamedCnx", name.c_str(), sid);
01661 return;
01662 }
01663
01664
01665 _NamedCnx.erase(it);
01666
01667 allstuffs += "-name "+name+"-"+toString(sid)+"\n";
01668 test.displayNL ("-name %s-%hu", name.c_str (), sid);
01669 }
01670
01671 void CUnifiedNetwork::addNetworkAssociation (const string &networkName, uint8 nid)
01672 {
01673 if (nid >= _NetworkAssociations.size ())
01674 _NetworkAssociations.resize (nid+1, 0xFF);
01675
01676 _NetworkAssociations[nid] = stringToInternalIPAddress (networkName);
01677 nlinfo ("HNETL5: Associate network '%s' 0x%08x '%s' to nid %hu", networkName.c_str(), _NetworkAssociations[nid], internalIPAddressToString (_NetworkAssociations[nid]).c_str(), (uint16)nid);
01678 }
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691 static bool createMessage (CMessage &msgout, const vector<string> &args, CLog &log)
01692 {
01693 for (uint i = 2; i < args.size (); i+=2)
01694 {
01695 string type = args[i+0];
01696 string value = args[i+1];
01697
01698 if (type == "s8") { sint8 v = atoi(value.c_str()); msgout.serial (v); }
01699 else if (type == "s16") { sint16 v = atoi(value.c_str()); msgout.serial (v); }
01700 else if (type == "s32") { sint32 v = atoi(value.c_str()); msgout.serial (v); }
01701 else if (type == "s64") { sint64 v = atoi(value.c_str()); msgout.serial (v); }
01702 else if (type == "u8") { uint8 v = atoi(value.c_str()); msgout.serial (v); }
01703 else if (type == "u16") { uint16 v = atoi(value.c_str()); msgout.serial (v); }
01704 else if (type == "u32") { uint32 v = atoi(value.c_str()); msgout.serial (v); }
01705 else if (type == "u64") { uint64 v = atoi(value.c_str()); msgout.serial (v); }
01706 else if (type == "f") { float v = (float)atof(value.c_str()); msgout.serial (v); }
01707 else if (type == "d") { double v = atof(value.c_str()); msgout.serial (v); }
01708 else if (type == "b") { bool v = atoi(value.c_str()) == 1; msgout.serial (v); }
01709 else if (type == "s") { msgout.serial (value); }
01710 else { log.displayNL ("type '%s' is not a valid type", type.c_str()); return false; }
01711 }
01712 return true;
01713 }
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728 NLMISC_COMMAND(msgin, "Simulate an input message from another service (ex: msgin 128 REGISTER u32 10 b 1 f 1.5)", "<ServiceName>|<ServiceId> <MessageName> [<ParamType> <Param>]*")
01729 {
01730 if(args.size() < 2) return false;
01731
01732 if (!CUnifiedNetwork::isUsed ())
01733 {
01734 log.displayNL("Can't do that because the service doesn't use CUnifiedNetwork");
01735 return false;
01736 }
01737
01738 uint16 serviceId = atoi (args[0].c_str());
01739 string serviceName = args[0].c_str();
01740 string messageName = args[1].c_str();
01741
01742 if (serviceId > 255)
01743 {
01744 log.displayNL ("Service Id %d must be between [1;255]", serviceId);
01745 return false;
01746 }
01747
01748 if ((args.size()-2) % 2 != 0)
01749 {
01750 log.displayNL ("The number of parameter must be a multiple of 2");
01751 return false;
01752 }
01753
01754 CMessage msg (messageName);
01755 msg.clear ();
01756
01757 if (!createMessage (msg, args, log))
01758 return false;
01759
01760 msg.invert ();
01761
01762 TUnifiedMsgCallback cb = CUnifiedNetwork::getInstance()->findCallback (messageName);
01763
01764 if (cb == NULL)
01765 {
01766 log.displayNL ("Callback for message '%s' is not found", messageName.c_str());
01767 }
01768 else
01769 {
01770 cb (msg, serviceName, serviceId);
01771 }
01772
01773
01774 return true;
01775 }
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790 NLMISC_COMMAND(msgout, "Send a message to a specified service (ex: msgout 128 REGISTER u32 10 b 1 f 1.5)", "<ServiceName>|<ServiceId> <MessageName> [<ParamType> <Param>]*")
01791 {
01792 if(args.size() < 2) return false;
01793
01794 if (!CUnifiedNetwork::isUsed ())
01795 {
01796 log.displayNL("Can't do that because the service doesn't use CUnifiedNetwork");
01797 return false;
01798 }
01799
01800 uint16 serviceId = atoi (args[0].c_str());
01801 string serviceName = args[0].c_str();
01802 string messageName = args[1].c_str();
01803
01804 if (serviceId > 255)
01805 {
01806 log.displayNL ("Service Id %d must be between [1;255]", serviceId);
01807 return false;
01808 }
01809
01810 if ((args.size()-2) % 2 != 0)
01811 {
01812 log.displayNL ("The number of parameter must be a multiple of 2");
01813 return false;
01814 }
01815
01816 CMessage msg (messageName);
01817
01818 if (!createMessage (msg, args, log))
01819 return false;
01820
01821 TSockId host = InvalidSockId;
01822 CCallbackNetBase *cnb = NULL;
01823
01824 if (serviceId != 0)
01825 cnb = CUnifiedNetwork::getInstance()->getNetBase ((uint8)serviceId, host);
01826 else
01827 cnb = CUnifiedNetwork::getInstance()->getNetBase (serviceName, host);
01828
01829 if (cnb == NULL)
01830 {
01831 log.displayNL ("'%s' is a bad <ServiceId> or <ServiceName>", args[0].c_str());
01832 return false;
01833 }
01834
01835 cnb->send (msg, host);
01836
01837 return true;
01838 }
01839
01840 NLMISC_COMMAND(l5InternalTables, "Displays internal table of network layer5", "")
01841 {
01842 if(args.size() != 0) return false;
01843
01844 if (!CUnifiedNetwork::isUsed ())
01845 {
01846 log.displayNL("Can't display internal table because layer5 is not used");
01847 return false;
01848 }
01849
01850 CUnifiedNetwork::getInstance ()->displayInternalTables(&log);
01851
01852 return true;
01853 }
01854
01855 NLMISC_COMMAND(isServiceLocal, "Says if a service is local or not compare with this service", "<sid>|<service name>")
01856 {
01857 if(args.size() != 1) return false;
01858
01859 if (!CUnifiedNetwork::isUsed ())
01860 {
01861 log.displayNL("Can't do that because the service doesn't use CUnifiedNetwork");
01862 return false;
01863 }
01864
01865 uint16 sid = atoi (args[0].c_str ());
01866 if (sid > 0)
01867 {
01868 log.displayNL ("Service %s-%hu and sid %s are %son the same computer", CUnifiedNetwork::getInstance ()->_Name.c_str(), (uint16)CUnifiedNetwork::getInstance ()->_SId, args[0].c_str(), CUnifiedNetwork::getInstance ()->isServiceLocal (sid)?"":"not ");
01869 }
01870 else
01871 {
01872 log.displayNL ("Service %s-%hu and %s are %son the same computer", CUnifiedNetwork::getInstance ()->_Name.c_str(), (uint16)CUnifiedNetwork::getInstance ()->_SId, args[0].c_str(), CUnifiedNetwork::getInstance ()->isServiceLocal (args[0])?"":"not ");
01873 }
01874
01875 return true;
01876 }
01877
01878 }