#include "connection.h" #include #include #include #include #include #include "nel_launcher_dlg.h" bool CNelLauncherConnection::connect() { std::string server = ConfigFile.getVar("StartupHost").asString(0); if(m_Sock.connected()) return true; try { // add the default port if no port in the cfg if(server.find(':') == std::string::npos) server+=":80"; m_Sock.connect(NLNET::CInetAddress(server)); if(!m_Sock.connected()) { nlwarning("Can't connect to web server '%s'", server.c_str()); goto end; } } catch(NLMISC::Exception &e) { nlwarning("Can't connect to web server '%s': %s", server.c_str(), e.what()); goto end; } return true; end: if(m_Sock.connected()) m_Sock.close (); return false; } bool CNelLauncherConnection::send(const std::string &url) { nlassert(m_Sock.connected()); std::string buffer = "GET " + url + "\r\n"; uint32 size = buffer.size(); if(!url.empty()) { if(m_Sock.send((uint8 *)buffer.c_str(), size, false) != NLNET::CSock::Ok) { nlwarning ("Can't send data to the server"); return false; } } return true; } bool CNelLauncherConnection::receive(std::string &res) { nlassert(m_Sock.connected()); uint32 size; res = ""; uint8 buf[1024]; //if(VerboseLog) nlinfo("Receiving"); while (true) { size = 1023; if(m_Sock.receive((uint8*)buf, size, false) == NLNET::CSock::Ok) { //if(VerboseLog) nlinfo("Received OK %d bytes", size); buf[1023] = '\0'; res += (char*)buf; //nlinfo("block received '%s'", buf); } else { //if(VerboseLog) nlinfo("Received CLOSE %d bytes", size); buf[size] = '\0'; res += (char*)buf; //nlwarning ("server connection closed"); break; } } // trim off whitespace. res = NLMISC::trim(res); nlinfo("all received '%s'", res.c_str()); return true; } std::string CNelLauncherConnection::checkLogin(const std::string &login, const std::string &password, const std::string &clientApp) { m_Shards.clear(); m_Login = m_Password = m_ClientApp = ""; if(ConfigFile.exists("UseDirectClient") && ConfigFile.getVar("UseDirectClient").asBool()) { ucstring pwd = ucstring(password); NLMISC::CHashKeyMD5 hk = NLMISC::getMD5((uint8*)pwd.c_str(), pwd.size()); std::string cpwd = hk.toString(); nlinfo("The crypted password is %s", cpwd.c_str()); std::string result = NLNET::CLoginClient::authenticate(ConfigFile.getVar("StartupHost").asString(), login, cpwd, clientApp); if (!result.empty()) return result; for(uint i = 0; i < NLNET::CLoginClient::ShardList.size(); ++i) { nldebug("Shard '%u' '%s' '%u'", NLNET::CLoginClient::ShardList[i].Id, NLNET::CLoginClient::ShardList[i].Name.toString().c_str(), NLNET::CLoginClient::ShardList[i].NbPlayers); m_Shards.push_back(CShard("1", true, NLNET::CLoginClient::ShardList[i].Id, NLNET::CLoginClient::ShardList[i].Name.toString(), NLNET::CLoginClient::ShardList[i].NbPlayers, "1", "1")); } m_Login = login; m_Password = password; m_ClientApp = clientApp; return ""; } if(!connect()) return "Can't connect (error code 1)"; //if(VerboseLog) nlinfo("Connected"); if(!send(ConfigFile.getVar("StartupPage").asString()+"?login="+login+"&password="+password+"&clientApplication="+clientApp)) return "Can't send (error code 2)"; //if(VerboseLog) nlinfo("Sent request login check"); std::string res; if(!receive(res)) return "Can't receive (error code 3)"; //if(VerboseLog) nlinfo("Received request login check"); if(res.empty()) return "Empty answer from server (error code 4)"; if(res[0] == '0') { // server returns an error nlwarning("server error: %s", res.substr(2).c_str()); return res.substr(2); } else if(res[0] == '1') { // server returns ok, we have the list of shard uint nbs = atoi(res.substr(2).c_str()); std::vector lines; NLMISC::explode(res, std::string("\n"), lines, true); // if(VerboseLog) // { //nlinfo ("Exploded, with nl, %d res", lines.size()); /* for (uint i = 0; i < lines.size(); i++) { nlinfo (" > '%s'", lines[i].c_str()); }*/ // } if(lines.size() != nbs+1) { nlwarning("bad shard lines number %d != %d", lines.size(), nbs+1); nlwarning("'%s'", res.c_str()); return "bad lines numbers (error code 5)"; } for(uint i = 1; i < lines.size(); i++) { std::vector res; NLMISC::explode(lines[i], std::string("|"), res); // if(VerboseLog) // { // nlinfo ("Exploded with '%s', %d res", "|", res.size()); /* for (uint i = 0; i < res.size(); i++) { nlinfo (" > '%s'", res[i].c_str()); }*/ // } if(res.size() != 7) { nlwarning("bad | numbers %d != %d", res.size(), 7); nlwarning("'%s'", lines[i].c_str()); return "bad pipe numbers (error code 6)"; } m_Shards.push_back(CShard(res[0], atoi(res[1].c_str())>0, atoi(res[2].c_str()), res[3], atoi(res[4].c_str()), res[5], res[6])); } } else { // server returns ??? nlwarning("%s", res.c_str()); return res; } m_Login = login; m_Password = password; m_ClientApp = clientApp; return ""; } std::string CNelLauncherConnection::selectShard(uint32 shardId, std::string &cookie, std::string &addr) { cookie = addr = ""; if(ConfigFile.exists("UseDirectClient") && ConfigFile.getVar("UseDirectClient").asBool()) return NLNET::CLoginClient::wantToConnectToShard(shardId, addr, cookie); if(!connect()) return "Can't connect (error code 7)"; if(m_Login.empty()) return "Empty Login (error code 8)"; if(m_Password.empty()) return "Empty Password (error code 9)"; if(m_ClientApp.empty()) return "Empty Client Application (error code 10)"; if(!send(ConfigFile.getVar("StartupPage").asString()+"?cmd=login&shardid="+NLMISC::toString(shardId)+"&login="+m_Login+"&password="+m_Password+"&clientApplication="+m_ClientApp)) return "Can't send (error code 11)"; std::string res; if(!receive(res)) return "Can't receive (error code 12)"; if(res.empty()) return "Empty result (error code 13)"; if(res[0] == '0') { // server returns an error nlwarning("server error: %s", res.substr(2).c_str()); return res.substr(2); } else if(res[0] == '1') { // server returns ok, we have the access std::vector line; NLMISC::explode(res, std::string(" "), line, true); if(line.size() != 2) { nlwarning("bad launch lines number %d != %d", line.size(), 2); return "bad launch line number (error code 14)"; } cookie = line[0].substr(2); addr = line[1]; } else { // server returns ??? nlwarning("%s", res.c_str()); return res; } return ""; }