From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/unified__network_8cpp-source.html | 1947 ++++++++++++++++++++ 1 file changed, 1947 insertions(+) create mode 100644 docs/doxygen/nel/unified__network_8cpp-source.html (limited to 'docs/doxygen/nel/unified__network_8cpp-source.html') diff --git a/docs/doxygen/nel/unified__network_8cpp-source.html b/docs/doxygen/nel/unified__network_8cpp-source.html new file mode 100644 index 00000000..818512db --- /dev/null +++ b/docs/doxygen/nel/unified__network_8cpp-source.html @@ -0,0 +1,1947 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

unified_network.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2002 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+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 //#define AUTOCHECK_DISPLAY CUnifiedNetwork::getInstance()->displayInternalTables (), nlerror
+00045 
+00046 // ace retirer ca
+00047 static string allstuffs;
+00048 
+00049 //
+00050 // Callbacks from NAMING SERVICE
+00051 //
+00052 
+00053 // when a service registers
+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                 // it's me! don't add me!!!
+00068                 return;
+00069         }
+00070 
+00071         // add the unified connection
+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         // set the list of external addresses
+00086 
+00087         nlassert (!addr.empty());
+00088 
+00089         uni->_IdCnx[sid].ExtAddress = addr;
+00090 
+00091         // associate nid with ext address
+00092         uni->_IdCnx[sid].setupNetworkAssociation (uni->_NetworkAssociations, uni->_DefaultNetwork);
+00093 }
+00094 
+00095 // when a service unregisters
+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         // get the service connection
+00104         CUnifiedNetwork *uni = CUnifiedNetwork::getInstance();
+00105 
+00106         CUnifiedNetwork::CUnifiedConnection *uc = uni->getUnifiedConnection (sid);
+00107         if (uc == 0) return;    // should never happen, the getUnifiedConnection() will generate a AUTOCHECK_DISPLAY
+00108 
+00109         // call the user callback
+00110         CUnifiedNetwork::TNameMappedCallback::iterator  it2 = uni->_DownCallbacks.find(uc->ServiceName);
+00111 
+00112         if (it2 != uni->_DownCallbacks.end())
+00113         {
+00114                 // call it
+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                 // set all connection to dead, now, all messages received on this socket will be ignored and closed
+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                 // It's the first connection that added the _NamedCnx so if there s no connection, no need to
+00136                 // remove entry in _NamedCnx
+00137                 //
+00138 
+00139                 uni->removeNamedCnx (uc->ServiceName, uc->ServiceId);
+00140         }
+00141 
+00142         // remove the _UsedConnection
+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         // reset the unified connection
+00156         uc->reset ();
+00157 }
+00158 
+00159 
+00160 //
+00161 // Callbacks from connection/disconnection services
+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                                         // If it s a external service with no auto retry, remove the connection
+00199                                         
+00200                                         // call the user callback
+00201                                         CUnifiedNetwork::TNameMappedCallback::iterator  it2 = uni->_DownCallbacks.find(uc->ServiceName);
+00202 
+00203                                         if (it2 != uni->_DownCallbacks.end())
+00204                                         {
+00205                                                 // call it
+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                                         // remove the _UsedConnection
+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                                 // reset the connection
+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                                                         // we have to remove the stuffs now because HostId will not be accessible later
+00245                                                         uc->Connection[i].reset();
+00246                                                 }
+00247                                                 else
+00248                                                 {
+00249                                                         // if it s a client, we can't delete now because the callback client is currently in use
+00250                                                         // only disconnect
+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 // Callback from identication services
+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         // recover the service name and id
+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         // add a new connection to the list
+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:              // add the new unified connection
+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         // add the connection to the already inserted unified connection
+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         // If the connection is external, we'll never receive the ExtAddress by the naming service, so add it manually
+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         // todo ace temp to savoir comment c est possible ce cas la
+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         // send the callback to the user with the first connection
+00367         if (uni->_IdCnx[inSid].Connection.size () == 1)
+00368         {
+00369                 // insert the name in the map to be able to send message with the name
+00370                 uni->addNamedCnx (inSName, inSid);
+00371 
+00372                 // now we warn the user
+00373                 CUnifiedNetwork::TNameMappedCallback::iterator  it = uni->_UpCallbacks.find(inSName);
+00374                 if (it != uni->_UpCallbacks.end())
+00375                 {
+00376                         // call it
+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 // the callbacks wrapper
+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                 // the callback doesn't exist
+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         //DebugLog->addNegativeFilter ("HNETL5");
+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         // if the address isn't 0, uses the naming service
+00460         if (_NamingServiceAddr.isValid ())
+00461         {
+00462                 // connect the callback to know when a new service comes in or goes down
+00463                 CNamingClient::setRegistrationBroadcastCallback(uNetRegistrationBroadcast);
+00464                 CNamingClient::setUnregistrationBroadcastCallback(uNetUnregistrationBroadcast);
+00465 
+00466                 // connect to the naming service (may generate a ESocketConnectionFailed exception)
+00467                 CNamingClient::connect(_NamingServiceAddr, _RecordingState, laddr);
+00468 
+00469                 if (port == 0)
+00470                         port = CNamingClient::queryServicePort ();
+00471         }
+00472 
+00473         // setup the server callback only if server port != 0, otherwise there's no server callback
+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);                                // the service ident callback
+00482                 _CbServer->setDefaultCallback(uncbMsgProcessing);                               // the default callback wrapper
+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                 // register the service
+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                 // get the services list
+00529                 const list<CNamingClient::CServiceEntry>        &services = CNamingClient::getRegisteredServices();
+00530 
+00531                 // connects to the registered services
+00532                 list<CNamingClient::CServiceEntry>::const_iterator      its;
+00533 
+00534                 // don't connect to itself
+00535                 for (its = services.begin(); its != services.end(); ++its)
+00536                 {
+00537                         if (_SId != (*its).SId)
+00538                         {
+00539                                 // add service with name, address, ident, not external, service id, and not autoretry (obsolete)
+00540                                 // we put the last true because the name callback should already inserted it by uNetRegistrationBroadcast()
+00541                                 addService((*its).Name, (*its).Addr, true, false, (*its).SId, false, true);
+00542                         }
+00543                         else
+00544                         {
+00545                                 // don't process services received after mine because they'll connect to me
+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         // disconnect all clients
+00560         if(_CbServer)
+00561         {
+00562                 _CbServer->disconnect(InvalidSockId);
+00563                 delete _CbServer;
+00564                 _CbServer = 0;
+00565         }
+00566 
+00567         // disconnect all connections to servers
+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         // clear all other data
+00587         _IdCnx.clear();
+00588         _UsedConnection.clear ();
+00589         _NamedCnx.clear();
+00590         _UpCallbacks.clear();
+00591         _DownCallbacks.clear();
+00592         _Callbacks.clear();
+00593 
+00594         // disconnect the connection with the naming service
+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         // add the entry in the unified connection table
+00626 
+00627         if (sid >= _IdCnx.size())
+00628                 _IdCnx.resize(sid+1);
+00629 
+00630         CUnifiedConnection      *uc = &_IdCnx[sid];
+00631 
+00632         // at this point it s possible that the service already added in the _IdCnx by the uNetRegistrationBroadcast()
+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                 // If the entry already set, check that all is correct
+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         // associate nid with ext address
+00655         uc->setupNetworkAssociation (_NetworkAssociations, _DefaultNetwork);
+00656 
+00657         // connect to all connection
+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                 // first we have to look if we have a network that can established the connection
+00670 
+00671                 uint j = 0;
+00672                 // it s 127.0.0.1, it s ok
+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                                         // it's ok, we can try
+00680                                         break;
+00681                                 }
+00682                         }
+00683 
+00684                         // If we don't found a valid network, we'll try with the first one.
+00685                         // It's happen, for example, when you try to connect to a service that is not in the network but use IP translation
+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                 // create a new connection with the service, setup callback and connect
+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                         // send identification to the service
+00731                         CMessage        msg("UN_SIDENT");
+00732                         msg.serial(_Name);
+00733                         uint16          ssid = _SId;
+00734                         if (uc->IsExternal)
+00735                         {
+00736                                 // in the case that the service is external, we can't send our sid because the external service can
+00737                                 // have other connectin with the same sid (for example, LS can have 2 WS with same sid => sid = 0 and leave
+00738                                 // the other side to find a good number
+00739                                 ssid = 0;
+00740                         }
+00741                         msg.serial(ssid);       // serializes a 16 bits service id
+00742                         uint8 pos = j;
+00743                         msg.serial(pos);        // send the position in the connection table
+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                 // add the name only if at least one connection is ok
+00770                 addNamedCnx (name, sid);
+00771 
+00772                 // call the connection callback associated to this service
+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;    // true every 5 seconds to reconnect if necessary
+00811 
+00812         // Compute the real timeout based on the next update timeout
+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                         // if we are too late, resync to the next value
+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         // check if we need to retry to connect to the client
+00839         if ((enableRetry = (t0-_LastRetry > 5000)))
+00840                 _LastRetry = t0;
+00841 
+00842         // Try to reconnect to the naming service if connection lost
+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                                 // re-register the service
+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                 // update all server connections
+00870                 if (_CbServer)
+00871                         _CbServer->update(0);
+00872 
+00873                 // update all client connections
+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                                                 // add the name only if at least one connection is ok
+00901                                                 if (!haveNamedCnx (uc.ServiceName, uc.ServiceId))
+00902                                                         addNamedCnx (uc.ServiceName, uc.ServiceId);
+00903 
+00904                                                 // resend the identification is necessary
+00905                                                 if (uc.SendId)
+00906                                                 {
+00907                                                         // send identification to the service
+00908                                                         CMessage        msg("UN_SIDENT");
+00909                                                         msg.serial(_Name);
+00910 
+00911                                                         uint16          ssid = _SId;
+00912                                                         msg.serial(ssid);       // serializes a 16 bits service id
+00913                                                         uint8 pos = j;
+00914                                                         msg.serial(pos);        // send the position in the connection table
+00915                                                         msg.serial (uc.IsExternal);
+00916                                                         uc.Connection[j].CbNetBase->send (msg, uc.Connection[j].HostId);
+00917                                                 }
+00918 
+00919                                                 // call the user callback
+00920                                                 CUnifiedNetwork::TNameMappedCallback::iterator  it = _UpCallbacks.find(uc.ServiceName);
+00921                                                 if (it != _UpCallbacks.end())
+00922                                                 {
+00923                                                         // call it
+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                 // If it's the end, don't nlSleep()
+00946                 if (CTime::getLocalTime() - t0 > timeout)
+00947                         break;
+00948                 
+00949                 // Enable windows multithreading before rescanning all connections
+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         // by default, connection id will be the default one
+00968         uint8 connectionId = _IdCnx[sid].DefaultNetwork;
+00969 
+00970         if (nid == 0xFF)
+00971         {
+00972                 // it s often appen because they didn't set a good network configuration, so it s in debug to disable it easily
+00973                 //nldebug ("HNETL5: nid %hu, will use the default connection %hu", (uint16)nid, (uint16)connectionId);
+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                 // there's a problem with the selected connectionID, so try to find a valid one
+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                                 // we found one at last, use this one
+01001                                 //nldebug ("HNETL5: Ok, we found a valid connectionid, use %hu",  (uint16)connectionId);
+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                                 // It often happen when the service is down (connection broke and the naming not already say that it s down)
+01039                                 // In this case, just warn
+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)       // failed
+01048                         {
+01049                                 nlwarning ("HNETL5: Can't send message to %hu because no connection available", sid);
+01050                                 found = false;
+01051                                 continue;
+01052                         }
+01053 
+01054                         //nldebug ("HNETL5: send message to %s using nid %d cnx %d / %s", serviceName.c_str (), nid, connectionId, connectionId<_IdCnx[sid].ExtAddress.size ()?_IdCnx[sid].ExtAddress[connectionId].asString().c_str():"???");
+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                 // happen when trying to send a message to an unknown service id
+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)       // failed
+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)       // failed
+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 /*      for (i=0; i<_IdCnx.size(); ++i)
+01196                 if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::Ready)
+01197                         for (j=0; j<_IdCnx[i].Connection.size (); ++j)
+01198                                 if(_IdCnx[i].Connection[j].valid () && !_IdCnx[i].Connection[j].IsServerConnection)
+01199                                         sent += _IdCnx[i].Connection[j].CbNetBase->getBytesSent();
+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 /*      for (i=0; i<_IdCnx.size(); ++i)
+01220                 if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::Ready)
+01221                         for (j=0; j<_IdCnx[i].Connection.size (); ++j)
+01222                                 if(_IdCnx[i].Connection[j].valid () && !_IdCnx[i].Connection[j].IsServerConnection)
+01223                                         received += _IdCnx[i].Connection[j].CbNetBase->getBytesReceived();
+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 /*      for (i=0; i<_IdCnx.size(); ++i)
+01244                 if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::Ready)
+01245                         for (j=0; j<_IdCnx[i].Connection.size (); ++j)
+01246                                 if(_IdCnx[i].Connection[j].valid () && !_IdCnx[i].Connection[j].IsServerConnection)
+01247                                         sent += _IdCnx[i].Connection[j].CbNetBase->getSendQueueSize();
+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 /*      for (i=0; i<_IdCnx.size(); ++i)
+01268                 if (_IdCnx[i].State == CUnifiedNetwork::CUnifiedConnection::Ready)
+01269                         for (j=0; j<_IdCnx[i].Connection.size (); ++j)
+01270                                 if(_IdCnx[i].Connection[j].valid () && !_IdCnx[i].Connection[j].IsServerConnection)
+01271                                         received += _IdCnx[i].Connection[j].CbNetBase->getReceiveQueueSize();
+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)       // failed
+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)       // failed
+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         // it s me, of course we are local
+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         // it s me, of course we are local
+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         // check if not already inserted
+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         // insert the name in the map to be able to send message with the name
+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         // get all map nodes of that service name
+01642         CUnifiedNetwork::TNameMappedConnection::iterator                                                                                        it;
+01643         pair<CUnifiedNetwork::TNameMappedConnection::iterator,CUnifiedNetwork::TNameMappedConnection::iterator> range;
+01644         range = _NamedCnx.equal_range(name);
+01645 
+01646         // assume not empty
+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         // select good service id
+01654         for (it=range.first; it!=range.second && (*it).second!=sid; ++it)
+01655                 ;
+01656 
+01657         // assume id exists
+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         // remove service for map
+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 // Commands
+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  * Simulate a message that comes from the network.
+01717  *
+01718  * for the bool (b type), you must set the value to 1 or 0
+01719  * for the string (s type), we don't manage space inside a string
+01720  * for stl containers, you have first to put a u32 type that is the size of the container and after all elements
+01721  * (ex: if you want to put a vector<uint16> that have 3 elements: u32 3 u16 10 u16 11 u16 12)
+01722  *
+01723  * ex: msgin 128 REGISTER u32 10 u32 541 u32 45
+01724  * You'll receive a fake message REGISTER that seems to come from the service number 128 with 3 uint32.
+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  * Create a message and send it to the specified service
+01779  *
+01780  * for the bool (b type), you must set the value to 1 or 0
+01781  * for the string (s type), we don't manage space inside a string
+01782  * for stl containers, you have first to put a u32 type that is the size of the container and after all elements
+01783  * (ex: if you want to put a vector<uint16> that have 3 elements: u32 3 u16 10 u16 11 u16 12)
+01784  *
+01785  * ex: msgout 128 REGISTER u32 10 u32 541 u32 45
+01786  * You'll send a real message REGISTER to the service number 128 with 3 uint32.
+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 } // NLNET
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1