More work on getting remote calls up and running, added two remote calls list_zones and get_zone_info.

This commit is contained in:
KimLS 2014-07-30 15:23:14 -07:00
parent 927580b983
commit 780789fbad
21 changed files with 528 additions and 167 deletions

View File

@ -91,7 +91,6 @@ SET(common_sources
tinyxml/tinyxml.cpp tinyxml/tinyxml.cpp
tinyxml/tinyxmlerror.cpp tinyxml/tinyxmlerror.cpp
tinyxml/tinyxmlparser.cpp tinyxml/tinyxmlparser.cpp
web_interface_utils.cpp
) )
SET(common_headers SET(common_headers
@ -237,7 +236,6 @@ SET(common_headers
StackWalker/StackWalker.h StackWalker/StackWalker.h
tinyxml/tinystr.h tinyxml/tinystr.h
tinyxml/tinyxml.h tinyxml/tinyxml.h
web_interface_utils.h
) )
SOURCE_GROUP(Patches FILES SOURCE_GROUP(Patches FILES

View File

@ -186,9 +186,8 @@
#define ServerOP_QSPlayerLogMoves 0x4014 #define ServerOP_QSPlayerLogMoves 0x4014
#define ServerOP_QSMerchantLogTransactions 0x4015 #define ServerOP_QSMerchantLogTransactions 0x4015
#define ServerOP_WIServGeneric 0x5001 #define ServerOP_WIRemoteCall 0x5001
#define ServerOP_WIWorldResponse 0x5002 #define ServerOP_WIRemoteCallResponse 0x5002
#define ServerOP_WIClientRequest 0x5003
enum { QSG_LFGuild = 0 }; enum { QSG_LFGuild = 0 };
enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_RequestPlayerInfo, QSG_LFGuild_UpdateGuildInfo, QSG_LFGuild_GuildMatches, enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_RequestPlayerInfo, QSG_LFGuild_UpdateGuildInfo, QSG_LFGuild_GuildMatches,
@ -1233,17 +1232,6 @@ struct ReloadWorld_Struct{
uint32 Option; uint32 Option;
}; };
struct WI_Client_Request_Struct{
char Client_UUID[64];
char JSON_Data[0];
};
struct WI_Client_Response_Struct{
char Client_UUID[64];
char JSON_Data[0];
};
#pragma pack() #pragma pack()
#endif #endif

View File

@ -41,7 +41,9 @@ extern "C" {
#include <stddef.h> #include <stddef.h>
#include <basetsd.h> #include <basetsd.h>
#ifndef strcasecmp
#define strcasecmp stricmp #define strcasecmp stricmp
#endif
#define getdtablesize() 30000 #define getdtablesize() 30000
#define LWS_VISIBLE #define LWS_VISIBLE

View File

@ -1,13 +1,15 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(web_interface_sources SET(web_interface_sources
call_handler.cpp method_handler.cpp
remote_call.cpp
web_interface.cpp web_interface.cpp
worldserver.cpp worldserver.cpp
) )
SET(web_interface_headers SET(web_interface_headers
call_handler.h method_handler.h
remote_call.h
worldserver.h worldserver.h
) )

View File

@ -1,35 +0,0 @@
#include "web_interface.h"
#include "call_handler.h"
extern std::map<std::string, CallHandler> authorized_calls;
extern std::map<std::string, CallHandler> unauthorized_calls;
void register_authorized_calls()
{
}
void register_unauthorized_calls()
{
unauthorized_calls["token_auth"] = handle_call_token_auth;
}
void register_calls()
{
register_authorized_calls();
register_unauthorized_calls();
}
void handle_call_token_auth(per_session_data_eqemu *session, rapidjson::Document &document)
{
if (!document.HasMember("token")) {
WriteWebCallResponse(session, document, "token_missing");
return;
}
session->auth = document["token"].GetString();
if (!CheckTokenAuthorization(session)) {
WriteWebCallResponse(session, document, "unauthorized");
} else {
WriteWebCallResponse(session, document, "authorized");
}
}

View File

@ -0,0 +1,103 @@
#include "web_interface.h"
#include "method_handler.h"
#include "remote_call.h"
extern WorldServer *worldserver;
extern std::map<std::string, std::pair<int, MethodHandler>> authorized_methods;
extern std::map<std::string, MethodHandler> unauthorized_methods;
void register_authorized_methods()
{
authorized_methods["token_auth"] = std::make_pair(0, handle_method_token_auth);
authorized_methods["list_zones"] = std::make_pair(10, handle_method_no_args);
authorized_methods["get_zone_info"] = std::make_pair(10, handle_method_get_zone_info);
authorized_methods["subscribe"] = std::make_pair(10, handle_method_subscribe);
}
void register_unauthorized_methods()
{
unauthorized_methods["token_auth"] = handle_method_token_auth;
}
void register_methods()
{
register_authorized_methods();
register_unauthorized_methods();
}
void handle_method_token_auth(per_session_data_eqemu *session, rapidjson::Document &document, std::string &method)
{
if (!document.HasMember("token")) {
WriteWebCallResponseString(session, document, "Auth token missing", true);
return;
}
session->auth = document["token"].GetString();
if (!CheckTokenAuthorization(session)) {
WriteWebCallResponseBoolean(session, document, "false", false);
} else {
WriteWebCallResponseBoolean(session, document, "true", false);
}
}
void handle_method_no_args(per_session_data_eqemu *session, rapidjson::Document &document, std::string &method)
{
CheckParams(0, "[]");
VerifyID();
uint32 sz = (uint32)(id.size() + session->uuid.size() + method.size() + 3 + 16);
ServerPacket *pack = new ServerPacket(ServerOP_WIRemoteCall, sz);
pack->WriteUInt32((uint32)id.size());
pack->WriteString(id.c_str());
pack->WriteUInt32((uint32)session->uuid.size());
pack->WriteString(session->uuid.c_str());
pack->WriteUInt32((uint32)method.size());
pack->WriteString(method.c_str());
pack->WriteUInt32(0);
worldserver->SendPacket(pack);
safe_delete(pack);
}
void handle_method_get_zone_info(per_session_data_eqemu *session, rapidjson::Document &document, std::string &method)
{
CheckParams(1, "[zoneserver_id]");
VerifyID();
uint32 sz = (uint32)(id.size() + session->uuid.size() + method.size() + 3 + 16);
auto &params = document["params"];
auto &param = params[(rapidjson::SizeType)0];
if(param.IsNull()) {
sz += 5;
}
else {
sz += (uint32)strlen(param.GetString());
sz += 5;
}
ServerPacket *pack = new ServerPacket(ServerOP_WIRemoteCall, sz);
pack->WriteUInt32((uint32)id.size());
pack->WriteString(id.c_str());
pack->WriteUInt32((uint32)session->uuid.size());
pack->WriteString(session->uuid.c_str());
pack->WriteUInt32((uint32)method.size());
pack->WriteString(method.c_str());
pack->WriteUInt32(1);
pack->WriteUInt32((uint32)strlen(param.GetString()));
pack->WriteString(param.GetString());
worldserver->SendPacket(pack);
safe_delete(pack);
}
void handle_method_subscribe(per_session_data_eqemu *session, rapidjson::Document &document, std::string &method) {
CheckParams(3, "[event, zone_id, instance_id]");
VerifyID();
uint32 sz = (uint32)(id.size() + session->uuid.size() + method.size() + 3 + 16);
auto &params = document["params"];
for(int i = 0; i < 3; ++i) {
auto &param = params[i];
if(param.IsNull()) {
sz += 5;
} else {
sz += (uint32)strlen(param.GetString());
sz += 5;
}
}
}

View File

@ -0,0 +1,51 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WI_METHOD_HANDLER_H
#define WI_METHOD_HANDLER_H
#define CheckParams(sz, msg) if (!document.HasMember("params")) { \
WriteWebCallResponseString(session, document, "Missing parameters, expected: " + std::string(msg), true); \
if (!document.HasMember("params") && sz > 0) { \
WriteWebCallResponseString(session, document, "Missing parameters, expected: " + std::string(msg), true); \
return; \
} \
auto &params = document["params"]; \
if(!params.IsArray()) { \
WriteWebCallResponseString(session, document, "Missing parameters, expected: " + std::string(msg), true); \
return; \
} \
if(params.Size() != sz) { \
WriteWebCallResponseString(session, document, "Missing parameters, expected: " + std::string(msg), true); \
return; \
} \
} \
#define VerifyID() std::string id; \
if (document.HasMember("id")) { \
id = document["id"].GetString(); \
} \
void register_methods();
void handle_method_token_auth(per_session_data_eqemu *session, rapidjson::Document &document, std::string &method);
void handle_method_no_args(per_session_data_eqemu *session, rapidjson::Document &document, std::string &method);
void handle_method_get_zone_info(per_session_data_eqemu *session, rapidjson::Document &document, std::string &method);
void handle_method_subscribe(per_session_data_eqemu *session, rapidjson::Document &document, std::string &method);
#endif

View File

@ -0,0 +1,90 @@
#include "web_interface.h"
#include "remote_call.h"
void WriteWebCallResponseString(per_session_data_eqemu *session, rapidjson::Document &doc, std::string result, bool error, bool send_no_id) {
if (doc.HasMember("id") || send_no_id) {
rapidjson::StringBuffer s;
rapidjson::Writer<rapidjson::StringBuffer> writer(s);
writer.StartObject();
writer.String("id");
if (send_no_id) {
writer.Null();
}
else {
writer.String(doc["id"].GetString());
}
writer.String("result");
writer.String(result.c_str());
writer.String("error");
if (error) {
writer.Bool(true);
}
else {
writer.Null();
}
writer.EndObject();
session->send_queue->push_back(s.GetString());
}
}
void WriteWebCallResponseInt(per_session_data_eqemu *session, rapidjson::Document &doc, int result, bool error, bool send_no_id) {
if (doc.HasMember("id") || send_no_id) {
rapidjson::StringBuffer s;
rapidjson::Writer<rapidjson::StringBuffer> writer(s);
writer.StartObject();
writer.String("id");
if (send_no_id) {
writer.Null();
}
else {
writer.String(doc["id"].GetString());
}
writer.String("result");
writer.Int(result);
writer.String("error");
if (error) {
writer.Bool(true);
}
else {
writer.Null();
}
writer.EndObject();
session->send_queue->push_back(s.GetString());
}
}
void WriteWebCallResponseBoolean(per_session_data_eqemu *session, rapidjson::Document &doc, bool result, bool error, bool send_no_id) {
if (doc.HasMember("id") || send_no_id) {
rapidjson::StringBuffer s;
rapidjson::Writer<rapidjson::StringBuffer> writer(s);
writer.StartObject();
writer.String("id");
if (send_no_id) {
writer.Null();
}
else {
writer.String(doc["id"].GetString());
}
writer.String("result");
writer.Bool(result);
writer.String("error");
if (error) {
writer.Bool(true);
}
else {
writer.Null();
}
writer.EndObject();
session->send_queue->push_back(s.GetString());
}
}
int CheckTokenAuthorization(per_session_data_eqemu *session) {
//todo: actually check this against a table of tokens that is updated periodically
//right now i have just one entry harded coded for testing purposes
if (session->auth.compare("c5b80ec8-4174-4c4c-d332-dbf3c3a551fc") == 0) {
return 255;
}
return 0;
}

View File

@ -15,11 +15,13 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifndef WI_CALL_HANDLER_H #ifndef WI_RPC_H
#define WI_CALL_HANDLER_H #define WI_RPC_H
void register_calls(); void WriteWebCallResponseString(per_session_data_eqemu *session, rapidjson::Document &doc, std::string result, bool error, bool send_no_id = false);
void handle_call_token_auth(per_session_data_eqemu *session, rapidjson::Document &document); void WriteWebCallResponseInt(per_session_data_eqemu *session, rapidjson::Document &doc, int result, bool error, bool send_no_id = false);
void WriteWebCallResponseBoolean(per_session_data_eqemu *session, rapidjson::Document &doc, bool result, bool error, bool send_no_id = false);
int CheckTokenAuthorization(per_session_data_eqemu*);
#endif #endif

View File

@ -1,5 +1,6 @@
#include "web_interface.h" #include "web_interface.h"
#include "call_handler.h" #include "method_handler.h"
#include "remote_call.h"
volatile bool run = true; volatile bool run = true;
TimeoutManager timeout_manager; TimeoutManager timeout_manager;
@ -7,8 +8,8 @@ const EQEmuConfig *config = nullptr;
WorldServer *worldserver = nullptr; WorldServer *worldserver = nullptr;
libwebsocket_context *context = nullptr; libwebsocket_context *context = nullptr;
std::map<std::string, per_session_data_eqemu*> sessions; std::map<std::string, per_session_data_eqemu*> sessions;
std::map<std::string, CallHandler> authorized_calls; std::map<std::string, std::pair<int, MethodHandler>> authorized_methods;
std::map<std::string, CallHandler> unauthorized_calls; std::map<std::string, MethodHandler> unauthorized_methods;
void CatchSignal(int sig_num) { void CatchSignal(int sig_num) {
run = false; run = false;
@ -49,39 +50,47 @@ int callback_eqemu(libwebsocket_context *context, libwebsocket *wsi, libwebsocke
rapidjson::Document document; rapidjson::Document document;
if(document.Parse((const char*)in).HasParseError()) { if(document.Parse((const char*)in).HasParseError()) {
WriteWebCallResponseString(session, document, "Malformed JSON data", true, true);
break; break;
} }
std::string call; std::string method;
if(document.HasMember("call")) { if(document.HasMember("method")) {
call = document["call"].GetString(); method = document["method"].GetString();
} }
if(call.length() == 0) { if(method.length() == 0) {
//No function called, toss this message //No function called, toss this message
WriteWebCallResponse(session, document, "call_empty"); WriteWebCallResponseString(session, document, "No method specified", true);
break; break;
} }
if (!CheckTokenAuthorization(session)) { int status = CheckTokenAuthorization(session);
if (status == 0) {
//check func call against functions that dont req auth //check func call against functions that dont req auth
if (unauthorized_calls.count(call) == 0) { if (unauthorized_methods.count(method) == 0) {
WriteWebCallResponse(session, document, "unauthorized_call_not_found: " + call); WriteWebCallResponseString(session, document, "No suitable method found: " + method, true);
break; break;
} }
auto call_func = unauthorized_methods[method];
auto call_func = unauthorized_calls[call]; call_func(session, document, method);
call_func(session, document);
} }
else { else if(status > 0) {
//check func call against functions that req auth //check func call against functions that req auth
if (authorized_calls.count(call) == 0) { if (authorized_methods.count(method) == 0) {
WriteWebCallResponse(session, document, "authorized_call_not_found: " + call); WriteWebCallResponseString(session, document, "No suitable method found: " + method, true);
break;
}
//check status level
auto iter = authorized_methods.find(method);
if(iter->second.first > status) {
WriteWebCallResponseString(session, document, "Method " + method + " requires status " + std::to_string((long)iter->second.first), true);
break; break;
} }
auto call_func = authorized_calls[call]; auto call_func = iter->second.second;
call_func(session, document); call_func(session, document, method);
} }
break; break;
@ -130,7 +139,7 @@ static struct libwebsocket_protocols protocols[] = {
int main() { int main() {
RegisterExecutablePlatform(ExePlatformWebInterface); RegisterExecutablePlatform(ExePlatformWebInterface);
set_exception_handler(); set_exception_handler();
register_calls(); register_methods();
Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect
_log(WEB_INTERFACE__INIT, "Starting EQEmu Web Server."); _log(WEB_INTERFACE__INIT, "Starting EQEmu Web Server.");
@ -189,27 +198,4 @@ int main() {
return 0; return 0;
} }
void WriteWebCallResponse(per_session_data_eqemu *session, rapidjson::Document &doc, std::string status) {
if (doc.HasMember("id")) {
rapidjson::StringBuffer s;
rapidjson::Writer<rapidjson::StringBuffer> writer(s);
writer.StartObject();
writer.String("id");
writer.String(doc["id"].GetString());
writer.String("status");
writer.String(status.c_str());
writer.EndObject();
session->send_queue->push_back(s.GetString());
}
}
bool CheckTokenAuthorization(per_session_data_eqemu *session) {
//todo: actually check this against a table of tokens that is updated periodically
//right now i have just one entry harded coded for testing purposes
if(session->auth.compare("c5b80ec8-4174-4c4c-d332-dbf3c3a551fc") == 0) {
return true;
}
return false;
}

View File

@ -46,8 +46,6 @@ struct per_session_data_eqemu {
std::list<std::string> *send_queue; std::list<std::string> *send_queue;
}; };
typedef void(*CallHandler)(per_session_data_eqemu*, rapidjson::Document&); typedef void(*MethodHandler)(per_session_data_eqemu*, rapidjson::Document&, std::string&);
void WriteWebCallResponse(per_session_data_eqemu *session, rapidjson::Document &doc, std::string status);
bool CheckTokenAuthorization(per_session_data_eqemu*);
#endif #endif

View File

@ -30,14 +30,8 @@
#include "../common/packet_functions.h" #include "../common/packet_functions.h"
#include "../common/md5.h" #include "../common/md5.h"
#include "../common/packet_dump.h" #include "../common/packet_dump.h"
#include "../common/web_interface_utils.h"
#include "worldserver.h" #include "worldserver.h"
#include "web_interface.h"
struct per_session_data_eqemu {
bool auth;
std::string uuid;
std::list<std::string> *send_queue;
};
extern std::map<std::string, per_session_data_eqemu*> sessions; extern std::map<std::string, per_session_data_eqemu*> sessions;
@ -65,18 +59,74 @@ void WorldServer::Process(){
switch(pack->opcode) { switch(pack->opcode) {
case 0: { break; } case 0: { break; }
case ServerOP_KeepAlive: { break; } case ServerOP_KeepAlive: { break; }
case ServerOP_WIWorldResponse: { case ServerOP_WIRemoteCallResponse: {
/* Generic Response routine: web_interface server recieves packet from World - char *id = nullptr;
Relays data back to client char *session_id = nullptr;
*/ char *error = nullptr;
_log(WEB_INTERFACE__ERROR, "WI Recieved packet from world 0x%04x, size %d", pack->opcode, pack->size);
WI_Client_Request_Struct* WICR = (WI_Client_Request_Struct*)pack->pBuffer; id = new char[pack->ReadUInt32() + 1];
std::string Data; pack->ReadString(id);
Data.assign(WICR->JSON_Data, pack->size - 64);
/* Check if Session is Valid before sending data back*/ session_id = new char[pack->ReadUInt32() + 1];
if (sessions[WICR->Client_UUID]){ pack->ReadString(session_id);
sessions[WICR->Client_UUID]->send_queue->push_back(Data.c_str());
error = new char[pack->ReadUInt32() + 1];
pack->ReadString(error);
uint32 param_count = pack->ReadUInt32();
std::vector<std::string> params;
for(uint32 i = 0; i < param_count; ++i) {
char *p = new char[pack->ReadUInt32() + 1];
pack->ReadString(p);
params.push_back(p);
safe_delete_array(p);
} }
//send the response to client...
rapidjson::StringBuffer s;
rapidjson::Writer<rapidjson::StringBuffer> writer(s);
writer.StartObject();
writer.String("id");
if(strlen(id) == 0) {
writer.Null();
} else {
writer.String(id);
}
if(strlen(error) != 0) {
writer.String("error");
writer.Bool(true);
writer.String("result");
writer.StartArray();
if(params.size() > 0) {
writer.String(params[0].c_str());
} else {
writer.String("");
}
writer.EndArray();
} else {
writer.String("error");
writer.Null();
writer.String("result");
writer.StartArray();
uint32 p_sz = (uint32)params.size();
for(uint32 i = 0; i < p_sz; ++i) {
writer.String(params[i].c_str());
}
writer.EndArray();
}
writer.EndObject();
if(sessions.count(session_id) != 0) {
per_session_data_eqemu *session = sessions[session_id];
session->send_queue->push_back(s.GetString());
}
safe_delete_array(id);
safe_delete_array(session_id);
safe_delete_array(error);
break; break;
} }
} }

View File

@ -23,6 +23,7 @@ SET(world_sources
perl_EQW.cpp perl_EQW.cpp
perl_HTTPRequest.cpp perl_HTTPRequest.cpp
queryserv.cpp queryserv.cpp
remote_call.cpp
ucs.cpp ucs.cpp
web_interface.cpp web_interface.cpp
wguild_mgr.cpp wguild_mgr.cpp
@ -54,6 +55,7 @@ SET(world_headers
LoginServerList.h LoginServerList.h
net.h net.h
queryserv.h queryserv.h
remote_call.h
SoFCharCreateData.h SoFCharCreateData.h
ucs.h ucs.h
web_interface.h web_interface.h

View File

@ -87,6 +87,7 @@
#include "ucs.h" #include "ucs.h"
#include "queryserv.h" #include "queryserv.h"
#include "web_interface.h" #include "web_interface.h"
#include "remote_call.h"
TimeoutManager timeout_manager; TimeoutManager timeout_manager;
EQStreamFactory eqsf(WorldStream,9000); EQStreamFactory eqsf(WorldStream,9000);
@ -107,7 +108,6 @@ uint32 numclients = 0;
uint32 numzones = 0; uint32 numzones = 0;
bool holdzones = false; bool holdzones = false;
extern ConsoleList console_list; extern ConsoleList console_list;
void CatchSignal(int sig_num); void CatchSignal(int sig_num);
@ -115,6 +115,7 @@ void CatchSignal(int sig_num);
int main(int argc, char** argv) { int main(int argc, char** argv) {
RegisterExecutablePlatform(ExePlatformWorld); RegisterExecutablePlatform(ExePlatformWorld);
set_exception_handler(); set_exception_handler();
register_remote_call_handlers();
// Load server configuration // Load server configuration
_log(WORLD__INIT, "Loading server configuration.."); _log(WORLD__INIT, "Loading server configuration..");

88
world/remote_call.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "../common/debug.h"
#include "../common/logsys.h"
#include "../common/logtypes.h"
#include "../common/md5.h"
#include "../common/EmuTCPConnection.h"
#include "../common/packet_dump.h"
#include "WorldConfig.h"
#include "clientlist.h"
#include "zonelist.h"
#include "web_interface.h"
#include "remote_call.h"
#include "zoneserver.h"
extern ClientList client_list;
extern ZSList zoneserver_list;
extern WebInterfaceConnection WILink;
std::map<std::string, RemoteCallHandler> remote_call_methods;
void RemoteCallResponse(const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &res, const std::string &error) {
uint32 sz = connection_id.size() + request_id.size() + error.size() + 3 + 16;
uint32 res_sz = res.size();
for(uint32 i = 0; i < res_sz; ++i) {
sz += res[i].size() + 5;
}
ServerPacket *pack = new ServerPacket(ServerOP_WIRemoteCallResponse, sz);
pack->WriteUInt32((uint32)request_id.size());
pack->WriteString(request_id.c_str());
pack->WriteUInt32((uint32)connection_id.size());
pack->WriteString(connection_id.c_str());
pack->WriteUInt32((uint32)error.size());
pack->WriteString(error.c_str());
pack->WriteUInt32((uint32)res_sz);
for (uint32 i = 0; i < res_sz; ++i) {
auto &r = res[i];
pack->WriteUInt32((uint32)r.size());
pack->WriteString(r.c_str());
}
WILink.SendPacket(pack);
}
void register_remote_call_handlers() {
remote_call_methods["list_zones"] = handle_rc_list_zones;
remote_call_methods["get_zone_info"] = handle_rc_get_zone_info;
}
void handle_rc_list_zones(const std::string &method, const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &params) {
std::vector<uint32> zones;
zoneserver_list.GetZoneIDList(zones);
std::vector<std::string> res;
uint32 sz = (uint32)zones.size();
for(uint32 i = 0; i < sz; ++i) {
res.push_back(itoa(zones[i]));
}
std::string error;
RemoteCallResponse(connection_id, request_id, res, error);
}
void handle_rc_get_zone_info(const std::string &method, const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &params) {
std::string error;
std::vector<std::string> res;
if(params.size() != 1) {
error = "Expected only one zone_id.";
RemoteCallResponse(connection_id, request_id, res, error);
return;
}
ZoneServer *zs = zoneserver_list.FindByID(atoi(params[0].c_str()));
if(zs == nullptr) {
error = "Invalid zone";
RemoteCallResponse(connection_id, request_id, res, error);
return;
}
res.push_back(zs->IsStaticZone() ? "static" : "dynamic");
res.push_back(itoa(zs->GetZoneID()));
res.push_back(itoa(zs->GetInstanceID()));
res.push_back(zs->GetLaunchName());
res.push_back(zs->GetLaunchedName());
res.push_back(zs->GetZoneName());
res.push_back(zs->GetZoneLongName());
res.push_back(itoa(zs->GetCPort()));
res.push_back(itoa(zs->NumPlayers()));
RemoteCallResponse(connection_id, request_id, res, error);
}

34
world/remote_call.h Normal file
View File

@ -0,0 +1,34 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WORLD_REMOTE_CALL_H
#define WORLD_REMOTE_CALL_H
#include <map>
#include <string>
#include <vector>
typedef void(*RemoteCallHandler)(const std::string&, const std::string&, const std::string&, const std::vector<std::string>&);
void RemoteCallResponse(const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &res, const std::string &error);
void register_remote_call_handlers();
void handle_rc_list_zones(const std::string &method, const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &params);
void handle_rc_get_zone_info(const std::string &method, const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &params);
#endif

View File

@ -3,6 +3,7 @@
#include "WorldConfig.h" #include "WorldConfig.h"
#include "clientlist.h" #include "clientlist.h"
#include "zonelist.h" #include "zonelist.h"
#include "remote_call.h"
#include "../common/logsys.h" #include "../common/logsys.h"
#include "../common/logtypes.h" #include "../common/logtypes.h"
#include "../common/md5.h" #include "../common/md5.h"
@ -11,6 +12,7 @@
extern ClientList client_list; extern ClientList client_list;
extern ZSList zoneserver_list; extern ZSList zoneserver_list;
extern std::map<std::string, RemoteCallHandler> remote_call_methods;
WebInterfaceConnection::WebInterfaceConnection() WebInterfaceConnection::WebInterfaceConnection()
{ {
@ -99,18 +101,38 @@ bool WebInterfaceConnection::Process()
_log(WEB_INTERFACE__ERROR, "Got authentication from WebInterface when they are already authenticated."); _log(WEB_INTERFACE__ERROR, "Got authentication from WebInterface when they are already authenticated.");
break; break;
} }
case ServerOP_WIServGeneric: case ServerOP_WIRemoteCall:
{ {
zoneserver_list.SendPacket(pack); // Send to all zones to test char *id = nullptr;
break; char *session_id = nullptr;
} char *method = nullptr;
case ServerOP_WIClientRequest:
{ id = new char[pack->ReadUInt32() + 1];
std::string Data; pack->ReadString(id);
WI_Client_Request_Struct* WICR = (WI_Client_Request_Struct*)pack->pBuffer;
Data.assign(WICR->JSON_Data, pack->size - 64); session_id = new char[pack->ReadUInt32() + 1];
_log(WEB_INTERFACE__ERROR, "Recieved ServerOPcode from WebInterface 0x%04x \nSize %d\nData '%s' from client:\n%s\n", pack->opcode, pack->size, Data.c_str(), WICR->Client_UUID); pack->ReadString(session_id);
zoneserver_list.SendPacket(pack); // Send to all zones to test
method = new char[pack->ReadUInt32() + 1];
pack->ReadString(method);
uint32 param_count = pack->ReadUInt32();
std::vector<std::string> params;
for(uint32 i = 0; i < param_count; ++i) {
char *p = new char[pack->ReadUInt32() + 1];
pack->ReadString(p);
params.push_back(p);
safe_delete_array(p);
}
if (remote_call_methods.count(method) != 0) {
auto f = remote_call_methods[method];
f(method, session_id, id, params);
}
safe_delete_array(id);
safe_delete_array(session_id);
safe_delete_array(method);
break; break;
} }
default: default:

View File

@ -1303,10 +1303,6 @@ bool ZoneServer::Process() {
case ServerOP_CZSignalClientByName: case ServerOP_CZSignalClientByName:
case ServerOP_CZMessagePlayer: case ServerOP_CZMessagePlayer:
case ServerOP_CZSignalClient: case ServerOP_CZSignalClient:
{
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DepopAllPlayersCorpses: case ServerOP_DepopAllPlayersCorpses:
case ServerOP_DepopPlayerCorpse: case ServerOP_DepopPlayerCorpse:
case ServerOP_ReloadTitles: case ServerOP_ReloadTitles:
@ -1318,12 +1314,6 @@ bool ZoneServer::Process() {
zoneserver_list.SendPacket(pack); zoneserver_list.SendPacket(pack);
break; break;
} }
case ServerOP_WIWorldResponse:
{
_log(WEB_INTERFACE__ERROR, "ServerOP_WIWorldResponse for WebInterface 0x%04x, size %d", pack->opcode, pack->size);
WILink.SendPacket(pack);
break;
}
default: default:
{ {
zlog(WORLD__ZONE_ERR,"Unknown ServerOPcode from zone 0x%04x, size %d",pack->opcode,pack->size); zlog(WORLD__ZONE_ERR,"Unknown ServerOPcode from zone 0x%04x, size %d",pack->opcode,pack->size);

View File

@ -22,7 +22,6 @@
#include "worldserver.h" #include "worldserver.h"
#include "QuestParserCollection.h" #include "QuestParserCollection.h"
#include "../common/StringUtil.h" #include "../common/StringUtil.h"
#include "../common/web_interface_utils.h"
#include <sstream> #include <sstream>
#include <math.h> #include <math.h>
@ -32,7 +31,6 @@ extern EntityList entity_list;
extern Zone* zone; extern Zone* zone;
extern WorldServer worldserver; extern WorldServer worldserver;
extern std::string WS_Client_Connected;
Mob::Mob(const char* in_name, Mob::Mob(const char* in_name,
const char* in_lastname, const char* in_lastname,
@ -1215,19 +1213,19 @@ void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){
spu->padding0014 =0x7f; spu->padding0014 =0x7f;
spu->padding0018 =0x5df27; spu->padding0018 =0x5df27;
/* Testing */ ///* Testing */
if (IsNPC() && WS_Client_Connected.size() != 0){ //if (IsNPC() && WS_Client_Connected.size() != 0){
std::string str = MakeJSON("ResponseType:PositionUpdate,entity:" + std::to_string(GetID()) + ",name:" + GetName() + ",x:" + std::to_string(x_pos) + ",y:" + std::to_string(y_pos) + ",z:" + std::to_string(z_pos) + ",h:" + std::to_string(heading)); // std::string str = MakeJSON("ResponseType:PositionUpdate,entity:" + std::to_string(GetID()) + ",name:" + GetName() + ",x:" + std::to_string(x_pos) + ",y:" + std::to_string(y_pos) + ",z:" + std::to_string(z_pos) + ",h:" + std::to_string(heading));
char * writable = new char[str.size() + 1]; // char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable); // std::copy(str.begin(), str.end(), writable);
ServerPacket* pack = new ServerPacket(ServerOP_WIWorldResponse, sizeof(WI_Client_Response_Struct)+str.length() + 1); // ServerPacket* pack = new ServerPacket(ServerOP_WIWorldResponse, sizeof(WI_Client_Response_Struct)+str.length() + 1);
WI_Client_Response_Struct* WICR = (WI_Client_Response_Struct*)pack->pBuffer; // WI_Client_Response_Struct* WICR = (WI_Client_Response_Struct*)pack->pBuffer;
strn0cpy(WICR->Client_UUID, WS_Client_Connected.c_str(), 64); // strn0cpy(WICR->Client_UUID, WS_Client_Connected.c_str(), 64);
strn0cpy(WICR->JSON_Data, str.c_str(), str.length() + 1); // strn0cpy(WICR->JSON_Data, str.c_str(), str.length() + 1);
if (worldserver.Connected()) { worldserver.SendPacket(pack); } // if (worldserver.Connected()) { worldserver.SendPacket(pack); }
safe_delete(pack); // safe_delete(pack);
delete[] writable; // delete[] writable;
} //}
} }
// this is for SendPosUpdate() // this is for SendPosUpdate()

View File

@ -100,7 +100,6 @@ DBAsyncFinishedQueue MTdbafq;
DBAsync *dbasync = nullptr; DBAsync *dbasync = nullptr;
TaskManager *taskmanager = 0; TaskManager *taskmanager = 0;
QuestParserCollection *parse = 0; QuestParserCollection *parse = 0;
std::string WS_Client_Connected;
const SPDat_Spell_Struct* spells; const SPDat_Spell_Struct* spells;
void LoadSpells(EQEmu::MemoryMappedFile **mmf); void LoadSpells(EQEmu::MemoryMappedFile **mmf);

View File

@ -62,7 +62,6 @@ extern NetConnection net;
extern PetitionList petition_list; extern PetitionList petition_list;
extern uint32 numclients; extern uint32 numclients;
extern volatile bool RunLoops; extern volatile bool RunLoops;
extern std::string WS_Client_Connected;
WorldServer::WorldServer() WorldServer::WorldServer()
: WorldConnection(EmuTCPConnection::packetModeZone) : WorldConnection(EmuTCPConnection::packetModeZone)
@ -1778,13 +1777,6 @@ void WorldServer::Process() {
break; break;
} }
case ServerOP_WIClientRequest:
{
WI_Client_Request_Struct* WICR = (WI_Client_Request_Struct*)pack->pBuffer;
WS_Client_Connected = WICR->Client_UUID;
_log(WEB_INTERFACE__ERROR, "Recieved packet from World, setting Client Connected to %s", WICR->Client_UUID);
break;
}
case ServerOP_CZSignalClient: case ServerOP_CZSignalClient:
{ {
CZClientSignal_Struct* CZCS = (CZClientSignal_Struct*) pack->pBuffer; CZClientSignal_Struct* CZCS = (CZClientSignal_Struct*) pack->pBuffer;