00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "stdnet.h"
00037
00038 #include "nel/misc/string_id_array.h"
00039 #include "nel/misc/time_nl.h"
00040
00041 #include "nel/net/naming_client.h"
00042
00043 #include "nel/net/callback_client.h"
00044 #include "nel/net/callback_server.h"
00045
00046 #include "nel/net/naming_client.h"
00047
00048 #include "nel/net/net_manager.h"
00049
00050 using namespace std;
00051 using namespace NLMISC;
00052
00053 namespace NLNET {
00054
00055
00056 CNetManager::TBaseMap CNetManager::_BaseMap;
00057
00058 CCallbackNetBase::TRecordingState CNetManager::_RecordingState;
00059
00060 TTime CNetManager::_NextUpdateTime = 0;
00061
00062 static void nmNewConnection (TSockId from, void *arg)
00063 {
00064 nlassert (arg != NULL);
00065 CBaseStruct *basest = (CBaseStruct *)arg;
00066
00067 nldebug("HNETL4: nmNewConnection() from service '%s'", basest->Name.c_str ());
00068
00069
00070 if (basest->ConnectionCallback != NULL)
00071 basest->ConnectionCallback (basest->Name, from, basest->ConnectionCbArg);
00072 }
00073
00074 static void nmNewDisconnection (TSockId from, void *arg)
00075 {
00076 nlassert (arg != NULL);
00077 CBaseStruct *basest = (CBaseStruct *)arg;
00078
00079 nldebug("HNETL4: nmNewDisconnection() from service '%s'", basest->Name.c_str ());
00080
00081
00082 if (basest->DisconnectionCallback != NULL)
00083 basest->DisconnectionCallback (basest->Name, from, basest->DisconnectionCbArg);
00084
00086
00087
00088 if (basest->Type != CBaseStruct::Server)
00089 {
00090 nlassert (basest->NetBase.size() == 1);
00091 basest->NetBase[0]->getSIDA ().clear ();
00092 }
00093 }
00094
00095
00096
00097 void CNetManager::createConnection(CBaseStruct &Base, const CInetAddress &Addr, const string& name)
00098 {
00099 uint i;
00100 for (i = 0; i < Base.NetBase.size (); i++)
00101 {
00102 if (!Base.NetBase[i]->connected ())
00103 {
00104 break;
00105 }
00106 }
00107 if (i == Base.NetBase.size ())
00108 {
00109 CCallbackClient *cc = new CCallbackClient( _RecordingState, name+string(".nmr") );
00110 Base.NetBase.push_back (cc);
00111 }
00112
00113 CCallbackClient *cc = dynamic_cast<CCallbackClient *>(Base.NetBase[i]);
00114
00115 cc->CCallbackNetBase::setDisconnectionCallback (nmNewDisconnection, (void*) &Base);
00116
00117 try
00118 {
00119 cc->connect (Addr);
00120
00121 if (Base.ConnectionCallback != NULL)
00122 Base.ConnectionCallback (Base.Name, cc->getSockId(), Base.ConnectionCbArg);
00123 }
00124 catch (ESocketConnectionFailed &e)
00125 {
00126 nlinfo ("HNETL4: can't connect now (%s)", e.what ());
00127 }
00128 }
00129
00130
00131 void RegistrationBroadcast (const std::string &name, TServiceId sid, const vector<CInetAddress> &addr)
00132 {
00133 nldebug("HNETL4: RegistrationBroadcast() of service %s-%hu", name.c_str (), (uint16)sid);
00134
00135
00136 for (CNetManager::ItBaseMap itbm = CNetManager::_BaseMap.begin (); itbm != CNetManager::_BaseMap.end (); itbm++)
00137 {
00138 if ((*itbm).second.Type == CBaseStruct::Client && !(*itbm).second.NetBase[0]->connected())
00139 {
00140 if (name == (*itbm).first)
00141 {
00142
00143
00144 CNetManager::createConnection ((*itbm).second, addr[0], name);
00145 }
00146 }
00147 else if ((*itbm).second.Type == CBaseStruct::Group)
00148 {
00149
00150 for (uint i = 0; i < (*itbm).second.ServiceNames.size (); i++)
00151 {
00152 if ((*itbm).second.ServiceNames[i] == name)
00153 {
00154
00155 CNetManager::createConnection ((*itbm).second, addr[0], name);
00156 break;
00157 }
00158 }
00159 }
00160 }
00161
00162 }
00163
00164 static void UnregistrationBroadcast (const std::string &name, TServiceId sid, const vector<CInetAddress> &addr)
00165 {
00166 nldebug("HNETL4: UnregistrationBroadcast() of service %s-%hu", name.c_str (), (uint16)sid);
00167 }
00168
00169 void CNetManager::init (const CInetAddress *addr, CCallbackNetBase::TRecordingState rec )
00170 {
00171 if (addr == NULL) return;
00172
00173 _RecordingState = rec;
00174
00175
00176
00177 vector<CInetAddress> laddr = CInetAddress::localAddresses();
00178 CNamingClient::connect( *addr, _RecordingState, laddr );
00179
00180
00181 CNamingClient::setRegistrationBroadcastCallback (RegistrationBroadcast);
00182 CNamingClient::setUnregistrationBroadcastCallback (UnregistrationBroadcast);
00183 }
00184
00185 void CNetManager::release ()
00186 {
00187 if (CNamingClient::connected ())
00188 CNamingClient::disconnect ();
00189
00190 for (ItBaseMap itbm = _BaseMap.begin (); itbm != _BaseMap.end (); itbm++)
00191 {
00192 for (uint32 i = 0; i < (*itbm).second.NetBase.size(); i++)
00193 {
00194 (*itbm).second.NetBase[i]->disconnect ();
00195 delete (*itbm).second.NetBase[i];
00196 }
00197 }
00198 _BaseMap.clear ();
00199 }
00200
00201 void CNetManager::addServer (const std::string &serviceName, uint16 servicePort, bool external)
00202 {
00203 TServiceId sid = 0;
00204 addServer (serviceName, servicePort, sid, external);
00205 }
00206
00207 void CNetManager::addServer (const std::string &serviceName, uint16 servicePort, TServiceId &sid, bool external)
00208 {
00209 nldebug ("HNETL4: Adding server '%s' in CNetManager", serviceName.c_str ());
00210 ItBaseMap itbm = find (serviceName);
00211
00212
00213 nlassert ((*itbm).second.NetBase.empty());
00214
00215 CCallbackServer *cs = new CCallbackServer( _RecordingState, serviceName+string(".nmr") );
00216 (*itbm).second.NetBase.push_back (cs);
00217
00218 (*itbm).second.Type = CBaseStruct::Server;
00219
00220
00221
00222 cs->setConnectionCallback (nmNewConnection, (void*) &((*itbm).second));
00223 cs->CCallbackNetBase::setDisconnectionCallback (nmNewDisconnection, (void*) &((*itbm).second));
00224
00225 if (servicePort == 0)
00226 {
00227 nlassert (CNamingClient::connected ());
00228 servicePort = CNamingClient::queryServicePort ();
00229 }
00230
00231 cs->init (servicePort);
00232
00233
00234
00235 if (CNamingClient::connected () && !external)
00236 {
00237
00238
00239 vector<CInetAddress> addr = CInetAddress::localAddresses();
00240 for (uint i = 0; i < addr.size(); i++)
00241 addr[i].setPort(servicePort);
00242
00243 if (sid == 0)
00244 {
00245 CNamingClient::registerService (serviceName, addr, sid);
00246 }
00247 else
00248 {
00249 CNamingClient::registerServiceWithSId (serviceName, addr, sid);
00250 }
00251 }
00252 nlinfo ("HNETL4: Server '%s' added, registered and listen to port %hu", serviceName.c_str (), servicePort);
00253 }
00254
00255
00256 void CNetManager::addClient (const std::string &serviceName, const std::string &addr, bool autoRetry)
00257 {
00258 nldebug ("HNETL4: Adding client '%s' with addr '%s' in CNetManager", serviceName.c_str (), addr.c_str());
00259 ItBaseMap itbm = find (serviceName);
00260
00261
00262 (*itbm).second.Type = CBaseStruct::ClientWithAddr;
00263 (*itbm).second.AutoRetry = autoRetry;
00264
00265 if ((*itbm).second.ServiceNames.empty())
00266 {
00267 (*itbm).second.ServiceNames.push_back(addr);
00268 }
00269 else
00270 {
00271 (*itbm).second.ServiceNames[0] = addr;
00272 }
00273
00274 nlassert ((*itbm).second.NetBase.size() < 2);
00275
00276 createConnection ((*itbm).second, addr, serviceName);
00277 }
00278
00279
00280 void CNetManager::addClient (const std::string &serviceName)
00281 {
00282 nlassert (CNamingClient::connected ());
00283 nldebug ("HNETL4: Adding client '%s' in CNetManager", serviceName.c_str ());
00284 ItBaseMap itbm = find (serviceName);
00285
00286
00287 nlassert ((*itbm).second.NetBase.empty());
00288
00289 CCallbackClient *cc = new CCallbackClient( _RecordingState, serviceName+string(".nmr") );
00290 (*itbm).second.NetBase.push_back (cc);
00291
00292 (*itbm).second.Type = CBaseStruct::Client;
00293
00294 cc->CCallbackNetBase::setDisconnectionCallback (nmNewDisconnection, (void*) &((*itbm).second));
00295
00296
00297 if (CNamingClient::lookupAndConnect (serviceName, *cc))
00298 {
00299
00300 if ((*itbm).second.ConnectionCallback != NULL)
00301 (*itbm).second.ConnectionCallback (serviceName, cc->getSockId(), (*itbm).second.ConnectionCbArg);
00302 }
00303 }
00304
00305
00306
00307 void CNetManager::addGroup (const std::string &groupName, const std::string &serviceName)
00308 {
00309 nlassert (CNamingClient::connected ());
00310 nldebug ("HNETL4: Adding '%s' to group '%s' in CNetManager", serviceName.c_str (), groupName.c_str());
00311 ItBaseMap itbm = find (groupName);
00312
00313 (*itbm).second.Type = CBaseStruct::Group;
00314
00315
00316 vector<string>::iterator it = std::find ((*itbm).second.ServiceNames.begin(), (*itbm).second.ServiceNames.end(), serviceName);
00317 nlassert (it == (*itbm).second.ServiceNames.end());
00318
00319 (*itbm).second.ServiceNames.push_back(serviceName);
00320
00321
00322
00323 vector<CInetAddress> addrs;
00324 CNamingClient::lookupAll (serviceName, addrs);
00325
00326
00327 for (uint i = 0; i < addrs.size (); i++)
00328 {
00329 createConnection ((*itbm).second, addrs[i], serviceName);
00330 }
00331 }
00332
00333
00334
00335 NLMISC::CStringIdArray &CNetManager::getSIDA (const std::string &serviceName)
00336 {
00337 nldebug ("HNETL4: getSIDA() for service '%s'", serviceName.c_str ());
00338 ItBaseMap itbm = find (serviceName);
00339
00340
00341 nlassert ((*itbm).second.NetBase.size() == 1);
00342
00343 return (*itbm).second.NetBase[0]->getSIDA ();
00344 }
00345
00346 void CNetManager::addCallbackArray (const std::string &serviceName, const TCallbackItem *callbackarray, NLMISC::CStringIdArray::TStringId arraysize)
00347 {
00348 nldebug ("HNETL4: addingCallabckArray() for service '%s'", serviceName.c_str ());
00349 ItBaseMap itbm = find (serviceName);
00350 for (uint32 i = 0; i < (*itbm).second.NetBase.size(); i++)
00351 {
00352
00353 (*itbm).second.NetBase[i]->addCallbackArray (callbackarray, arraysize);
00354 }
00355 }
00356
00357 void CNetManager::update (TTime timeout)
00358 {
00359
00360
00361
00362
00363 TTime t0 = CTime::getLocalTime ();
00364
00365 if (timeout > 0)
00366 {
00367 if (_NextUpdateTime == 0)
00368 {
00369 _NextUpdateTime = t0 + timeout;
00370 }
00371 else
00372 {
00373 TTime err = t0 - _NextUpdateTime;
00374 _NextUpdateTime += timeout;
00375
00376
00377 while (err > timeout)
00378 {
00379 err -= timeout;
00380 _NextUpdateTime += timeout;
00381 }
00382
00383 timeout -= err;
00384 if (timeout < 0) timeout = 0;
00385 }
00386 }
00387
00388
00389
00390 while (true)
00391 {
00392 for (ItBaseMap itbm = _BaseMap.begin (); itbm != _BaseMap.end (); itbm++)
00393 {
00394 for (uint32 i = 0; i < (*itbm).second.NetBase.size(); i++)
00395 {
00397
00398 (*itbm).second.NetBase[i]->update (0);
00399 if ((*itbm).second.NetBase[i]->connected())
00400 {
00401
00402
00403 }
00404 else
00405 {
00406 static TTime lastTime = CTime::getLocalTime();
00407 if (CTime::getLocalTime() - lastTime > 5000)
00408 {
00409 lastTime = CTime::getLocalTime();
00410
00411
00412 if ((*itbm).second.Type == CBaseStruct::ClientWithAddr && (*itbm).second.AutoRetry)
00413 {
00414 CCallbackClient *cc = dynamic_cast<CCallbackClient *>((*itbm).second.NetBase[i]);
00415 try
00416 {
00417 nlassert ((*itbm).second.ServiceNames.size()==1);
00418 cc->connect (CInetAddress((*itbm).second.ServiceNames[0]));
00419
00420 if ((*itbm).second.ConnectionCallback != NULL)
00421 (*itbm).second.ConnectionCallback ((*itbm).second.Name, cc->getSockId(), (*itbm).second.ConnectionCbArg);
00422 }
00423 catch (ESocketConnectionFailed &e)
00424 {
00425
00426 nlinfo("HNETL4: can't connect now to %s (reason: %s)", (*itbm).second.ServiceNames[0].c_str(), e.what());
00427 }
00428 }
00429 }
00430 }
00431 }
00432 }
00433
00434
00435 if (CTime::getLocalTime() - t0 > timeout)
00436 break;
00437
00438
00439
00440 nlSleep (1);
00441
00442 }
00443
00444
00445
00446 if (CNamingClient::connected ())
00447 CNamingClient::update ();
00448
00449
00450
00451
00452 }
00453
00454
00455 void CNetManager::send (const std::string &serviceName, const CMessage &buffer, TSockId hostid)
00456 {
00457 nldebug ("HNETL4: send for service '%s' message %s to %s", serviceName.c_str(), buffer.toString().c_str(), hostid->asString().c_str());
00458 ItBaseMap itbm = find (serviceName);
00459 for (uint32 i = 0; i < (*itbm).second.NetBase.size(); i++)
00460 {
00461 if ((*itbm).second.NetBase[i]->connected())
00462 (*itbm).second.NetBase[i]->send (buffer, hostid);
00463 }
00464 }
00465
00466 CCallbackNetBase *CNetManager::getNetBase (const std::string &serviceName)
00467 {
00468 ItBaseMap itbm = find (serviceName);
00469 return (*itbm).second.NetBase[0];
00470 }
00471
00472 void CNetManager::setConnectionCallback (const std::string &serviceName, TNetManagerCallback cb, void *arg)
00473 {
00474 nldebug ("HNETL4: setConnectionCallback() for service '%s'", serviceName.c_str ());
00475 ItBaseMap itbm = find (serviceName);
00476 (*itbm).second.ConnectionCallback = cb;
00477 (*itbm).second.ConnectionCbArg = arg;
00478 }
00479
00480 void CNetManager::setDisconnectionCallback (const std::string &serviceName, TNetManagerCallback cb, void *arg)
00481 {
00482 nldebug ("HNETL4: setDisconnectionCallback() for service '%s'", serviceName.c_str ());
00483 ItBaseMap itbm = find (serviceName);
00484 (*itbm).second.DisconnectionCallback = cb;
00485 (*itbm).second.DisconnectionCbArg = arg;
00486 }
00487
00488
00489 CNetManager::ItBaseMap CNetManager::find (const std::string &serviceName)
00490 {
00491
00492 pair<ItBaseMap, bool> p;
00493 p = _BaseMap.insert (make_pair (serviceName, CBaseStruct (serviceName)));
00494 return p.first;
00495 }
00496
00497 uint64 CNetManager::getBytesSent ()
00498 {
00499 uint64 sent = 0;
00500 for (ItBaseMap itbm = _BaseMap.begin (); itbm != _BaseMap.end (); itbm++)
00501 {
00502 for (uint32 i = 0; i < (*itbm).second.NetBase.size(); i++)
00503 {
00504 sent += (*itbm).second.NetBase[i]->getBytesSent ();
00505 }
00506 }
00507 return sent;
00508 }
00509
00510 uint64 CNetManager::getBytesReceived ()
00511 {
00512 uint64 received = 0;
00513 for (ItBaseMap itbm = _BaseMap.begin (); itbm != _BaseMap.end (); itbm++)
00514 {
00515 for (uint32 i = 0; i < (*itbm).second.NetBase.size(); i++)
00516 {
00517 received += (*itbm).second.NetBase[i]->getBytesReceived ();
00518 }
00519 }
00520 return received;
00521 }
00522
00523 uint64 CNetManager::getSendQueueSize ()
00524 {
00525 uint64 val = 0;
00526 for (ItBaseMap itbm = _BaseMap.begin (); itbm != _BaseMap.end (); itbm++)
00527 {
00528 for (uint32 i = 0; i < (*itbm).second.NetBase.size(); i++)
00529 {
00530 val += (*itbm).second.NetBase[i]->getSendQueueSize ();
00531 }
00532 }
00533 return val;
00534 }
00535
00536 uint64 CNetManager::getReceiveQueueSize ()
00537 {
00538 uint64 val = 0;
00539 for (ItBaseMap itbm = _BaseMap.begin (); itbm != _BaseMap.end (); itbm++)
00540 {
00541 for (uint32 i = 0; i < (*itbm).second.NetBase.size(); i++)
00542 {
00543 val += (*itbm).second.NetBase[i]->getReceiveQueueSize ();
00544 }
00545 }
00546 return val;
00547 }
00548
00549 }