AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
ACSoap.cpp File Reference
#include "ACSoap.h"
#include "AccountMgr.h"
#include "Log.h"
#include "World.h"
#include "soapStub.h"
#include <chrono>
#include <memory>

Go to the source code of this file.

Functions

void ACSoapThread (const std::string &host, uint16 port)
 
void process_message (struct soap *soap_message)
 
int ns1__executeCommand (soap *soap, char *command, char **result)
 

Variables

struct Namespace namespaces []
 

Function Documentation

◆ ACSoapThread()

void ACSoapThread ( const std::string &  host,
uint16  port 
)
27{
28 struct soap soap;
29 soap_init(&soap);
30 soap_set_imode(&soap, SOAP_C_UTFSTRING);
31 soap_set_omode(&soap, SOAP_C_UTFSTRING);
32
33 // check every 3 seconds if world ended
34 soap.accept_timeout = 3;
35 soap.recv_timeout = 5;
36 soap.send_timeout = 5;
37
38 // allow rebinding while the previous socket is still in TIME_WAIT (e.g. on a quick restart)
39 soap.bind_flags = SO_REUSEADDR;
40
41 if (!soap_valid_socket(soap_bind(&soap, host.c_str(), port, 100)))
42 {
43 LOG_ERROR("network.soap", "ACSoap: couldn't bind to {}:{}", host, port);
44 // graceful shutdown: exit() here would destroy SocketMgr before StopNetwork() and assert
46 return;
47 }
48
49 LOG_INFO("network.soap", "ACSoap: bound to http://{}:{}", host, port);
50
51 while (!World::IsStopped())
52 {
53 if (!soap_valid_socket(soap_accept(&soap)))
54 continue; // ran into an accept timeout
55
56 LOG_DEBUG("network.soap", "ACSoap: accepted connection from IP={}.{}.{}.{}", (int)(soap.ip >> 24) & 0xFF, (int)(soap.ip >> 16) & 0xFF, (int)(soap.ip >> 8) & 0xFF, (int)soap.ip & 0xFF);
57 struct soap* thread_soap = soap_copy(&soap);// make a safe copy
58
59 process_message(thread_soap);
60 }
61
62 soap_destroy(&soap);
63 soap_end(&soap);
64 soap_done(&soap);
65}
void process_message(struct soap *soap_message)
Definition ACSoap.cpp:67
#define LOG_INFO(filterType__,...)
Definition Log.h:153
#define LOG_ERROR(filterType__,...)
Definition Log.h:145
#define LOG_DEBUG(filterType__,...)
Definition Log.h:157
static void StopNow(uint8 exitcode)
Definition World.h:188
static bool IsStopped()
Definition World.h:189
@ ERROR_EXIT_CODE
Definition World.h:54

References ERROR_EXIT_CODE, World::IsStopped(), LOG_DEBUG, LOG_ERROR, LOG_INFO, process_message(), and World::StopNow().

Referenced by main().

◆ ns1__executeCommand()

int ns1__executeCommand ( soap *  soap,
char *  command,
char **  result 
)
82{
83 // security check
84 if (!soap->userid || !soap->passwd)
85 {
86 LOG_DEBUG("network.soap", "ACSoap: Client didn't provide login information");
87 return 401;
88 }
89
90 uint32 accountId = AccountMgr::GetId(soap->userid);
91 if (!accountId)
92 {
93 LOG_DEBUG("network", "ACSoap: Client used invalid username '{}'", soap->userid);
94 return 401;
95 }
96
97 if (!AccountMgr::CheckPassword(accountId, soap->passwd))
98 {
99 LOG_DEBUG("network.soap", "ACSoap: invalid password for account '{}'", soap->userid);
100 return 401;
101 }
102
104 {
105 LOG_DEBUG("network.soap", "ACSoap: {}'s gmlevel is too low", soap->userid);
106 return 403;
107 }
108
109 if (!command || !*command)
110 return soap_sender_fault(soap, "Command can not be empty", "The supplied command was an empty string");
111
112 LOG_DEBUG("network.soap", "ACSoap: got command '{}'", command);
113
114 // Shared so the object survives if we stop waiting below: the queued command keeps a raw
115 // pointer to it and the world thread may still run it after that. The extra reference is
116 // released by commandFinished() once the world side is done with it.
117 auto connection = std::make_shared<SOAPCommand>();
118 connection->m_self = connection;
119
120 // commands are executed in the world thread. We have to wait for them to be completed
121 sWorld->QueueCliCommand(new CliCommandHolder(connection.get(), command, &SOAPCommand::print, &SOAPCommand::commandFinished));
122
123 // Wait for the command to finish, but bail on shutdown: ProcessCliCommands() (which fulfils
124 // the promise) stops once the world loop exits, so an unbounded wait here would deadlock.
125 std::future<void> finished = connection->finishedPromise.get_future();
126 while (finished.wait_for(std::chrono::seconds(1)) != std::future_status::ready)
127 {
128 if (World::IsStopped())
129 return soap_receiver_fault(soap, "Server is shutting down", "Command aborted: the server is shutting down");
130 }
131
132 // The command has finished executing already
133 char* printBuffer = soap_strdup(soap, connection->m_printBuffer.c_str());
134 if (connection->hasCommandSucceeded())
135 {
136 *result = printBuffer;
137 return SOAP_OK;
138 }
139 else
140 return soap_sender_fault(soap, printBuffer, printBuffer);
141}
@ SEC_ADMINISTRATOR
Definition Common.h:60
std::uint32_t uint32
Definition Define.h:107
static bool CheckPassword(uint32 accountId, std::string password)
Definition AccountMgr.cpp:291
static uint32 GetSecurity(uint32 accountId)
Definition AccountMgr.cpp:257
static uint32 GetId(std::string const &username)
Definition AccountMgr.cpp:248
static void commandFinished(void *callbackArg, bool success)
Definition ACSoap.cpp:143
static void print(void *callbackArg, std::string_view msg)
Definition ACSoap.h:52
#define sWorld
Definition World.h:317
Storage class for commands issued for delayed execution.
Definition IWorld.h:35

References AccountMgr::CheckPassword(), SOAPCommand::commandFinished(), AccountMgr::GetId(), AccountMgr::GetSecurity(), World::IsStopped(), LOG_DEBUG, SOAPCommand::print(), SEC_ADMINISTRATOR, and sWorld.

◆ process_message()

void process_message ( struct soap *  soap_message)
68{
69 LOG_TRACE("network.soap", "SOAPWorkingThread::process_message");
70
71 soap_serve(soap_message);
72 soap_destroy(soap_message); // dealloc C++ data
73 soap_end(soap_message); // dealloc data and clean up
74 soap_free(soap_message); // detach soap struct and fre up the memory
75}
#define LOG_TRACE(filterType__,...)
Definition Log.h:161

References LOG_TRACE.

Referenced by ACSoapThread().

Variable Documentation

◆ namespaces

struct Namespace namespaces[]
Initial value:
=
{
{ "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", nullptr, nullptr },
{ "SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", nullptr, nullptr },
{ "xsi", "http://www.w3.org/1999/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", nullptr },
{ "xsd", "http://www.w3.org/1999/XMLSchema", "http://www.w3.org/*/XMLSchema", nullptr },
{ "ns1", "urn:AC", nullptr, nullptr },
{ nullptr, nullptr, nullptr, nullptr }
}
158{
159 { "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", nullptr, nullptr }, // must be first
160 { "SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", nullptr, nullptr }, // must be second
161 { "xsi", "http://www.w3.org/1999/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", nullptr },
162 { "xsd", "http://www.w3.org/1999/XMLSchema", "http://www.w3.org/*/XMLSchema", nullptr },
163 { "ns1", "urn:AC", nullptr, nullptr }, // "ns1" namespace prefix
164 { nullptr, nullptr, nullptr, nullptr }
165};