00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "stdnet.h"
00032
00033 #include "nel/net/naming_client.h"
00034 #include "nel/net/callback_client.h"
00035 #include "nel/net/service.h"
00036
00037
00038
00039
00040
00041
00042 using namespace std;
00043 using namespace NLMISC;
00044
00045
00046 namespace NLNET {
00047
00048
00049
00050
00051
00052 CCallbackClient *CNamingClient::_Connection = NULL;
00053 CNamingClient::TRegServices CNamingClient::_RegisteredServices;
00054
00055 static TBroadcastCallback _RegistrationBroadcastCallback = NULL;
00056 static TBroadcastCallback _UnregistrationBroadcastCallback = NULL;
00057
00058 uint CNamingClient::_ThreadId = 0xFFFFFFFF;
00059
00060 TServiceId CNamingClient::_MySId = 0;
00061
00062
00063 std::list<CNamingClient::CServiceEntry> CNamingClient::RegisteredServices;
00064 NLMISC::CMutex CNamingClient::RegisteredServicesMutex("CNamingClient::RegisteredServicesMutex");
00065
00066 void CNamingClient::setRegistrationBroadcastCallback (TBroadcastCallback cb)
00067 {
00068 _RegistrationBroadcastCallback = cb;
00069 }
00070
00071 void CNamingClient::setUnregistrationBroadcastCallback (TBroadcastCallback cb)
00072 {
00073 _UnregistrationBroadcastCallback = cb;
00074 }
00075
00076
00077
00078
00079
00080 static bool Registered;
00081 static TServiceId RegisteredSuccess;
00082 static TServiceId *RegisteredSID = NULL;
00083
00084 static void cbRegister (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00085 {
00086 nlassert(RegisteredSID != NULL);
00087
00088 msgin.serial (RegisteredSuccess);
00089 if (RegisteredSuccess)
00090 {
00091 msgin.serial (*RegisteredSID);
00092
00093
00094 cbRegisterBroadcast (msgin, from, netbase);
00095 }
00096 Registered = true;
00097 }
00098
00099
00100
00101 static bool QueryPort;
00102 static uint16 QueryPortPort;
00103
00104 static void cbQueryPort (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00105 {
00106 msgin.serial (QueryPortPort);
00107 QueryPort = true;
00108 }
00109
00110
00111
00112
00113
00114 void cbRegisterBroadcast (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00115 {
00116 TServiceId size;
00117 string name;
00118 TServiceId sid;
00119 vector<CInetAddress> addr;
00120
00121 msgin.serial (size);
00122
00123 for (TServiceId i = 0; i < size; i++)
00124 {
00125 msgin.serial (name);
00126 msgin.serial (sid);
00127 msgin.serialCont (addr);
00128
00129
00130
00131 std::vector<CInetAddress> addrs;
00132 CNamingClient::find (sid, addrs);
00133
00134 if (addrs.size() == 0)
00135 {
00136 CNamingClient::RegisteredServicesMutex.enter ();
00137 CNamingClient::RegisteredServices.push_back (CNamingClient::CServiceEntry (name, sid, addr));
00138 CNamingClient::RegisteredServicesMutex.leave ();
00139
00140 nlinfo ("NC: Registration Broadcast of the service %s-%hu '%s'", name.c_str(), (uint16)sid, vectorCInetAddressToString(addr).c_str());
00141
00142 if (_RegistrationBroadcastCallback != NULL)
00143 _RegistrationBroadcastCallback (name, sid, addr);
00144 }
00145 else if (addrs.size() == 1)
00146 {
00147 CNamingClient::RegisteredServicesMutex.enter ();
00148 for (std::list<CNamingClient::CServiceEntry>::iterator it = CNamingClient::RegisteredServices.begin(); it != CNamingClient::RegisteredServices.end (); it++)
00149 {
00150 if (sid == (*it).SId)
00151 {
00152 (*it).Name = name;
00153 (*it).Addr = addr;
00154 break;
00155 }
00156 }
00157 CNamingClient::RegisteredServicesMutex.leave ();
00158 nlinfo ("NC: Registration Broadcast (update) of the service %s-%hu '%s'", name.c_str(), (uint16)sid, addr[0].asString().c_str());
00159 }
00160 else
00161 {
00162 nlstop;
00163 }
00164 }
00165
00166
00167
00168
00169 }
00170
00171
00172
00173 void cbUnregisterBroadcast (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00174 {
00175 string name;
00176 TServiceId sid;
00177 vector<CInetAddress> addrs;
00178
00179 msgin.serial (name);
00180 msgin.serial (sid);
00181
00182
00183
00184 CNamingClient::RegisteredServicesMutex.enter ();
00185 for (std::list<CNamingClient::CServiceEntry>::iterator it = CNamingClient::RegisteredServices.begin(); it != CNamingClient::RegisteredServices.end (); it++)
00186 {
00187 if ((*it).SId == sid)
00188 {
00189
00190 nlassertex ((*it).Name == name, ("%s %s",(*it).Name.c_str(), name.c_str()));
00191
00192 addrs = (*it).Addr;
00193
00194 CNamingClient::RegisteredServices.erase (it);
00195 break;
00196 }
00197 }
00198 CNamingClient::RegisteredServicesMutex.leave ();
00199
00200 nlinfo ("NC: Unregistration Broadcast of the service %s-%hu", name.c_str(), (uint16)sid);
00201
00202
00203
00204 CMessage msgout (CNamingClient::_Connection->getSIDA(), "ACK_UNI");
00205 msgout.serial (sid);
00206 CNamingClient::_Connection->send (msgout);
00207
00208
00209 if(CNamingClient::_MySId == sid)
00210 {
00211 nlwarning ("Naming Service asked me to leave, I leave!");
00212 IService::getInstance()->exit();
00213 return;
00214 }
00215
00216 if (_UnregistrationBroadcastCallback != NULL)
00217 _UnregistrationBroadcastCallback (name, sid, addrs);
00218
00219
00220 }
00221
00222
00223
00224 static TCallbackItem NamingClientCallbackArray[] =
00225 {
00226 { "RG", cbRegister },
00227 { "QP", cbQueryPort },
00228
00229 { "RGB", cbRegisterBroadcast },
00230 { "UNB", cbUnregisterBroadcast },
00231 };
00232
00233 void CNamingClient::connect( const CInetAddress &addr, CCallbackNetBase::TRecordingState rec, const vector<CInetAddress> &addresses )
00234 {
00235 nlassert (_Connection == NULL || _Connection != NULL && !_Connection->connected ());
00236 _ThreadId = getThreadId ();
00237
00238 if (_Connection == NULL)
00239 {
00240 _Connection = new CCallbackClient( rec, "naming_client.nmr" );
00241 _Connection->addCallbackArray (NamingClientCallbackArray, sizeof (NamingClientCallbackArray) / sizeof (NamingClientCallbackArray[0]));
00242 }
00243
00244 _Connection->connect (addr);
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 }
00259
00260
00261 void CNamingClient::disconnect ()
00262 {
00263 checkThreadId ();
00264
00265 if (_Connection != NULL)
00266 {
00267 if (_Connection->connected ())
00268 {
00269 _Connection->disconnect ();
00270 }
00271 delete _Connection;
00272 _Connection = NULL;
00273 }
00274
00275
00276
00277 }
00278
00279 string CNamingClient::info ()
00280 {
00281 string res;
00282
00283 if (connected ())
00284 {
00285 res = "connected to ";
00286 res += _Connection->remoteAddress().asString();
00287 }
00288 else
00289 {
00290 res = "Not connected";
00291 }
00292
00293 return res;
00294 }
00295
00296 bool CNamingClient::registerService (const std::string &name, const std::vector<CInetAddress> &addr, TServiceId &sid)
00297 {
00298 checkThreadId ();
00299 nlassert (_Connection != NULL && _Connection->connected ());
00300
00301 CMessage msgout (_Connection->getSIDA(), "RG");
00302 msgout.serial (const_cast<std::string&>(name));
00303 msgout.serialCont (const_cast<vector<CInetAddress>&>(addr));
00304 sid = 0;
00305 msgout.serial (sid);
00306 _Connection->send (msgout);
00307
00308
00309 Registered = false;
00310 RegisteredSID = &sid;
00311 while (!Registered)
00312 {
00313 _Connection->update (-1);
00314 nlSleep (1);
00315 }
00316 if (RegisteredSuccess)
00317 {
00318 _MySId = sid;
00319 _RegisteredServices.insert (make_pair (*RegisteredSID, name));
00320 nldebug ("NC: Registered service %s-%hu at %s", name.c_str(), (uint16)sid, addr[0].asString().c_str());
00321 }
00322 else
00323 {
00324 nlerror ("NC: Naming service refused to register service %s at %s", name.c_str(), addr[0].asString().c_str());
00325 }
00326
00327 RegisteredSID = NULL;
00328
00329 return RegisteredSuccess == 1;
00330 }
00331
00332 bool CNamingClient::registerServiceWithSId (const std::string &name, const std::vector<CInetAddress> &addr, TServiceId sid)
00333 {
00334 checkThreadId ();
00335 nlassert (_Connection != NULL && _Connection->connected ());
00336
00337 CMessage msgout (_Connection->getSIDA(), "RG");
00338 msgout.serial (const_cast<std::string&>(name));
00339 msgout.serialCont (const_cast<vector<CInetAddress>&>(addr));
00340 msgout.serial (sid);
00341 _Connection->send (msgout);
00342
00343
00344 Registered = false;
00345 RegisteredSID = &sid;
00346 while (!Registered)
00347 {
00348 _Connection->update (-1);
00349 nlSleep (1);
00350 }
00351 if (RegisteredSuccess)
00352 {
00353 _MySId = sid;
00354 _RegisteredServices.insert (make_pair (*RegisteredSID, name));
00355 nldebug ("NC: Registered service with sid %s-%hu at %s", name.c_str(), (uint16)RegisteredSID, addr[0].asString().c_str());
00356 }
00357 else
00358 {
00359 nlerror ("NC: Naming service refused to register service with sid %s at %s", name.c_str(), addr[0].asString().c_str());
00360 }
00361
00362 return RegisteredSuccess == 1;
00363 }
00364
00365 void CNamingClient::resendRegisteration (const std::string &name, const std::vector<CInetAddress> &addr, TServiceId sid)
00366 {
00367 checkThreadId ();
00368 nlassert (_Connection != NULL && _Connection->connected ());
00369
00370 CMessage msgout (_Connection->getSIDA(), "RRG");
00371 msgout.serial (const_cast<std::string&>(name));
00372 msgout.serialCont (const_cast<vector<CInetAddress>&>(addr));
00373 msgout.serial (sid);
00374 _Connection->send (msgout);
00375 }
00376
00377 void CNamingClient::unregisterService (TServiceId sid)
00378 {
00379 checkThreadId ();
00380 nlassert (_Connection != NULL && _Connection->connected ());
00381
00382 CMessage msgout (_Connection->getSIDA(), "UNI");
00383 msgout.serial (sid);
00384 _Connection->send (msgout);
00385
00386 nldebug ("NC: Unregistering service %s-%hu", _RegisteredServices[sid].c_str(), sid);
00387 _RegisteredServices.erase (sid);
00388 }
00389
00390 void CNamingClient::unregisterAllServices ()
00391 {
00392 checkThreadId ();
00393 nlassert (_Connection != NULL && _Connection->connected ());
00394
00395 while (!_RegisteredServices.empty())
00396 {
00397 TRegServices::iterator irs = _RegisteredServices.begin();
00398 TServiceId sid = (*irs).first;
00399 unregisterService (sid);
00400 }
00401 }
00402
00403 uint16 CNamingClient::queryServicePort ()
00404 {
00405 checkThreadId ();
00406 nlassert (_Connection != NULL && _Connection->connected ());
00407
00408 CMessage msgout (_Connection->getSIDA(), "QP");
00409 _Connection->send (msgout);
00410
00411
00412 QueryPort = false;
00413 while (!QueryPort)
00414 {
00415 _Connection->update (-1);
00416 nlSleep (1);
00417 }
00418
00419 nlinfo ("NC: Received the answer of the query port (%hu)", QueryPortPort);
00420
00421 return QueryPortPort;
00422 }
00423
00424 bool CNamingClient::lookup (const std::string &name, CInetAddress &addr)
00425 {
00426 nlassert (_Connection != NULL && _Connection->connected ());
00427
00428 vector<CInetAddress> addrs;
00429 find (name, addrs);
00430
00431 if (addrs.size()==0)
00432 return false;
00433
00434 nlassert (addrs.size()==1);
00435 addr = addrs[0];
00436
00437 return true;
00438 }
00439
00440 bool CNamingClient::lookup (TServiceId sid, CInetAddress &addr)
00441 {
00442 nlassert (_Connection != NULL && _Connection->connected ());
00443
00444 vector<CInetAddress> addrs;
00445 find (sid, addrs);
00446
00447 if (addrs.size()==0)
00448 return false;
00449
00450 nlassert (addrs.size()==1);
00451 addr = addrs[0];
00452
00453 return true;
00454 }
00455
00457 bool CNamingClient::lookupAlternate (const std::string &name, CInetAddress &addr)
00458 {
00459 nlassert (_Connection != NULL && _Connection->connected ());
00460
00461
00462
00463 RegisteredServicesMutex.enter ();
00464 for (std::list<CServiceEntry>::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
00465 {
00466 if ((*it).Addr[0] == addr)
00467 {
00468 RegisteredServices.erase (it);
00469 break;
00470 }
00471 }
00472 RegisteredServicesMutex.leave ();
00473
00474 vector<CInetAddress> addrs;
00475 find (name, addrs);
00476
00477 if (addrs.size()==0)
00478 return false;
00479
00480 nlassert (addrs.size()==1);
00481 addr = addrs[0];
00482
00483 return true;
00484 }
00485
00486 void CNamingClient::lookupAll (const std::string &name, std::vector<CInetAddress> &addrs)
00487 {
00488 nlassert (_Connection != NULL && _Connection->connected ());
00489
00490 find (name, addrs);
00491 }
00492
00493 bool CNamingClient::lookupAndConnect (const std::string &name, CCallbackClient &sock)
00494 {
00495 nlassert (_Connection != NULL && _Connection->connected ());
00496
00497
00498 CInetAddress servaddr;
00499
00500
00501 if (!CNamingClient::lookup (name, servaddr))
00502 return false;
00503
00504 do
00505 {
00506 try
00507 {
00508
00509 sock.connect (servaddr);
00510
00511
00512 return true;
00513 }
00514 catch (ESocketConnectionFailed &e)
00515 {
00516 nldebug( "Connection to %s failed: %s, tring another service if available", servaddr.asString().c_str(), e.what() );
00517
00518
00519 if (!CNamingClient::lookupAlternate (name, servaddr))
00520 return false;
00521 }
00522 }
00523 while (true);
00524 }
00525
00526
00527
00528 void CNamingClient::update ()
00529 {
00530 checkThreadId ();
00531
00532 if (_Connection != NULL && _Connection->connected ())
00533 _Connection->update ();
00534 }
00535
00536 void CNamingClient::checkThreadId ()
00537 {
00538 if (getThreadId () != _ThreadId)
00539 {
00540 nlerror ("You try to access to the CNamingClient with 2 differents thread (%d and %d)", _ThreadId, getThreadId());
00541 }
00542 }
00543
00544
00545
00546
00547
00548
00549 NLMISC_COMMAND(services, "displays registered services", "")
00550 {
00551 if(args.size() != 0) return false;
00552
00553 CNamingClient::displayRegisteredServices (&log);
00554
00555 return true;
00556 }
00557
00558 }