TrinityCore
Loading...
Searching...
No Matches
TCSoap.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "TCSoap.h"
19#include "AccountMgr.h"
20#include "IpAddress.h"
21#include "Log.h"
22#include "Memory.h"
23#include "RealmList.h"
24#include "World.h"
25#include "soapH.h"
26#include "soapStub.h"
27
28std::thread* CreateSoapThread(const std::string& host, uint16 port)
29{
30 auto soap = Trinity::make_unique_ptr_with_deleter(new struct soap(), [](struct soap* soap)
31 {
32 soap_destroy(soap);
33 soap_end(soap);
34 soap_done(soap);
35 delete soap;
36 });
37
38 soap_init(soap.get());
39 soap_set_imode(soap.get(), SOAP_C_UTFSTRING);
40 soap_set_omode(soap.get(), SOAP_C_UTFSTRING);
41
42#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
43 soap->bind_flags = SO_REUSEADDR;
44#endif
45
46 // check every 3 seconds if world ended
47 soap->accept_timeout = 3;
48 soap->recv_timeout = 5;
49 soap->send_timeout = 5;
50 if (!soap_valid_socket(soap_bind(soap.get(), host.c_str(), port, 100)))
51 {
52 TC_LOG_ERROR("network.soap", "Couldn't bind to {}:{}", host, port);
53 return nullptr;
54 }
55
56 TC_LOG_INFO("network.soap", "Bound to http://{}:{}", host, port);
57
58 return new std::thread([soap = std::move(soap)]
59 {
60 while (!World::IsStopped())
61 {
62 if (!soap_valid_socket(soap_accept(soap.get())))
63 continue; // ran into an accept timeout
64
65 struct soap* thread_soap = soap_copy(soap.get());// make a safe copy
66 TC_LOG_DEBUG("network.soap", "Accepted connection from IP={}", Trinity::Net::make_address_v4(thread_soap->ip).to_string());
67 process_message(thread_soap);
68 }
69 });
70}
71
72void process_message(struct soap* soap_message)
73{
74 TC_LOG_TRACE("network.soap", "SOAPWorkingThread::process_message");
75
76 soap_serve(soap_message);
77 soap_destroy(soap_message); // dealloc C++ data
78 soap_end(soap_message); // dealloc data and clean up
79 soap_free(soap_message); // detach soap struct and free up the memory
80}
81/*
82Code used for generating stubs:
83
84int ns1__executeCommand(char* command, char** result);
85*/
86int ns1__executeCommand(soap* soap, char* command, char** result)
87{
88 // security check
89 if (!soap->userid || !soap->passwd)
90 {
91 TC_LOG_INFO("network.soap", "Client didn't provide login information");
92 return 401;
93 }
94
95 uint32 accountId = AccountMgr::GetId(soap->userid);
96 if (!accountId)
97 {
98 TC_LOG_INFO("network.soap", "Client used invalid username '{}'", soap->userid);
99 return 401;
100 }
101
102 if (!AccountMgr::CheckPassword(accountId, soap->passwd))
103 {
104 TC_LOG_INFO("network.soap", "Invalid password for account '{}'", soap->userid);
105 return 401;
106 }
107
108 if (AccountMgr::GetSecurity(accountId, sRealmList->GetCurrentRealmId().Realm) < SEC_ADMINISTRATOR)
109 {
110 TC_LOG_INFO("network.soap", "{}'s gmlevel is too low", soap->userid);
111 return 403;
112 }
113
114 if (!command || !*command)
115 return soap_sender_fault(soap, "Command can not be empty", "The supplied command was an empty string");
116
117 TC_LOG_INFO("network.soap", "Received command '{}'", command);
118 SOAPCommand connection;
119
120 // commands are executed in the world thread. We have to wait for them to be completed
121 {
122 // CliCommandHolder will be deleted from world, accessing after queueing is NOT safe
124 sWorld->QueueCliCommand(cmd);
125 }
126
127 // Wait until the command has finished executing
128 connection.finishedPromise.get_future().wait();
129
130 // The command has finished executing already
131 char* printBuffer = soap_strdup(soap, connection.m_printBuffer.c_str());
132 if (connection.hasCommandSucceeded())
133 {
134 *result = printBuffer;
135 return SOAP_OK;
136 }
137 else
138 return soap_sender_fault(soap, printBuffer, printBuffer);
139}
140
141void SOAPCommand::commandFinished(void* soapconnection, bool success)
142{
143 SOAPCommand* con = (SOAPCommand*)soapconnection;
144 con->setCommandSuccess(success);
145}
146
148//
149// Namespace Definition Table
150//
152
153struct Namespace namespaces[] =
154{ { "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", nullptr, nullptr }, // must be first
155 { "SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", nullptr, nullptr }, // must be second
156 { "xsi", "http://www.w3.org/1999/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", nullptr },
157 { "xsd", "http://www.w3.org/1999/XMLSchema", "http://www.w3.org/*/XMLSchema", nullptr },
158 { "ns1", "urn:TC", nullptr, nullptr }, // "ns1" namespace prefix
159 { nullptr, nullptr, nullptr, nullptr }
160};
@ SEC_ADMINISTRATOR
Definition Common.h:46
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_INFO(filterType__, message__,...)
Definition Log.h:184
#define TC_LOG_TRACE(filterType__, message__,...)
Definition Log.h:178
#define sRealmList
Definition RealmList.h:93
std::thread * CreateSoapThread(const std::string &host, uint16 port)
Definition TCSoap.cpp:28
struct Namespace namespaces[]
Definition TCSoap.cpp:153
void process_message(struct soap *soap_message)
Definition TCSoap.cpp:72
int ns1__executeCommand(soap *soap, char *command, char **result)
Definition TCSoap.cpp:86
static uint32 GetSecurity(uint32 accountId, int32 realmId)
static bool CheckPassword(std::string username, std::string password)
static uint32 GetId(std::string_view username)
static void commandFinished(void *callbackArg, bool success)
Definition TCSoap.cpp:141
bool hasCommandSucceeded() const
Definition TCSoap.h:52
static void print(void *callbackArg, std::string_view msg)
Definition TCSoap.h:57
std::string m_printBuffer
Definition TCSoap.h:65
void setCommandSuccess(bool val)
Definition TCSoap.h:46
std::promise< void > finishedPromise
Definition TCSoap.h:66
static bool IsStopped()
Definition World.h:668
#define sWorld
Definition World.h:916
std::unique_ptr< T, Impl::stateful_unique_ptr_deleter< Ptr, Del > > make_unique_ptr_with_deleter(Ptr ptr, Del deleter)
Definition Memory.h:133
Storage class for commands issued for delayed execution.
Definition World.h:534