# 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  

transport_class.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000-2002 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NeL Network Services.
00010  * NEVRAX NeL Network Services 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 Network Services 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 Network Services; 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 /*
00027  * Limitations: Not threadsafe, not reentrant.
00028  */
00029 
00030 
00031 //
00032 // Includes
00033 //
00034 
00035 #include "stdnet.h"
00036 
00037 #include "nel/misc/types_nl.h"
00038 #include "nel/misc/debug.h"
00039 #include "nel/misc/entity_id.h"
00040 #include "nel/misc/sheet_id.h"
00041 
00042 #include "nel/net/unified_network.h"
00043 
00044 #include "nel/net/transport_class.h"
00045 
00046 //
00047 // Namespace
00048 //
00049 
00050 using namespace std;
00051 using namespace NLMISC;
00052 using namespace NLNET;
00053 
00054 namespace NLNET {
00055 
00056 //
00057 // Variables
00058 //
00059 
00060 uint CTransportClass::Mode = 0; // 0=nothing 1=read 2=write 3=register
00061 
00062 map<string, CTransportClass::CRegisteredClass>  CTransportClass::LocalRegisteredClass;  // registered class that are in my program
00063 
00064 CTransportClass::CRegisteredClass       CTransportClass::TempRegisteredClass;
00065 
00066 NLNET::CMessage CTransportClass::TempMessage;
00067 
00068 vector<CTransportClass::CRegisteredBaseProp *> CTransportClass::DummyProp;
00069 
00070 bool CTransportClass::Init = false;
00071 
00072 
00073 //
00074 // Functions
00075 //
00076 
00077 string typeToString (CTransportClass::TProp type)
00078 {
00079         string conv[] = {
00080                 "PropUInt8", "PropUInt16", "PropUInt32", "PropUInt64",
00081                 "PropSInt8", "PropSInt16", "PropSInt32", "PropSInt64",
00082                 "PropBool", "PropFloat", "PropDouble", "PropString", "PropEntityId", "PropSheetId", "PropUKN" };
00083 
00084         if (type > CTransportClass::PropUKN)
00085                 return "<InvalidType>";
00086         return conv[type];
00087 }
00088 
00089 void CTransportClass::displayDifferentClass (uint8 sid, const string &className, const vector<CRegisteredBaseProp> &otherClass, const vector<CRegisteredBaseProp *> &myClass)
00090 {
00091         nlinfo ("Service with sid %u send me the TransportClass '%s' with differents properties:", sid, className.c_str());
00092         uint i;
00093         nlinfo ("  My local TransportClass is:");
00094         for (i = 0; i < myClass.size(); i++)
00095         {
00096                 nlinfo ("    Property: %d Name: '%s' type: '%s'", i, myClass[i]->Name.c_str(), typeToString(myClass[i]->Type).c_str());
00097         }
00098 
00099         nlinfo ("  The other side TransportClass is:");
00100         for (i = 0; i < otherClass.size(); i++)
00101         {
00102                 nlinfo ("    Property: %d Name: '%s' type: '%s'", i, otherClass[i].Name.c_str(), typeToString(otherClass[i].Type).c_str());
00103         }
00104 }
00105 
00106 void CTransportClass::registerOtherSideClass (uint8 sid, TOtherSideRegisteredClass &osrc)
00107 {
00108         for (TOtherSideRegisteredClass::iterator it = osrc.begin(); it != osrc.end (); it++)
00109         {
00110                 // find the class name in the map
00111 
00112                 TRegisteredClass::iterator res = LocalRegisteredClass.find ((*it).first);
00113                 if (res == LocalRegisteredClass.end ())
00114                 {
00115                         // it s a class that the other side have but not me, can't send this class
00116                         nlwarning ("CTransportClass::registerOtherSideClass(): the other side class '%s' is not registered in my system, skip it", (*it).first.c_str());
00117                         continue;
00118                 }
00119 
00120                 if (sid >= (*res).second.Instance->States.size ())
00121                         (*res).second.Instance->States.resize (sid+1);
00122 
00123                 (*res).second.Instance->States[sid].clear ();
00124 
00125                 for (sint j = 0; j < (sint)(*it).second.size (); j++)
00126                 {
00127                         // check each prop to see the correspondance
00128 
00129                         // try to find the prop name in the array
00130                         uint k;
00131                         for (k = 0; k < (*res).second.Instance->Prop.size(); k++)
00132                         {
00133                                 if ((*it).second[j].Name == (*res).second.Instance->Prop[k]->Name)
00134                                 {
00135                                         if ((*it).second[j].Type != (*res).second.Instance->Prop[k]->Type)
00136                                         {
00137                                                 nlwarning ("Property '%s' of the class '%s' have not the same type in the 2 sides (%s %s)", (*it).second[j].Name.c_str(), (*it).first.c_str(), typeToString((*it).second[j].Type).c_str(), typeToString((*res).second.Instance->Prop[k]->Type).c_str());
00138                                         }
00139                                         break;
00140                                 }
00141                         }
00142                         if (k == (*res).second.Instance->Prop.size())
00143                         {
00144                                 // not found, put -1
00145                                 (*res).second.Instance->States[sid].push_back (make_pair (-1, (*it).second[j].Type));
00146                         }
00147                         else
00148                         {
00149                                 // same, store the index
00150                                 (*res).second.Instance->States[sid].push_back (make_pair (k, PropUKN));
00151                         }
00152                 }
00153 
00154                 // check if the version are the same
00155                 if ((*it).second.size () != (*res).second.Instance->Prop.size ())
00156                 {
00157                         // 2 class don't have the same number of prop => different class => display class
00158                         displayDifferentClass (sid, (*it).first.c_str(), (*it).second, (*res).second.Instance->Prop);
00159                 }
00160                 else
00161                 {
00162                         // check if the prop are same
00163                         for (uint i = 0; i < (*res).second.Instance->Prop.size (); i++)
00164                         {
00165                                 if ((*res).second.Instance->Prop[i]->Name != (*it).second[i].Name)
00166                                 {
00167                                         // different name => different class => display class
00168                                         displayDifferentClass (sid, (*it).first.c_str(), (*it).second, (*res).second.Instance->Prop);
00169                                         break;
00170                                 }
00171                                 else if ((*res).second.Instance->Prop[i]->Type != (*it).second[i].Type)
00172                                 {
00173                                         // different type => different class => display class
00174                                         displayDifferentClass (sid, (*it).first.c_str(), (*it).second, (*res).second.Instance->Prop);
00175                                         break;
00176                                 }
00177                         }
00178                 }
00179         }
00180 
00181         displayLocalRegisteredClass ();
00182 }
00183 
00184 
00185 void CTransportClass::registerClass (CTransportClass &instance)
00186 {
00187         nlassert (Init);
00188         nlassert (Mode == 0);
00189 
00190         // set the mode to register
00191         Mode = 3;
00192         
00193         // clear the current class
00194         TempRegisteredClass.clear ();
00195 
00196         // set the instance pointer
00197         TempRegisteredClass.Instance = &instance;
00198 
00199         // fill name and props
00200         TempRegisteredClass.Instance->description ();
00201 
00202         // add the new registered class in the array
00203         LocalRegisteredClass[TempRegisteredClass.Instance->Name] = TempRegisteredClass;
00204 
00205         // set to mode none
00206         Mode = 0;
00207 }
00208 
00209 void CTransportClass::unregisterClass ()
00210 {
00211         for (TRegisteredClass::iterator it = LocalRegisteredClass.begin(); it != LocalRegisteredClass.end (); it++)
00212         {
00213                 for (uint j = 0; j < (*it).second.Instance->Prop.size (); j++)
00214                 {
00215                         delete (*it).second.Instance->Prop[j];
00216                 }
00217                 (*it).second.Instance->Prop.clear ();
00218                 (*it).second.Instance = NULL;
00219         }
00220         LocalRegisteredClass.clear ();
00221 }
00222 
00223 void CTransportClass::displayLocalRegisteredClass (CRegisteredClass &c)
00224 {
00225         nldebug ("NETTC:  > %s", c.Instance->Name.c_str());
00226         for (uint j = 0; j < c.Instance->Prop.size (); j++)
00227         {
00228                 nldebug ("NETTC:    > %s %s", c.Instance->Prop[j]->Name.c_str(), typeToString(c.Instance->Prop[j]->Type).c_str());
00229         }
00230 
00231         for (uint l = 0; l < c.Instance->States.size (); l++)
00232         {
00233                 if (c.Instance->States[l].size () != 0)
00234                 {
00235                         nldebug ("NETTC:      > sid: %u", l);
00236                         for (uint k = 0; k < c.Instance->States[l].size (); k++)
00237                         {
00238                                 nldebug ("NETTC:      - %d type : %s", c.Instance->States[l][k].first, typeToString(c.Instance->States[l][k].second).c_str());
00239                         }
00240                 }
00241         }
00242 }
00243 
00244 void CTransportClass::displayLocalRegisteredClass ()
00245 {
00246         nldebug ("NETTC:> LocalRegisteredClass:");
00247         for (TRegisteredClass::iterator it = LocalRegisteredClass.begin(); it != LocalRegisteredClass.end (); it++)
00248         {
00249                 displayLocalRegisteredClass ((*it).second);
00250         }
00251 }
00252 
00253 void cbTCReceiveMessage (CMessage &msgin, const string &name, uint16 sid)
00254 {
00255         nldebug ("NETTC: cbReceiveMessage");
00256 
00257         CTransportClass::TempMessage = msgin;
00258 
00259         string className;
00260         CTransportClass::TempMessage.serial (className);
00261 
00262         CTransportClass::TRegisteredClass::iterator it = CTransportClass::LocalRegisteredClass.find (className);
00263         if (it == CTransportClass::LocalRegisteredClass.end ())
00264         {
00265                 nlwarning ("receive unknown class '%s', skip it", className.c_str());
00266                 return;
00267         }
00268 
00269         nlassert ((*it).second.Instance != NULL);
00270         (*it).second.Instance->read (name, (uint8)sid);
00271 }
00272 
00273 void cbTCReceiveOtherSideClass (CMessage &msgin, const string &name, uint16 sid)
00274 {
00275         nldebug ("NETTC: cbReceiveOtherSideClass");
00276 
00277         CTransportClass::TOtherSideRegisteredClass osrc;
00278 
00279         uint32 nbClass;
00280         msgin.serial (nbClass);
00281 
00282         nldebug ("NETTC: %d class", nbClass);
00283 
00284         for (uint i = 0; i < nbClass; i++)
00285         {
00286                 string className;
00287                 msgin.serial (className);
00288 
00289                 osrc.push_back(make_pair (className, vector<CTransportClass::CRegisteredBaseProp>()));
00290 
00291                 uint32 nbProp;
00292                 msgin.serial (nbProp);
00293 
00294                 nldebug ("NETTC:   %s (%d prop)", className.c_str(), nbProp);
00295 
00296                 for (uint j = 0; j < nbProp; j++)
00297                 {
00298                         CTransportClass::CRegisteredBaseProp prop;
00299                         msgin.serial (prop.Name);
00300                         msgin.serialEnum (prop.Type);
00301                         nldebug ("NETTC:     %s %s", prop.Name.c_str(), typeToString(prop.Type).c_str());
00302                         osrc[osrc.size()-1].second.push_back (prop);
00303                 }
00304         }
00305 
00306         // we have the good structure
00307         CTransportClass::registerOtherSideClass ((uint8)sid, osrc);
00308 }
00309 
00310 static TUnifiedCallbackItem CallbackArray[] =
00311 {
00312         { "CT_LRC", cbTCReceiveOtherSideClass },
00313         { "CT_MSG", cbTCReceiveMessage },
00314 };
00315 
00316 void cbTCUpService (const std::string &serviceName, uint16 sid, void *arg)
00317 {
00318         nldebug ("NETTC: CTransportClass Service %s %d is up", serviceName.c_str(), sid);
00319         if (sid >= 256)
00320                 return;
00321         CTransportClass::sendLocalRegisteredClass ((uint8)sid);
00322 }
00323 
00324 void CTransportClass::init ()
00325 {
00326         // this isn't an error!
00327         if (Init) return;
00328 
00329         // filter all my debug stuffs
00330         DebugLog->addNegativeFilter ("NETTC");
00331 
00332 
00333         CUnifiedNetwork::getInstance()->addCallbackArray (CallbackArray, sizeof (CallbackArray) / sizeof (CallbackArray[0]));
00334 
00335         // create an instance of all d'ifferent prop types
00336 
00337         DummyProp.resize (PropUKN);
00338 
00339         nlassert (PropUInt8 < PropUKN); DummyProp[PropUInt8] = new CTransportClass::CRegisteredProp<uint8>;
00340         nlassert (PropUInt16 < PropUKN); DummyProp[PropUInt16] = new CTransportClass::CRegisteredProp<uint16>;
00341         nlassert (PropUInt32 < PropUKN); DummyProp[PropUInt32] = new CTransportClass::CRegisteredProp<uint32>;
00342         nlassert (PropUInt64 < PropUKN); DummyProp[PropUInt64] = new CTransportClass::CRegisteredProp<uint64>;
00343         nlassert (PropSInt8 < PropUKN); DummyProp[PropSInt8] = new CTransportClass::CRegisteredProp<sint8>;
00344         nlassert (PropSInt16 < PropUKN); DummyProp[PropSInt16] = new CTransportClass::CRegisteredProp<sint16>;
00345         nlassert (PropSInt32 < PropUKN); DummyProp[PropSInt32] = new CTransportClass::CRegisteredProp<sint32>;
00346         nlassert (PropSInt64 < PropUKN); DummyProp[PropSInt64] = new CTransportClass::CRegisteredProp<sint64>;
00347         nlassert (PropBool < PropUKN); DummyProp[PropBool] = new CTransportClass::CRegisteredProp<bool>;
00348         nlassert (PropFloat < PropUKN); DummyProp[PropFloat] = new CTransportClass::CRegisteredProp<float>;
00349         nlassert (PropDouble < PropUKN); DummyProp[PropDouble] = new CTransportClass::CRegisteredProp<double>;
00350         nlassert (PropString < PropUKN); DummyProp[PropString] = new CTransportClass::CRegisteredProp<string>;
00351         nlassert (PropEntityId < PropUKN); DummyProp[PropEntityId] = new CTransportClass::CRegisteredProp<CEntityId>;
00352         nlassert (PropSheetId < PropUKN); DummyProp[PropSheetId] = new CTransportClass::CRegisteredProp<CSheetId>;
00353 
00354         // we have to know when a service comes, so add callback (put the callback before all other one because we have to send this message first)
00355         CUnifiedNetwork::getInstance()->setServiceUpCallback("*", cbTCUpService, NULL, false);
00356 
00357         Init = true;
00358 }
00359 
00360 void CTransportClass::release ()
00361 {
00362         unregisterClass ();
00363 
00364         for (uint i = 0; i < DummyProp.size (); i++)
00365         {
00366                 delete DummyProp[i];
00367         }
00368         DummyProp.clear ();
00369 }
00370 
00371 void CTransportClass::createLocalRegisteredClassMessage ()
00372 {
00373         TempMessage.clear ();
00374         if (TempMessage.isReading())
00375                 TempMessage.invert();
00376         TempMessage.setType ("CT_LRC");
00377 
00378         uint32 nbClass = LocalRegisteredClass.size ();
00379         TempMessage.serial (nbClass);
00380 
00381         for (TRegisteredClass::iterator it = LocalRegisteredClass.begin(); it != LocalRegisteredClass.end (); it++)
00382         {
00383                 nlassert ((*it).first == (*it).second.Instance->Name);
00384 
00385                 TempMessage.serial ((*it).second.Instance->Name);
00386 
00387                 uint32 nbProp = (*it).second.Instance->Prop.size ();
00388                 TempMessage.serial (nbProp);
00389 
00390                 for (uint j = 0; j < (*it).second.Instance->Prop.size (); j++)
00391                 {
00392                         // send the name and the type of the prop
00393                         TempMessage.serial ((*it).second.Instance->Prop[j]->Name);
00394                         TempMessage.serialEnum ((*it).second.Instance->Prop[j]->Type);
00395                 }
00396         }
00397 }
00398 
00399 } // NLNET