00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "stdnet.h"
00028
00029 #include "nel/net/callback_client.h"
00030 #include "nel/net/service.h"
00031
00032 #include "nel/net/login_cookie.h"
00033 #include "nel/net/login_server.h"
00034
00035 #include "nel/net/udp_sock.h"
00036
00037 using namespace std;
00038 using namespace NLMISC;
00039
00040 namespace NLNET {
00041
00042 struct CPendingUser
00043 {
00044 CPendingUser (const CLoginCookie &cookie) : Cookie (cookie) { }
00045 CLoginCookie Cookie;
00046 };
00047
00048 static list<CPendingUser> PendingUsers;
00049
00050 static CCallbackServer *Server;
00051 static string ListenAddr;
00052
00053 static TDisconnectClientCallback DisconnectClientCallback = NULL;
00054
00056 map<uint32, TSockId> UserIdSockAssociations;
00057
00058 TNewClientCallback NewClientCallback = NULL;
00059
00065
00066 void cbWSChooseShard (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00067 {
00068
00069 string reason;
00070 CLoginCookie cookie;
00071
00072
00073
00074
00075
00076 msgin.serial (cookie);
00077
00078 list<CPendingUser>::iterator it;
00079 for (it = PendingUsers.begin(); it != PendingUsers.end (); it++)
00080 {
00081 if ((*it).Cookie == cookie)
00082 {
00083
00084 nlwarning ("cookie %s is already in the pending user list", cookie.toString().c_str());
00085 PendingUsers.erase (it);
00086 reason = "cookie already exists";
00087 break;
00088 }
00089 }
00090 if (it == PendingUsers.end ())
00091 {
00092
00093 PendingUsers.push_back (CPendingUser (cookie));
00094 reason = "";
00095 }
00096
00097 CMessage msgout (CNetManager::getSIDA ("WS"), "SCS");
00098 msgout.serial (reason);
00099 msgout.serial (cookie);
00100 msgout.serial (ListenAddr);
00101 CNetManager::send ("WS", msgout);
00102 }
00103
00104 void cbWSChooseShard5 (CMessage &msgin, const std::string &serviceName, uint16 sid)
00105 {
00106
00107 string reason;
00108 CLoginCookie cookie;
00109
00110
00111
00112
00113
00114 msgin.serial (cookie);
00115
00116 list<CPendingUser>::iterator it;
00117 for (it = PendingUsers.begin(); it != PendingUsers.end (); it++)
00118 {
00119 if ((*it).Cookie == cookie)
00120 {
00121
00122 nlwarning ("cookie %s is already in the pending user list", cookie.toString().c_str());
00123 PendingUsers.erase (it);
00124 reason = "cookie already exists";
00125 break;
00126 }
00127 }
00128 if (it == PendingUsers.end ())
00129 {
00130
00131 nlinfo ("New cookie %s inserted in the pending user list (awaiting new client)", cookie.toString().c_str());
00132 PendingUsers.push_back (CPendingUser (cookie));
00133 reason = "";
00134 }
00135
00136 CMessage msgout ("SCS");
00137 msgout.serial (reason);
00138 msgout.serial (cookie);
00139 msgout.serial (ListenAddr);
00140 CUnifiedNetwork::getInstance()->send ("WS", msgout);
00141 }
00142
00143 void cbWSDisconnectClient5 (CMessage &msgin, const std::string &serviceName, uint16 sid)
00144 {
00145
00146
00147 uint32 userid;
00148 msgin.serial (userid);
00149
00150 map<uint32, TSockId>::iterator it = UserIdSockAssociations.find (userid);
00151 if (it == UserIdSockAssociations.end ())
00152 {
00153 nlwarning ("Can't disconnect the user %d, he is not found", userid);
00154 }
00155 else
00156 {
00157 nlinfo ("Disconnect the user %d", userid);
00158 Server->disconnect ((*it).second);
00159 }
00160
00161 if (DisconnectClientCallback != NULL)
00162 {
00163 DisconnectClientCallback (userid);
00164 }
00165 }
00166
00167 void cbWSDisconnectClient (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00168 {
00169 cbWSDisconnectClient5 (msgin, "", 0);
00170 }
00171
00172 static TCallbackItem WSCallbackArray[] =
00173 {
00174 { "CS", cbWSChooseShard },
00175 { "DC", cbWSDisconnectClient },
00176 };
00177
00178 static TUnifiedCallbackItem WSCallbackArray5[] =
00179 {
00180 { "CS", cbWSChooseShard5 },
00181 { "DC", cbWSDisconnectClient5 },
00182 };
00183
00189
00190 void cbShardValidation (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00191 {
00192
00193
00194
00195
00196
00197 CLoginCookie cookie;
00198 string reason;
00199 msgin.serial (cookie);
00200
00201
00202 reason = CLoginServer::isValidCookie (cookie);
00203
00204 CMessage msgout2 (netbase.getSIDA (), "SV");
00205 msgout2.serial (reason);
00206 netbase.send (msgout2, from);
00207
00208 if (!reason.empty())
00209 {
00210 nlwarning ("User (%s) is not in the pending user list (cookie:%s)", netbase.hostAddress(from).asString().c_str(), cookie.toString().c_str());
00211
00212 netbase.disconnect (from);
00213 }
00214 else
00215 {
00216
00217 uint32 userid = cookie.getUserId();
00218 UserIdSockAssociations.insert (make_pair(userid, from));
00219
00220
00221 if (NewClientCallback != NULL)
00222 NewClientCallback (from, cookie);
00223
00224
00225 Server->authorizeOnly (NULL, from);
00226 }
00227 }
00228
00229 void ClientConnection (TSockId from, void *arg)
00230 {
00231 nldebug("new client connection: %s", from->asString ().c_str ());
00232
00233
00234 Server->authorizeOnly ("SV", from);
00235 }
00236
00237
00238 static const TCallbackItem ClientCallbackArray[] =
00239 {
00240 { "SV", cbShardValidation },
00241 };
00242
00243 void cfcbListenAddress (CConfigFile::CVar &var)
00244 {
00245
00246 ListenAddr = var.asString();
00247
00248
00249 if (ListenAddr.empty())
00250 {
00251 ListenAddr = Server->listenAddress ().asIPString();
00252 }
00253
00254 nlinfo("Listen Address trapped '%s'", ListenAddr.c_str());
00255 }
00256
00257
00263
00264 void CLoginServer::init (CCallbackServer &server, TNewClientCallback ncl)
00265 {
00266
00267 connectToWS ();
00268
00269
00270 server.addCallbackArray (ClientCallbackArray, sizeof (ClientCallbackArray) / sizeof (ClientCallbackArray[0]));
00271 server.setConnectionCallback (ClientConnection, NULL);
00272
00273 try
00274 {
00275 cfcbListenAddress (IService::getInstance()->ConfigFile.getVar("ListenAddress"));
00276 IService::getInstance()->ConfigFile.setCallback("ListenAddress", cfcbListenAddress);
00277 }
00278 catch(Exception &)
00279 {
00280 }
00281
00282
00283 if (ListenAddr.empty())
00284 {
00285 ListenAddr = server.listenAddress ().asIPString();
00286 }
00287
00288 nlinfo("Listen Address trapped '%s'", ListenAddr.c_str());
00289
00290 NewClientCallback = ncl;
00291 Server = &server;
00292 }
00293
00294 void CLoginServer::init (CUdpSock &server, TDisconnectClientCallback dc)
00295 {
00296
00297 connectToWS ();
00298
00299 try
00300 {
00301 cfcbListenAddress (IService::getInstance()->ConfigFile.getVar("ListenAddress"));
00302 IService::getInstance()->ConfigFile.setCallback("ListenAddress", cfcbListenAddress);
00303 }
00304 catch(Exception &)
00305 {
00306 }
00307
00308
00309 if (ListenAddr.empty())
00310 {
00311 ListenAddr = server.localAddr ().asIPString();
00312 }
00313
00314 nlinfo("Listen Addresss trapped '%s'", ListenAddr.c_str());
00315
00316 DisconnectClientCallback = dc;
00317 }
00318
00319 string CLoginServer::isValidCookie (const CLoginCookie &lc)
00320 {
00321
00322 list<CPendingUser>::iterator it;
00323 for (it = PendingUsers.begin(); it != PendingUsers.end (); it++)
00324 {
00325 if ((*it).Cookie == lc)
00326 {
00327
00328 PendingUsers.erase (it);
00329
00330
00331 uint8 con = 1;
00332 CMessage msgout ("CC");
00333 uint32 userid = lc.getUserId();
00334 msgout.serial (userid);
00335 msgout.serial (con);
00336
00337 if (CUnifiedNetwork::isUsed ())
00338 {
00339 CUnifiedNetwork::getInstance()->send("WS", msgout);
00340 }
00341 else
00342 {
00343 CNetManager::send("WS", msgout);
00344 }
00345
00346 return "";
00347 }
00348 }
00349 return "I didn't receive the cookie from WS";
00350 }
00351
00352 void CLoginServer::connectToWS ()
00353 {
00354 if (CUnifiedNetwork::isUsed ())
00355 {
00356 CUnifiedNetwork::getInstance()->addCallbackArray(WSCallbackArray5, sizeof(WSCallbackArray5)/sizeof(WSCallbackArray5[0]));
00357 }
00358 else
00359 {
00360 CNetManager::addClient ("WS");
00361 CNetManager::addCallbackArray ("WS", WSCallbackArray, sizeof (WSCallbackArray) / sizeof (WSCallbackArray[0]));
00362
00363 CMessage msg("UN_SIDENT");
00364 nlassert (IService::getInstance());
00365 uint16 ssid = IService::getInstance()->getServiceId();
00366 string name = IService::getInstance()->getServiceShortName();
00367 msg.serial(name);
00368 msg.serial(ssid);
00369 CNetManager::send("WS", msg);
00370 }
00371 }
00372
00373 void CLoginServer::clientDisconnected (uint32 userId)
00374 {
00375 uint8 con = 0;
00376 CMessage msgout ("CC");
00377 msgout.serial (userId);
00378 msgout.serial (con);
00379
00380 if (CUnifiedNetwork::isUsed ())
00381 {
00382 CUnifiedNetwork::getInstance()->send("WS", msgout);
00383 }
00384 else
00385 {
00386 CNetManager::send("WS", msgout);
00387 }
00388
00389
00390 UserIdSockAssociations.erase (userId);
00391 }
00392
00393
00394
00395
00396
00397 NLMISC_COMMAND (lsUsers, "displays the list of all connected users", "")
00398 {
00399 if(args.size() != 0) return false;
00400
00401 log.displayNL ("Display the %d connected users :", UserIdSockAssociations.size());
00402 for (map<uint32, TSockId>::iterator it = UserIdSockAssociations.begin(); it != UserIdSockAssociations.end (); it++)
00403 {
00404 log.displayNL ("> %u %s", (*it).first, (*it).second->asString().c_str());
00405 }
00406 log.displayNL ("End ot the list");
00407
00408 return true;
00409 }
00410
00411 NLMISC_COMMAND (lsPending, "displays the list of all pending users", "")
00412 {
00413 if(args.size() != 0) return false;
00414
00415 log.displayNL ("Display the %d pending users :", PendingUsers.size());
00416 for (list<CPendingUser>::iterator it = PendingUsers.begin(); it != PendingUsers.end (); it++)
00417 {
00418 log.displayNL ("> %s", (*it).Cookie.toString().c_str());
00419 }
00420 log.displayNL ("End ot the list");
00421
00422 return true;
00423 }
00424
00425
00426 NLMISC_DYNVARIABLE(string, LSListenAddress, "the listen address sended to the client to connect on this front_end")
00427 {
00428 if (get)
00429 {
00430 *pointer = ListenAddr;
00431 }
00432 else
00433 {
00434 if ((*pointer).find (":") == string::npos)
00435 {
00436 log.displayNL ("You must set the address + port (ie: \"itsalive.nevrax.org:38000\")");
00437 return;
00438 }
00439 else if ((*pointer).empty())
00440 {
00441 ListenAddr = Server->listenAddress ().asIPString();
00442 }
00443 else
00444 {
00445 ListenAddr = *pointer;
00446 }
00447 log.displayNL ("Listen Address trapped '%s'", ListenAddr.c_str());
00448 }
00449 }
00450
00451
00452 }
00453
00454
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00482
00483
00484
00485
00486
00487
00488
00489
00491
00492