World <-> Login connection reworked

This commit is contained in:
KimLS
2016-10-28 19:02:03 -07:00
parent fab8765c2f
commit 0b8b41d91f
32 changed files with 729 additions and 701 deletions
-12
View File
@@ -467,7 +467,6 @@ void Console::ProcessCommand(const char* command) {
SendMessage(1, " IPLookup [name]");
}
if (admin >= 100) {
SendMessage(1, " LSReconnect");
SendMessage(1, " signalcharbyname charname ID");
SendMessage(1, " reloadworld");
}
@@ -794,17 +793,6 @@ void Console::ProcessCommand(const char* command) {
else if (strcasecmp(sep.arg[0], "IPLookup") == 0 && admin >= 201) {
client_list.SendCLEList(admin, 0, this, sep.argplus[1]);
}
else if (strcasecmp(sep.arg[0], "LSReconnect") == 0 && admin >= 100) {
#ifdef _WINDOWS
_beginthread(AutoInitLoginServer, 0, nullptr);
#else
pthread_t thread;
pthread_create(&thread, nullptr, &AutoInitLoginServer, nullptr);
#endif
RunLoops = true;
SendMessage(1, " Login Server Reconnect manually restarted by Console");
Log.Out(Logs::Detail, Logs::World_Server,"Login Server Reconnect manually restarted by Console");
}
else if (strcasecmp(sep.arg[0], "zonelock") == 0 && admin >= consoleZoneStatus) {
if (strcasecmp(sep.arg[1], "list") == 0) {
zoneserver_list.ListLockedZones(0, this);
-78
View File
@@ -261,84 +261,6 @@ void EQW::CreateLauncher(Const_char *launcher_name, int dynamic_count) {
launcher_list.CreateLauncher(launcher_name, dynamic_count);
}
void EQW::LSReconnect() {
#ifdef _WINDOWS
_beginthread(AutoInitLoginServer, 0, nullptr);
#else
pthread_t thread;
pthread_create(&thread, nullptr, &AutoInitLoginServer, nullptr);
#endif
RunLoops = true;
Log.Out(Logs::Detail, Logs::World_Server,"Login Server Reconnect manually restarted by Web Tool");
}
/*EQLConfig * EQW::FindLauncher(Const_char *zone_ref) {
return(nullptr);
}*/
/*
map<string,string> EQW::GetLaunchersDetails(Const_char *launcher_name) {
map<string,string> res;
LauncherLink *ll = launcher_list.Get(launcher_name);
if(ll == nullptr) {
res["name"] = launcher_name;
res["ip"] = "Not Connected";
res["id"] = "0";
res["zone_count"] = "0";
res["connected"] = "no";
return(res);
} else {
res["name"] = ll->GetName();
res["ip"] = long2ip(ll->GetIP());
res["id"] = itoa(ll->GetID());
res["zone_count"] = itoa(ll->CountZones());
res["connected"] = "yes";
}
return(res);
}
vector<string> EQW::ListLauncherZones(Const_char *launcher_name) {
vector<string> list;
LauncherLink *ll = launcher_list.Get(launcher_name);
if(ll != nullptr) {
ll->GetZoneList(list);
}
return(list);
}
map<string,string> EQW::GetLauncherZoneDetails(Const_char *launcher_name, Const_char *zone_ref) {
map<string,string> res;
LauncherLink *ll = launcher_list.Get(launcher_name);
if(ll != nullptr) {
ll->GetZoneDetails(zone_ref, res);
} else {
res["error"] = "Launcher Not Found";
}
return(res);
}
void EQW::CreateLauncher(Const_char *launcher_name, int dynamic_count) {
}
bool EQW::BootStaticZone(Const_char *launcher_name, Const_char *short_name) {
return(false);
}
bool EQW::DeleteStaticZone(Const_char *launcher_name, Const_char *short_name) {
return(false);
}
bool EQW::SetDynamicCount(Const_char *launcher_name, int count) {
return(false);
}
int EQW::GetDynamicCount(Const_char *launcher_name) {
return(0);
}
*/
uint32 EQW::CreateGuild(const char* name, uint32 leader_char_id) {
uint32 id = guild_mgr.CreateGuild(name, leader_char_id);
if(id != GUILD_NONE)
-1
View File
@@ -42,7 +42,6 @@ public:
void UnlockWorld();
bool LSConnected();
void LSReconnect();
int CountZones();
std::vector<std::string> ListBootedZones(); //returns an array of zone_refs (opaque)
+104 -161
View File
@@ -22,35 +22,6 @@
#include <iomanip>
#include <stdlib.h>
#include "../common/version.h"
#ifdef _WINDOWS
#include <process.h>
#include <winsock2.h>
#include <windows.h>
#define snprintf _snprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else // Pyro: fix for linux
#include <sys/socket.h>
#ifdef FREEBSD //Timothy Whitman - January 7, 2003
#include <sys/types.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include "../common/unix.h"
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
extern int errno;
#endif
#define IGNORE_LS_FATAL_ERROR
#include "../common/servertalk.h"
#include "login_server.h"
#include "login_server_list.h"
@@ -70,145 +41,107 @@ extern uint32 numplayers;
extern volatile bool RunLoops;
LoginServer::LoginServer(const char* iAddress, uint16 iPort, const char* Account, const char* Password)
: statusupdate_timer(LoginServer_StatusUpdateInterval)
{
strn0cpy(LoginServerAddress,iAddress,256);
LoginServerPort = iPort;
strn0cpy(LoginAccount,Account,31);
strn0cpy(LoginPassword,Password,31);
CanAccountUpdate = false;
tcpc = new EmuTCPConnection(true);
tcpc->SetPacketMode(EmuTCPConnection::packetModeLogin);
Connect();
}
LoginServer::~LoginServer() {
delete tcpc;
}
bool LoginServer::Process() {
void LoginServer::ProcessPacket(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config=WorldConfig::get();
if (statusupdate_timer.Check()) {
this->SendStatus();
}
/************ Get all packets from packet manager out queue and process them ************/
ServerPacket *pack = 0;
while((pack = tcpc->PopPacket()))
{
Log.Out(Logs::Detail, Logs::World_Server,"Recevied ServerPacket from LS OpCode 0x04x",pack->opcode);
Log.Out(Logs::Detail, Logs::World_Server,"Recevied ServerPacket from LS OpCode 0x04x", opcode);
switch(pack->opcode) {
case 0:
break;
case ServerOP_KeepAlive: {
// ignore this
break;
}
case ServerOP_UsertoWorldReq: {
UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*) pack->pBuffer;
uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid);
int16 status = database.CheckStatus(id);
switch(opcode) {
case ServerOP_UsertoWorldReq: {
UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*)p.Data();
uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid);
int16 status = database.CheckStatus(id);
auto outpack = new ServerPacket;
outpack->opcode = ServerOP_UsertoWorldResp;
outpack->size = sizeof(UsertoWorldResponse_Struct);
outpack->pBuffer = new uchar[outpack->size];
memset(outpack->pBuffer, 0, outpack->size);
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*) outpack->pBuffer;
utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID;
auto outpack = new ServerPacket;
outpack->opcode = ServerOP_UsertoWorldResp;
outpack->size = sizeof(UsertoWorldResponse_Struct);
outpack->pBuffer = new uchar[outpack->size];
memset(outpack->pBuffer, 0, outpack->size);
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*) outpack->pBuffer;
utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID;
if(Config->Locked == true)
{
if((status == 0 || status < 100) && (status != -2 || status != -1))
utwrs->response = 0;
if(status >= 100)
utwrs->response = 1;
}
else {
utwrs->response = 1;
}
int32 x = Config->MaxClients;
if( (int32)numplayers >= x && x != -1 && x != 255 && status < 80)
utwrs->response = -3;
if(status == -1)
utwrs->response = -1;
if(status == -2)
utwrs->response = -2;
utwrs->worldid = utwr->worldid;
SendPacket(outpack);
delete outpack;
break;
}
case ServerOP_LSClientAuth: {
ClientAuth_Struct* slsca = (ClientAuth_Struct*) pack->pBuffer;
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca->lsaccount_id);
}
client_list.CLEAdd(slsca->lsaccount_id, slsca->name, slsca->key, slsca->worldadmin, slsca->ip, slsca->local);
break;
}
case ServerOP_LSFatalError: {
#ifndef IGNORE_LS_FATAL_ERROR
WorldConfig::DisableLoginserver();
Log.Out(Logs::Detail, Logs::World_Server, "Login server responded with FatalError. Disabling reconnect.");
#else
Log.Out(Logs::Detail, Logs::World_Server, "Login server responded with FatalError.");
#endif
if (pack->size > 1) {
Log.Out(Logs::Detail, Logs::World_Server, " %s",pack->pBuffer);
}
break;
}
case ServerOP_SystemwideMessage: {
ServerSystemwideMessage* swm = (ServerSystemwideMessage*) pack->pBuffer;
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
break;
}
case ServerOP_LSRemoteAddr: {
if (!Config->WorldAddress.length()) {
WorldConfig::SetWorldAddress((char *)pack->pBuffer);
Log.Out(Logs::Detail, Logs::World_Server, "Loginserver provided %s as world address",pack->pBuffer);
}
break;
}
case ServerOP_LSAccountUpdate: {
Log.Out(Logs::Detail, Logs::World_Server, "Received ServerOP_LSAccountUpdate packet from loginserver");
CanAccountUpdate = true;
break;
}
default:
if(Config->Locked == true)
{
Log.Out(Logs::Detail, Logs::World_Server, "Unknown LSOpCode: 0x%04x size=%d",(int)pack->opcode,pack->size);
DumpPacket(pack->pBuffer, pack->size);
break;
if((status == 0 || status < 100) && (status != -2 || status != -1))
utwrs->response = 0;
if(status >= 100)
utwrs->response = 1;
}
else {
utwrs->response = 1;
}
int32 x = Config->MaxClients;
if( (int32)numplayers >= x && x != -1 && x != 255 && status < 80)
utwrs->response = -3;
if(status == -1)
utwrs->response = -1;
if(status == -2)
utwrs->response = -2;
utwrs->worldid = utwr->worldid;
SendPacket(outpack);
delete outpack;
break;
}
delete pack;
}
case ServerOP_LSClientAuth: {
ClientAuth_Struct* slsca = (ClientAuth_Struct*)p.Data();
return true;
}
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca->lsaccount_id);
}
bool LoginServer::InitLoginServer() {
if(Connected() == false) {
if(ConnectReady()) {
Log.Out(Logs::Detail, Logs::World_Server, "Connecting to login server: %s:%d",LoginServerAddress,LoginServerPort);
Connect();
} else {
Log.Out(Logs::Detail, Logs::World_Server, "Not connected but not ready to connect, this is bad: %s:%d",
LoginServerAddress,LoginServerPort);
client_list.CLEAdd(slsca->lsaccount_id, slsca->name, slsca->key, slsca->worldadmin, inet_addr(slsca->ip), slsca->local);
break;
}
case ServerOP_LSFatalError: {
Log.Out(Logs::Detail, Logs::World_Server, "Login server responded with FatalError.");
if (p.Length() > 1) {
Log.Out(Logs::Detail, Logs::World_Server, " %s", (const char*)p.Data());
}
break;
}
case ServerOP_SystemwideMessage: {
ServerSystemwideMessage* swm = (ServerSystemwideMessage*)p.Data();
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
break;
}
case ServerOP_LSRemoteAddr: {
if (!Config->WorldAddress.length()) {
WorldConfig::SetWorldAddress((char *)p.Data());
Log.Out(Logs::Detail, Logs::World_Server, "Loginserver provided %s as world address", (const char*)p.Data());
}
break;
}
case ServerOP_LSAccountUpdate: {
Log.Out(Logs::Detail, Logs::World_Server, "Received ServerOP_LSAccountUpdate packet from loginserver");
CanAccountUpdate = true;
break;
}
default:
{
Log.Out(Logs::Detail, Logs::World_Server, "Unknown LSOpCode: 0x%04x size=%d",(int)opcode, p.Length());
Log.OutF(Logs::General, Logs::Login_Server, "{0}", p.ToString());
break;
}
}
return true;
}
bool LoginServer::Connect() {
@@ -236,20 +169,32 @@ bool LoginServer::Connect() {
return false;
}
if (tcpc->ConnectIP(LoginServerIP, LoginServerPort, errbuf)) {
Log.Out(Logs::Detail, Logs::World_Server, "Connected to Loginserver: %s:%d",LoginServerAddress,LoginServerPort);
if (minilogin)
SendInfo();
else
SendNewInfo();
SendStatus();
zoneserver_list.SendLSZones();
return true;
}
else {
Log.Out(Logs::Detail, Logs::World_Server, "Could not connect to login server: %s:%d %s",LoginServerAddress,LoginServerPort,errbuf);
return false;
}
client.reset(new EQ::Net::ServertalkClient(LoginServerAddress, LoginServerPort, false, "World", ""));
client->OnConnect([this](EQ::Net::ServertalkClient *client) {
if (client) {
Log.Out(Logs::Detail, Logs::World_Server, "Connected to Loginserver: %s:%d", LoginServerAddress, LoginServerPort);
if (minilogin)
SendInfo();
else
SendNewInfo();
SendStatus();
zoneserver_list.SendLSZones();
statusupdate_timer.reset(new EQ::Timer(LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) {
SendStatus();
}));
}
else {
Log.Out(Logs::Detail, Logs::World_Server, "Could not connect to Loginserver: %s:%d", LoginServerAddress, LoginServerPort);
}
});
client->OnMessage(ServerOP_UsertoWorldReq, std::bind(&LoginServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSClientAuth, std::bind(&LoginServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSFatalError, std::bind(&LoginServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_SystemwideMessage, std::bind(&LoginServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSRemoteAddr, std::bind(&LoginServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSAccountUpdate, std::bind(&LoginServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
}
void LoginServer::SendInfo() {
const WorldConfig *Config=WorldConfig::get();
@@ -291,15 +236,13 @@ void LoginServer::SendNewInfo() {
if (Config->LocalAddress.length())
strcpy(lsi->local_address, Config->LocalAddress.c_str());
else {
tcpc->GetSockName(lsi->local_address,&port);
WorldConfig::SetLocalAddress(lsi->local_address);
WorldConfig::SetLocalAddress(client->Handle()->LocalIP());
}
SendPacket(pack);
delete pack;
}
void LoginServer::SendStatus() {
statusupdate_timer.Start();
auto pack = new ServerPacket;
pack->opcode = ServerOP_LSStatus;
pack->size = sizeof(ServerLSStatus_Struct);
+8 -10
View File
@@ -24,39 +24,37 @@
#include "../common/queue.h"
#include "../common/eq_packet_structs.h"
#include "../common/mutex.h"
#include "../common/emu_tcp_connection.h"
#include "../common/net/servertalk_client_connection.h"
#include "../common/event/timer.h"
#include <memory>
class LoginServer{
public:
LoginServer(const char*, uint16, const char*, const char*);
~LoginServer();
bool InitLoginServer();
bool Process();
void ProcessPacket(uint16_t opcode, EQ::Net::Packet &p);
bool Connect();
void SendInfo();
void SendNewInfo();
void SendStatus();
void SendPacket(ServerPacket* pack) { tcpc->SendPacket(pack); }
void SendPacket(ServerPacket* pack) { client->SendPacket(pack); }
void SendAccountUpdate(ServerPacket* pack);
bool ConnectReady() { return tcpc->ConnectReady(); }
bool Connected() { return tcpc->Connected(); }
bool Connected() { return client->Connected(); }
bool MiniLogin() { return minilogin; }
bool CanUpdate() { return CanAccountUpdate; }
private:
bool minilogin;
EmuTCPConnection* tcpc;
std::unique_ptr<EQ::Net::ServertalkClient> client;
std::unique_ptr<EQ::Timer> statusupdate_timer;
char LoginServerAddress[256];
uint32 LoginServerIP;
uint16 LoginServerPort;
char LoginAccount[32];
char LoginPassword[32];
bool CanAccountUpdate;
Timer statusupdate_timer;
};
#endif
-32
View File
@@ -55,38 +55,6 @@ void LoginServerList::Add(const char* iAddress, uint16 iPort, const char* Accoun
list.Insert(loginserver);
}
bool LoginServerList::Process() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
iterator.GetData()->Process();
iterator.Advance();
}
return true;
}
#ifdef _WINDOWS
void AutoInitLoginServer(void *tmp) {
#else
void *AutoInitLoginServer(void *tmp) {
#endif
loginserverlist.InitLoginServer();
#ifndef WIN32
return 0;
#endif
}
void LoginServerList::InitLoginServer() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
iterator.GetData()->InitLoginServer();
iterator.Advance();
}
}
bool LoginServerList::SendInfo() {
LinkedListIterator<LoginServer*> iterator(list);
-9
View File
@@ -9,12 +9,6 @@
#include "../common/mutex.h"
#include "../common/emu_tcp_connection.h"
#ifdef _WINDOWS
void AutoInitLoginServer(void *tmp);
#else
void *AutoInitLoginServer(void *tmp);
#endif
class LoginServer;
class LoginServerList{
@@ -23,9 +17,6 @@ public:
~LoginServerList();
void Add(const char*, uint16, const char*, const char*);
void InitLoginServer();
bool Process();
bool SendInfo();
bool SendNewInfo();
+26 -12
View File
@@ -86,6 +86,9 @@
#include "ucs.h"
#include "queryserv.h"
#include "../common/net/tcp_server.h"
#include "../common/net/servertalk_server.h"
EmuTCPServer tcps;
ClientList client_list;
GroupLFPList LFPGroupList;
@@ -412,6 +415,28 @@ int main(int argc, char** argv) {
Log.OutF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->RemoteEndpoint(), ntohs(stream->GetRemotePort()));
});
EQ::Net::ServertalkServer server;
EQ::Net::ServertalkServerOptions stopts;
stopts.port = 5999;
stopts.credentials = "User:Root;Password:1234567890";
stopts.encrypted = true;
server.Listen(stopts);
server.OnConnectionIdentified("QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> conn) {
Log.Out(Logs::General, Logs::Debug, "New QueryServ Connection....");
EQ::Net::WritablePacket out;
out.PutCString(0, "Hello");
conn->Send(1, out);
conn->OnMessage(2, [&](uint16_t opcode, EQ::Net::Packet &p) {
Log.OutF(Logs::General, Logs::Debug, "Server got message of type {0}\n{1}", opcode, p.ToString());
});
});
server.OnConnectionRemoved("QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> conn) {
Log.Out(Logs::General, Logs::Debug, "Lost QueryServ connection.");
});
while(RunLoops) {
Timer::SetCurrentTime();
eqs = nullptr;
@@ -487,7 +512,6 @@ int main(int argc, char** argv) {
Log.Out(Logs::Detail, Logs::World_Server, "EQTime successfully saved.");
}
loginserverlist.Process();
console_list.Process();
zoneserver_list.Process();
launcher_list.Process();
@@ -498,17 +522,7 @@ int main(int argc, char** argv) {
if (InterserverTimer.Check()) {
InterserverTimer.Start();
database.ping();
if (loginserverlist.AllConnected() == false) {
#ifdef _WINDOWS
_beginthread(AutoInitLoginServer, 0, nullptr);
#else
pthread_t thread;
pthread_create(&thread, nullptr, &AutoInitLoginServer, nullptr);
#endif
}
database.ping();
}
EQ::EventLoop::Get().Process();
-24
View File
@@ -140,29 +140,6 @@ XS(XS_EQW_LSConnected)
XSRETURN(1);
}
XS(XS_EQW_LSReconnect); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQW_LSReconnect)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: EQW::LSReconnect(THIS)");
{
EQW * THIS;
if (sv_derived_from(ST(0), "EQW")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQW *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQW");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->LSReconnect();
}
XSRETURN_EMPTY;
}
XS(XS_EQW_CountZones); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQW_CountZones)
{
@@ -1010,7 +987,6 @@ XS(boot_EQW)
newXSproto(strcpy(buf, "LockWorld"), XS_EQW_LockWorld, file, "$");
newXSproto(strcpy(buf, "UnlockWorld"), XS_EQW_UnlockWorld, file, "$");
newXSproto(strcpy(buf, "LSConnected"), XS_EQW_LSConnected, file, "$");
newXSproto(strcpy(buf, "LSReconnect"), XS_EQW_LSReconnect, file, "$");
newXSproto(strcpy(buf, "CountZones"), XS_EQW_CountZones, file, "$");
newXSproto(strcpy(buf, "ListBootedZones"), XS_EQW_ListBootedZones, file, "$");
newXSproto(strcpy(buf, "GetZoneDetails"), XS_EQW_GetZoneDetails, file, "$$");