diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 6fcaed04b..a3faf0ad6 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -16,8 +16,6 @@ SET(common_sources emu_legacy.cpp emu_limits.cpp emu_opcodes.cpp - emu_tcp_connection.cpp - emu_tcp_server.cpp emu_versions.cpp eqdb.cpp eqdb_res.cpp @@ -67,12 +65,9 @@ SET(common_sources spdat.cpp string_util.cpp struct_strategy.cpp - tcp_connection.cpp - tcp_server.cpp textures.cpp timer.cpp unix.cpp - worldconn.cpp xml_parser.cpp platform.cpp event/event_loop.cpp @@ -100,17 +95,6 @@ SET(common_sources patches/titanium_limits.cpp patches/uf.cpp patches/uf_limits.cpp - SocketLib/Base64.cpp - SocketLib/File.cpp - SocketLib/HttpdCookies.cpp - SocketLib/HttpdForm.cpp - SocketLib/HttpdSocket.cpp - SocketLib/HTTPSocket.cpp - SocketLib/MemFile.cpp - SocketLib/Mime.cpp - SocketLib/Parse.cpp - SocketLib/socket_include.cpp - SocketLib/Utility.cpp StackWalker/StackWalker.cpp tinyxml/tinystr.cpp tinyxml/tinyxml.cpp @@ -138,8 +122,6 @@ SET(common_headers emu_limits.h emu_opcodes.h emu_oplist.h - emu_tcp_connection.h - emu_tcp_server.h emu_versions.h eq_constants.h eq_packet_structs.h @@ -210,16 +192,12 @@ SET(common_headers spdat.h string_util.h struct_strategy.h - tcp_basic_server.h - tcp_connection.h - tcp_server.h textures.h timer.h types.h unix.h useperl.h version.h - worldconn.h xml_parser.h zone_numbers.h event/background_task.h @@ -269,18 +247,6 @@ SET(common_headers patches/uf_limits.h patches/uf_ops.h patches/uf_structs.h - SocketLib/Base64.h - SocketLib/File.h - SocketLib/HttpdCookies.h - SocketLib/HttpdForm.h - SocketLib/HttpdSocket.h - SocketLib/HTTPSocket.h - SocketLib/IFile.h - SocketLib/MemFile.h - SocketLib/Mime.h - SocketLib/Parse.h - SocketLib/socket_include.h - SocketLib/Utility.h StackWalker/StackWalker.h tinyxml/tinystr.h tinyxml/tinyxml.h @@ -374,32 +340,6 @@ SOURCE_GROUP(Patches FILES patches/uf_limits.cpp ) -SOURCE_GROUP(SocketLib FILES - SocketLib/Base64.h - SocketLib/File.h - SocketLib/HttpdCookies.h - SocketLib/HttpdForm.h - SocketLib/HttpdSocket.h - SocketLib/HTTPSocket.h - SocketLib/IFile.h - SocketLib/MemFile.h - SocketLib/Mime.h - SocketLib/Parse.h - SocketLib/socket_include.h - SocketLib/Utility.h - SocketLib/Base64.cpp - SocketLib/File.cpp - SocketLib/HttpdCookies.cpp - SocketLib/HttpdForm.cpp - SocketLib/HttpdSocket.cpp - SocketLib/HTTPSocket.cpp - SocketLib/MemFile.cpp - SocketLib/Mime.cpp - SocketLib/Parse.cpp - SocketLib/socket_include.cpp - SocketLib/Utility.cpp -) - SOURCE_GROUP(StackWalker FILES StackWalker/StackWalker.h StackWalker/StackWalker.cpp diff --git a/common/emu_tcp_connection.cpp b/common/emu_tcp_connection.cpp deleted file mode 100644 index 0a0444c69..000000000 --- a/common/emu_tcp_connection.cpp +++ /dev/null @@ -1,818 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 -*/ - -/* -There are really two or three different objects shoe-hored into this -connection object. Sombody really needs to factor out the relay link -crap into its own subclass of this object, it will clean things up -tremendously. -*/ - -#include "../common/global_define.h" - -#include -#include - -#include "emu_tcp_connection.h" -#include "emu_tcp_server.h" -#include "../common/servertalk.h" - -#ifdef FREEBSD //Timothy Whitman - January 7, 2003 - #define MSG_NOSIGNAL 0 -#endif - -#define TCPN_DEBUG 0 -#define TCPN_DEBUG_Console 0 -#define TCPN_DEBUG_Memory 0 -#define TCPN_LOG_PACKETS 0 -#define TCPN_LOG_RAW_DATA_OUT 0 -#define TCPN_LOG_RAW_DATA_IN 0 - - -//server side case -EmuTCPConnection::EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, SOCKET in_socket, uint32 irIP, uint16 irPort, bool iOldFormat) -: TCPConnection(ID, in_socket, irIP, irPort), - keepalive_timer(SERVER_TIMEOUT), - timeout_timer(SERVER_TIMEOUT * 2) -{ - id = 0; - Server = nullptr; - pOldFormat = iOldFormat; - #ifdef MINILOGIN - TCPMode = modePacket; - PacketMode = packetModeLogin; - #else - if (pOldFormat) - TCPMode = modePacket; - else - TCPMode = modeConsole; - PacketMode = packetModeZone; - #endif - RelayLink = 0; - RelayServer = false; - RelayCount = 0; - RemoteID = 0; - -} - -//client outgoing connection case (and client side relay) -EmuTCPConnection::EmuTCPConnection(bool iOldFormat, EmuTCPServer* iRelayServer, eTCPMode iMode) -: TCPConnection(), - keepalive_timer(SERVER_TIMEOUT), - timeout_timer(SERVER_TIMEOUT * 2) -{ - Server = iRelayServer; - if (Server) - RelayServer = true; - else - RelayServer = false; - RelayLink = 0; - RelayCount = 0; - RemoteID = 0; - pOldFormat = iOldFormat; - TCPMode = iMode; - PacketMode = packetModeZone; -#if TCPN_DEBUG_Memory >= 7 - std::cout << "Constructor #1 on outgoing TCP# " << GetID() << std::endl; -#endif -} - -//server side relay case -EmuTCPConnection::EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, EmuTCPConnection* iRelayLink, uint32 iRemoteID, uint32 irIP, uint16 irPort) -: TCPConnection(ID, 0, irIP, irPort), - keepalive_timer(SERVER_TIMEOUT), - timeout_timer(SERVER_TIMEOUT * 2) -{ - Server = iServer; - RelayLink = iRelayLink; - RelayServer = true; - RelayCount = 0; - RemoteID = iRemoteID; - pOldFormat = false; - ConnectionType = Incoming; - TCPMode = modePacket; - PacketMode = packetModeZone; -#if TCPN_DEBUG_Memory >= 7 - std::cout << "Constructor #3 on outgoing TCP# " << GetID() << std::endl; -#endif -} - -EmuTCPConnection::~EmuTCPConnection() { - //the queues free their content right now I believe. -} - -EmuTCPNetPacket_Struct* EmuTCPConnection::MakePacket(ServerPacket* pack, uint32 iDestination) { - int32 size = sizeof(EmuTCPNetPacket_Struct) + pack->size; - if (pack->compressed) { - size += 4; - } - if (iDestination) { - size += 4; - } - EmuTCPNetPacket_Struct* tnps = (EmuTCPNetPacket_Struct*) new uchar[size]; - tnps->size = size; - tnps->opcode = pack->opcode; - *((uint8*) &tnps->flags) = 0; - uchar* buffer = tnps->buffer; - if (pack->compressed) { - tnps->flags.compressed = 1; - *((int32*) buffer) = pack->InflatedSize; - buffer += 4; - } - if (iDestination) { - tnps->flags.destination = 1; - *((int32*) buffer) = iDestination; - buffer += 4; - } - memcpy(buffer, pack->pBuffer, pack->size); - return tnps; -} - -SPackSendQueue* EmuTCPConnection::MakeOldPacket(ServerPacket* pack) { - SPackSendQueue* spsq = (SPackSendQueue*) new uchar[sizeof(SPackSendQueue) + pack->size + 4]; - if (pack->pBuffer != 0 && pack->size != 0) - memcpy((char *) &spsq->buffer[4], (char *) pack->pBuffer, pack->size); - memcpy((char *) &spsq->buffer[0], (char *) &pack->opcode, 2); - spsq->size = pack->size+4; - memcpy((char *) &spsq->buffer[2], (char *) &spsq->size, 2); - return spsq; -} - -bool EmuTCPConnection::SendPacket(ServerPacket* pack, uint32 iDestination) { - if (!Connected()) - return false; - eTCPMode tmp = GetMode(); - if (tmp != modePacket && tmp != modeTransition) - return false; - LockMutex lock(&MState); - if (RemoteID) - return RelayLink->SendPacket(pack, RemoteID); - else if (pOldFormat) { - #if TCPN_LOG_PACKETS >= 1 - if (pack && pack->opcode != 0) { - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Logging outgoing TCP OldPacket. OPCode: 0x" << std::hex << std::setw(4) << std::setfill('0') << pack->opcode << std::dec << ", size: " << std::setw(5) << std::setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; - #if TCPN_LOG_PACKETS == 2 - if (pack->size >= 32) - DumpPacket(pack->pBuffer, 32); - else - DumpPacket(pack); - #endif - #if TCPN_LOG_PACKETS >= 3 - DumpPacket(pack); - #endif - } - #endif - SPackSendQueue* spsq = MakeOldPacket(pack); - ServerSendQueuePushEnd(spsq->buffer, spsq->size); - safe_delete_array(spsq); - } - else { - EmuTCPNetPacket_Struct* tnps = MakePacket(pack, iDestination); - if (tmp == modeTransition) { - InModeQueuePush(tnps); - } - else { - #if TCPN_LOG_PACKETS >= 1 - if (pack && pack->opcode != 0) { - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Logging outgoing TCP packet. OPCode: 0x" << std::hex << std::setw(4) << std::setfill('0') << pack->opcode << std::dec << ", size: " << std::setw(5) << std::setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; - #if TCPN_LOG_PACKETS == 2 - if (pack->size >= 32) - DumpPacket(pack->pBuffer, 32); - else - DumpPacket(pack); - #endif - #if TCPN_LOG_PACKETS >= 3 - DumpPacket(pack); - #endif - } - #endif - ServerSendQueuePushEnd((uchar**) &tnps, tnps->size); - } - } - return true; -} - -bool EmuTCPConnection::SendPacket(EmuTCPNetPacket_Struct* tnps) { - if (RemoteID) - return false; - if (!Connected()) - return false; - if (GetMode() != modePacket) - return false; - - LockMutex lock(&MState); - eTCPMode tmp = GetMode(); - if (tmp == modeTransition) { - EmuTCPNetPacket_Struct* tnps2 = (EmuTCPNetPacket_Struct*) new uchar[tnps->size]; - memcpy(tnps2, tnps, tnps->size); - InModeQueuePush(tnps2); - return true; - } - #if TCPN_LOG_PACKETS >= 1 - if (tnps && tnps->opcode != 0) { - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Logging outgoing TCP NetPacket. OPCode: 0x" << std::hex << std::setw(4) << std::setfill('0') << tnps->opcode << std::dec << ", size: " << std::setw(5) << std::setfill(' ') << tnps->size << " " << inet_ntoa(in) << ":" << GetrPort(); - if (pOldFormat) - std::cout << " (OldFormat)"; - std::cout << std::endl; - #if TCPN_LOG_PACKETS == 2 - if (tnps->size >= 32) - DumpPacket((uchar*) tnps, 32); - else - DumpPacket((uchar*) tnps, tnps->size); - #endif - #if TCPN_LOG_PACKETS >= 3 - DumpPacket((uchar*) tnps, tnps->size); - #endif - } - #endif - ServerSendQueuePushEnd((const uchar*) tnps, tnps->size); - return true; -} - -ServerPacket* EmuTCPConnection::PopPacket() { - ServerPacket* ret; - if (!MOutQueueLock.trylock()) - return nullptr; - ret = OutQueue.pop(); - MOutQueueLock.unlock(); - return ret; -} - -void EmuTCPConnection::InModeQueuePush(EmuTCPNetPacket_Struct* tnps) { - MSendQueue.lock(); - InModeQueue.push(tnps); - MSendQueue.unlock(); -} - -void EmuTCPConnection::OutQueuePush(ServerPacket* pack) { - MOutQueueLock.lock(); - OutQueue.push(pack); - MOutQueueLock.unlock(); -} - - -bool EmuTCPConnection::LineOutQueuePush(char* line) { - #if defined(GOTFRAGS) && 0 - if (strcmp(line, "**CRASHME**") == 0) { - int i = 0; - std::cout << (5 / i) << std::endl; - } - #endif - if(line[0] == '*') { - if (strcmp(line, "**PACKETMODE**") == 0) { - MSendQueue.lock(); - safe_delete_array(sendbuf); - if (TCPMode == modeConsole) - Send((const uchar*) "\0**PACKETMODE**\r", 16); - TCPMode = modePacket; - PacketMode = packetModeLogin; - EmuTCPNetPacket_Struct* tnps = 0; - while ((tnps = InModeQueue.pop())) { - SendPacket(tnps); - safe_delete_array(tnps); - } - MSendQueue.unlock(); - safe_delete_array(line); - return(true); - } - if (strcmp(line, "**PACKETMODEZONE**") == 0) { - MSendQueue.lock(); - safe_delete_array(sendbuf); - if (TCPMode == modeConsole) - Send((const uchar*) "\0**PACKETMODEZONE**\r", 20); - TCPMode = modePacket; - PacketMode = packetModeZone; - EmuTCPNetPacket_Struct* tnps = 0; - while ((tnps = InModeQueue.pop())) { - SendPacket(tnps); - safe_delete_array(tnps); - } - MSendQueue.unlock(); - safe_delete_array(line); - return(true); - } - if (strcmp(line, "**PACKETMODELAUNCHER**") == 0) { - MSendQueue.lock(); - safe_delete_array(sendbuf); - if (TCPMode == modeConsole) - Send((const uchar*) "\0**PACKETMODELAUNCHER**\r", 24); - TCPMode = modePacket; - PacketMode = packetModeLauncher; - EmuTCPNetPacket_Struct* tnps = 0; - while ((tnps = InModeQueue.pop())) { - SendPacket(tnps); - safe_delete_array(tnps); - } - MSendQueue.unlock(); - safe_delete_array(line); - return(true); - } - if (strcmp(line, "**PACKETMODEUCS**") == 0) { - MSendQueue.lock(); - safe_delete_array(sendbuf); - if (TCPMode == modeConsole) - Send((const uchar*) "\0**PACKETMODEUCS**\r", 19); - TCPMode = modePacket; - PacketMode = packetModeUCS; - EmuTCPNetPacket_Struct* tnps = 0; - while ((tnps = InModeQueue.pop())) { - SendPacket(tnps); - safe_delete_array(tnps); - } - MSendQueue.unlock(); - safe_delete_array(line); - return(true); - } - if (strcmp(line, "**PACKETMODEQS**") == 0) { - MSendQueue.lock(); - safe_delete_array(sendbuf); - if (TCPMode == modeConsole) - Send((const uchar*) "\0**PACKETMODEQS**\r", 18); - TCPMode = modePacket; - PacketMode = packetModeQueryServ; - EmuTCPNetPacket_Struct* tnps = 0; - while ((tnps = InModeQueue.pop())) { - SendPacket(tnps); - safe_delete_array(tnps); - } - MSendQueue.unlock(); - safe_delete_array(line); - return(true); - } - } - - return(TCPConnection::LineOutQueuePush(line)); -} - -void EmuTCPConnection::Disconnect(bool iSendRelayDisconnect) { - TCPConnection::Disconnect(); - - if (RelayLink) { - RelayLink->RemoveRelay(this, iSendRelayDisconnect); - RelayLink = 0; - } -} - -bool EmuTCPConnection::ConnectIP(uint32 irIP, uint16 irPort, char* errbuf) { - if(!TCPConnection::ConnectIP(irIP, irPort, errbuf)) - return(false); - - MSendQueue.lock(); - #ifdef MINILOGIN - TCPMode = modePacket; - #else - if (pOldFormat) { - TCPMode = modePacket; - } - else if (TCPMode == modePacket || TCPMode == modeTransition) { - TCPMode = modeTransition; - if(PacketMode == packetModeLauncher) { - safe_delete_array(sendbuf); - sendbuf_size = 24; - sendbuf_used = sendbuf_size; - sendbuf = new uchar[sendbuf_size]; - memcpy(sendbuf, "\0**PACKETMODELAUNCHER**\r", sendbuf_size); - } else if(PacketMode == packetModeLogin) { - safe_delete_array(sendbuf); - sendbuf_size = 16; - sendbuf_used = sendbuf_size; - sendbuf = new uchar[sendbuf_size]; - memcpy(sendbuf, "\0**PACKETMODE**\r", sendbuf_size); - } else if(PacketMode == packetModeUCS) { - safe_delete_array(sendbuf); - sendbuf_size = 19; - sendbuf_used = sendbuf_size; - sendbuf = new uchar[sendbuf_size]; - memcpy(sendbuf, "\0**PACKETMODEUCS**\r", sendbuf_size); - } - else if(PacketMode == packetModeQueryServ) { - safe_delete_array(sendbuf); - sendbuf_size = 18; - sendbuf_used = sendbuf_size; - sendbuf = new uchar[sendbuf_size]; - memcpy(sendbuf, "\0**PACKETMODEQS**\r", sendbuf_size); - } - else { - //default: packetModeZone - safe_delete_array(sendbuf); - sendbuf_size = 20; - sendbuf_used = sendbuf_size; - sendbuf = new uchar[sendbuf_size]; - memcpy(sendbuf, "\0**PACKETMODEZONE**\r", sendbuf_size); - } - } - #endif - MSendQueue.unlock(); - - return(true); -} - -void EmuTCPConnection::ClearBuffers() { - TCPConnection::ClearBuffers(); - - LockMutex lock2(&MOutQueueLock); - ServerPacket* pack = 0; - while ((pack = OutQueue.pop())) - safe_delete(pack); - - EmuTCPNetPacket_Struct* tnps = 0; - while ((tnps = InModeQueue.pop())) - safe_delete(tnps); - - keepalive_timer.Start(); - timeout_timer.Start(); -} - -void EmuTCPConnection::SendNetErrorPacket(const char* reason) { - #if TCPC_DEBUG >= 1 - struct in_addr in; - in.s_addr = GetrIP(); - std::cout "NetError: '"; - if (reason) - std::cout << reason; - std::cout << "': " << inet_ntoa(in) << ":" << GetPort() << std::endl; - #endif - auto pack = new ServerPacket(0); - pack->size = 1; - if (reason) - pack->size += strlen(reason) + 1; - pack->pBuffer = new uchar[pack->size]; - memset(pack->pBuffer, 0, pack->size); - pack->pBuffer[0] = 255; - strcpy((char *)&pack->pBuffer[1], reason); - SendPacket(pack); - safe_delete(pack); -} - -void EmuTCPConnection::RemoveRelay(EmuTCPConnection* relay, bool iSendRelayDisconnect) { - if (iSendRelayDisconnect) { - auto pack = new ServerPacket(0, 5); - pack->pBuffer[0] = 3; - *((uint32*) &pack->pBuffer[1]) = relay->GetRemoteID(); - SendPacket(pack); - safe_delete(pack); - } - RelayCount--; -} - - - -bool EmuTCPConnection::ProcessReceivedData(char* errbuf) { - if (errbuf) - errbuf[0] = 0; - timeout_timer.Start(); - if (!recvbuf) - return true; - if (TCPMode == modePacket) { - if (pOldFormat) - return ProcessReceivedDataAsOldPackets(errbuf); - else - return ProcessReceivedDataAsPackets(errbuf); - } - //else, use the base class's text processing. - bool ret = TCPConnection::ProcessReceivedData(errbuf); - //see if we made the transition to packet mode... - if(ret && TCPMode == modePacket) { - return ProcessReceivedDataAsPackets(errbuf); - } - return(ret); -} - - - -bool EmuTCPConnection::ProcessReceivedDataAsPackets(char* errbuf) { - if (errbuf) - errbuf[0] = 0; - int32 base = 0; - int32 size = 7; - uchar* buffer; - ServerPacket* pack = 0; - while ((recvbuf_used - base) >= size) { - EmuTCPNetPacket_Struct* tnps = (EmuTCPNetPacket_Struct*) &recvbuf[base]; - buffer = tnps->buffer; - size = tnps->size; - if (size >= MaxTCPReceiveBuffferSize) { -#if TCPN_DEBUG_Memory >= 1 - std::cout << "TCPConnection[" << GetID() << "]::ProcessReceivedDataAsPackets(): size[" << size << "] >= MaxTCPReceiveBuffferSize" << std::endl; - DumpPacket(&recvbuf[base], 16); -#endif - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "EmuTCPConnection::ProcessReceivedDataAsPackets(): size >= MaxTCPReceiveBuffferSize"); - return false; - } - if ((recvbuf_used - base) >= size) { - // ok, we got enough data to make this packet! - pack = new ServerPacket; - pack->size = size - sizeof(EmuTCPNetPacket_Struct); - // read headers - pack->opcode = tnps->opcode; - if (tnps->flags.compressed) { - pack->compressed = true; - pack->InflatedSize = *((int32*)buffer); - pack->size -= 4; - buffer += 4; - } - if (tnps->flags.destination) { - pack->destination = *((int32*)buffer); - pack->size -= 4; - buffer += 4; - } - // end read headers - if (pack->size > 0) { - if (tnps->flags.compressed) { - // Lets decompress the packet here - pack->compressed = false; - pack->pBuffer = new uchar[pack->InflatedSize]; - pack->size = InflatePacket(buffer, pack->size, pack->pBuffer, pack->InflatedSize); - } - else { - pack->pBuffer = new uchar[pack->size]; - memcpy(pack->pBuffer, buffer, pack->size); - } - } - if (pack->opcode == 0) { - if (pack->size) { - #if TCPN_DEBUG >= 2 - std::cout << "Received TCP Network layer packet" << std::endl; - #endif - ProcessNetworkLayerPacket(pack); - } - #if TCPN_DEBUG >= 5 - else { - std::cout << "Received TCP keepalive packet. (opcode=0)" << std::endl; - } - #endif - // keepalive, no need to process - safe_delete(pack); - } - else { - #if TCPN_LOG_PACKETS >= 1 - if (pack && pack->opcode != 0) { - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Logging incoming TCP packet. OPCode: 0x" << std::hex << std::setw(4) << std::setfill('0') << pack->opcode << std::dec << ", size: " << std::setw(5) << std::setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; - #if TCPN_LOG_PACKETS == 2 - if (pack->size >= 32) - DumpPacket(pack->pBuffer, 32); - else - DumpPacket(pack); - #endif - #if TCPN_LOG_PACKETS >= 3 - DumpPacket(pack); - #endif - } - #endif - if (RelayServer && Server && pack->destination) { - EmuTCPConnection* con = Server->FindConnection(pack->destination); - if (!con) { - #if TCPN_DEBUG >= 1 - std::cout << "Error relaying packet: con = 0" << std::endl; - #endif - safe_delete(pack); - } - else - con->OutQueuePush(pack); - } - else - OutQueuePush(pack); - } - base += size; - size = 7; - } - } - if (base != 0) { - if (base >= recvbuf_used) { - safe_delete_array(recvbuf); - } else { - auto tmpbuf = new uchar[recvbuf_size - base]; - memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base); - safe_delete_array(recvbuf); - recvbuf = tmpbuf; - recvbuf_used -= base; - recvbuf_size -= base; - } - } - return true; -} - -bool EmuTCPConnection::ProcessReceivedDataAsOldPackets(char* errbuf) { - int32 base = 0; - int32 size = 4; - uchar* buffer; - ServerPacket* pack = 0; - while ((recvbuf_used - base) >= size) { - buffer = &recvbuf[base]; - memcpy(&size, &buffer[2], 2); - if (size >= MaxTCPReceiveBuffferSize) { -#if TCPN_DEBUG_Memory >= 1 - std::cout << "TCPConnection[" << GetID() << "]::ProcessReceivedDataAsPackets(): size[" << size << "] >= MaxTCPReceiveBuffferSize" << std::endl; -#endif - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "EmuTCPConnection::ProcessReceivedDataAsPackets(): size >= MaxTCPReceiveBuffferSize"); - return false; - } - if ((recvbuf_used - base) >= size) { - // ok, we got enough data to make this packet! - pack = new ServerPacket; - memcpy(&pack->opcode, &buffer[0], 2); - pack->size = size - 4; -/* if () { // TODO: Checksum or size check or something similar - // Datastream corruption, get the hell outta here! - delete pack; - return false; - }*/ - if (pack->size > 0) { - pack->pBuffer = new uchar[pack->size]; - memcpy(pack->pBuffer, &buffer[4], pack->size); - } - if (pack->opcode == 0) { - // keepalive, no need to process - safe_delete(pack); - } - else { - #if TCPN_LOG_PACKETS >= 1 - if (pack && pack->opcode != 0) { - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Logging incoming TCP OldPacket. OPCode: 0x" << std::hex << std::setw(4) << std::setfill('0') << pack->opcode << std::dec << ", size: " << std::setw(5) << std::setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; - #if TCPN_LOG_PACKETS == 2 - if (pack->size >= 32) - DumpPacket(pack->pBuffer, 32); - else - DumpPacket(pack); - #endif - #if TCPN_LOG_PACKETS >= 3 - DumpPacket(pack); - #endif - } - #endif - OutQueuePush(pack); - } - base += size; - size = 4; - } - } - if (base != 0) { - if (base >= recvbuf_used) { - safe_delete_array(recvbuf); - } - else { - auto tmpbuf = new uchar[recvbuf_size - base]; - memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base); - safe_delete_array(recvbuf); - recvbuf = tmpbuf; - recvbuf_used -= base; - recvbuf_size -= base; - } - } - return true; -} - -void EmuTCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) { - uint8 opcode = pack->pBuffer[0]; - uint8* data = &pack->pBuffer[1]; - switch (opcode) { - case 0: { - break; - } - case 1: { // Switch to RelayServer mode - if (pack->size != 1) { - SendNetErrorPacket("New RelayClient: wrong size, expected 1"); - break; - } - if (RelayServer) { - SendNetErrorPacket("Switch to RelayServer mode when already in RelayServer mode"); - break; - } - if (RemoteID) { - SendNetErrorPacket("Switch to RelayServer mode by a Relay Client"); - break; - } - if (ConnectionType != Incoming) { - SendNetErrorPacket("Switch to RelayServer mode on outgoing connection"); - break; - } - #if TCPC_DEBUG >= 3 - struct in_addr in; - in.s_addr = GetrIP(); - std::cout << "Switching to RelayServer mode: " << inet_ntoa(in) << ":" << GetPort() << std::endl; - #endif - RelayServer = true; - break; - } - case 2: { // New Relay Client - if (!RelayServer) { - SendNetErrorPacket("New RelayClient when not in RelayServer mode"); - break; - } - if (pack->size != 11) { - SendNetErrorPacket("New RelayClient: wrong size, expected 11"); - break; - } - if (ConnectionType != Incoming) { - SendNetErrorPacket("New RelayClient: illegal on outgoing connection"); - break; - } - auto con = new EmuTCPConnection(Server->GetNextID(), Server, this, *((uint32 *)data), - *((uint32 *)&data[4]), *((uint16 *)&data[8])); - Server->AddConnection(con); - RelayCount++; - break; - } - case 3: { // Delete Relay Client - if (!RelayServer) { - SendNetErrorPacket("Delete RelayClient when not in RelayServer mode"); - break; - } - if (pack->size != 5) { - SendNetErrorPacket("Delete RelayClient: wrong size, expected 5"); - break; - } - EmuTCPConnection* con = Server->FindConnection(*((uint32*)data)); - if (con) { - if (ConnectionType == Incoming) { - if (con->GetRelayLink() != this) { - SendNetErrorPacket("Delete RelayClient: RelayLink != this"); - break; - } - } - con->Disconnect(false); - } - break; - } - case 255: { - #if TCPC_DEBUG >= 1 - struct in_addr in; - in.s_addr = GetrIP(); - std::cout "Received NetError: '"; - if (pack->size > 1) - std::cout << (char*) data; - std::cout << "': " << inet_ntoa(in) << ":" << GetPort() << std::endl; - #endif - break; - } - } -} - -bool EmuTCPConnection::SendData(bool &sent_something, char* errbuf) { - sent_something = false; - if(!TCPConnection::SendData(sent_something, errbuf)) - return(false); - - if(sent_something) - keepalive_timer.Start(); - else if (TCPMode == modePacket && keepalive_timer.Check()) { - auto pack = new ServerPacket(0, 0); - SendPacket(pack); - safe_delete(pack); - #if TCPN_DEBUG >= 5 - std::cout << "Sending TCP keepalive packet. (timeout=" << timeout_timer.GetRemainingTime() << " remaining)" << std::endl; - #endif - } - - return(true); -} - -bool EmuTCPConnection::RecvData(char* errbuf) { - if(!TCPConnection::RecvData(errbuf)) { - if (OutQueue.count()) - return(true); - else - return(false); - } - - if ((TCPMode == modePacket || TCPMode == modeTransition) && timeout_timer.Check()) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Connection timeout"); - return false; - } - - return(true); -} - diff --git a/common/emu_tcp_connection.h b/common/emu_tcp_connection.h deleted file mode 100644 index 7f4d0710b..000000000 --- a/common/emu_tcp_connection.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef EmuTCPCONNECTION_H_ -#define EmuTCPCONNECTION_H_ - -#include "tcp_connection.h" -#include "timer.h" - -//moved out of TCPConnection:: to be more exportable -#pragma pack(1) - struct EmuTCPNetPacket_Struct { - uint32 size; - struct { - uint8 - compressed : 1, - destination : 1, - flag3 : 1, - flag4 : 1, - flag5 : 1, - flag6 : 1, - flag7 : 1, - flag8 : 1; - } flags; - uint16 opcode; - uchar buffer[0]; - }; -#pragma pack() - -struct SPackSendQueue; -class EmuTCPServer; -class ServerPacket; - -class EmuTCPConnection : public TCPConnection { -public: - enum eTCPMode { modeConsole, modeTransition, modePacket }; - enum ePacketMode { packetModeZone, packetModeLauncher, packetModeLogin, packetModeUCS, packetModeQueryServ }; - - EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, SOCKET iSock, uint32 irIP, uint16 irPort, bool iOldFormat = false); - EmuTCPConnection(bool iOldFormat = false, EmuTCPServer* iRelayServer = 0, eTCPMode iMode = modePacket); // for outgoing connections - EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, EmuTCPConnection* iRelayLink, uint32 iRemoteID, uint32 irIP, uint16 irPort); // for relay connections - virtual ~EmuTCPConnection(); - - virtual bool ConnectIP(uint32 irIP, uint16 irPort, char* errbuf = 0); - virtual void Disconnect(bool iSendRelayDisconnect = true); - - static EmuTCPNetPacket_Struct* MakePacket(ServerPacket* pack, uint32 iDestination = 0); - static SPackSendQueue* MakeOldPacket(ServerPacket* pack); - - virtual bool SendPacket(ServerPacket* pack, uint32 iDestination = 0); - virtual bool SendPacket(EmuTCPNetPacket_Struct* tnps); - ServerPacket* PopPacket(); // OutQueuePop() - void SetPacketMode(ePacketMode mode) { PacketMode = mode; } - - eTCPMode GetMode() const { return TCPMode; } - ePacketMode GetPacketMode() const { return(PacketMode); } - - //relay crap: - inline bool IsRelayServer() const { return RelayServer; } - inline TCPConnection* GetRelayLink() const { return RelayLink; } - inline uint32 GetRemoteID() const { return RemoteID; } - -protected: - void OutQueuePush(ServerPacket* pack); - void RemoveRelay(EmuTCPConnection* relay, bool iSendRelayDisconnect); - - void SendNetErrorPacket(const char* reason = 0); - - virtual bool SendData(bool &sent_something, char* errbuf = 0); - virtual bool RecvData(char* errbuf = 0); - - virtual bool ProcessReceivedData(char* errbuf = 0); - bool ProcessReceivedDataAsPackets(char* errbuf = 0); - bool ProcessReceivedDataAsOldPackets(char* errbuf = 0); - void ProcessNetworkLayerPacket(ServerPacket* pack); - - virtual bool LineOutQueuePush(char* line); - virtual void ClearBuffers(); - - EmuTCPServer* Server; - - eTCPMode TCPMode; - ePacketMode PacketMode; - bool pOldFormat; - - Timer keepalive_timer; - Timer timeout_timer; - - //relay crap: - EmuTCPConnection* RelayLink; - int32 RelayCount; - bool RelayServer; - uint32 RemoteID; - - //input queue... - void InModeQueuePush(EmuTCPNetPacket_Struct* tnps); - MyQueue InModeQueue; - - //output queue... - MyQueue OutQueue; - Mutex MOutQueueLock; -}; - -#endif /*EmuTCPCONNECTION_H_*/ - - - diff --git a/common/emu_tcp_server.cpp b/common/emu_tcp_server.cpp deleted file mode 100644 index 00a241859..000000000 --- a/common/emu_tcp_server.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "global_define.h" -#include "emu_tcp_server.h" -#include "emu_tcp_connection.h" - -EmuTCPServer::EmuTCPServer(uint16 iPort, bool iOldFormat) -: TCPServer(iPort), - pOldFormat(iOldFormat) -{ -} - -EmuTCPServer::~EmuTCPServer() { - MInQueue.lock(); - while(!m_InQueue.empty()) { - delete m_InQueue.front(); - m_InQueue.pop(); - } - MInQueue.unlock(); -} - -void EmuTCPServer::Process() { - CheckInQueue(); - TCPServer::Process(); -} - -void EmuTCPServer::CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -{ - auto conn = new EmuTCPConnection(ID, this, in_socket, irIP, irPort, pOldFormat); - AddConnection(conn); -} - - -void EmuTCPServer::SendPacket(ServerPacket* pack) { - EmuTCPNetPacket_Struct* tnps = EmuTCPConnection::MakePacket(pack); - SendPacket(&tnps); -} - -void EmuTCPServer::SendPacket(EmuTCPNetPacket_Struct** tnps) { - MInQueue.lock(); - m_InQueue.push(*tnps); - MInQueue.unlock(); - tnps = nullptr; -} - -void EmuTCPServer::CheckInQueue() { - EmuTCPNetPacket_Struct* tnps = 0; - - while (( tnps = InQueuePop() )) { - vitr cur, end; - cur = m_list.begin(); - end = m_list.end(); - for(; cur != end; cur++) { - if ((*cur)->GetMode() != EmuTCPConnection::modeConsole && (*cur)->GetRemoteID() == 0) - (*cur)->SendPacket(tnps); - } - safe_delete(tnps); - } -} - -EmuTCPNetPacket_Struct* EmuTCPServer::InQueuePop() { - EmuTCPNetPacket_Struct* ret = nullptr; - MInQueue.lock(); - if(!m_InQueue.empty()) { - ret = m_InQueue.front(); - m_InQueue.pop(); - } - MInQueue.unlock(); - return ret; -} - - -EmuTCPConnection *EmuTCPServer::FindConnection(uint32 iID) { - vitr cur, end; - cur = m_list.begin(); - end = m_list.end(); - for(; cur != end; cur++) { - if ((*cur)->GetID() == iID) - return *cur; - } - return(nullptr); -} - diff --git a/common/emu_tcp_server.h b/common/emu_tcp_server.h deleted file mode 100644 index 8941812ad..000000000 --- a/common/emu_tcp_server.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef EmuTCPSERVER_H_ -#define EmuTCPSERVER_H_ - -#include "tcp_server.h" - -class EmuTCPConnection; -struct EmuTCPNetPacket_Struct; -class ServerPacket; - -class EmuTCPServer : public TCPServer { -public: - EmuTCPServer(uint16 iPort = 0, bool iOldFormat = false); - virtual ~EmuTCPServer(); - - //packet broadcast routines. - void SendPacket(ServerPacket* pack); - void SendPacket(EmuTCPNetPacket_Struct** tnps); - - //special crap for relay management - EmuTCPConnection *FindConnection(uint32 iID); - - //exposed for some crap we pull. Do not call from outside this object. - using TCPServer::AddConnection; - -protected: - virtual void Process(); - - virtual void CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort); - - bool pOldFormat; - - //broadcast packet queue.. - void CheckInQueue(); - Mutex MInQueue; - EmuTCPNetPacket_Struct* InQueuePop(); //returns ownership - std::queue m_InQueue; -}; -#endif /*EmuTCPSERVER_H_*/ diff --git a/common/net/servertalk_server_connection.cpp b/common/net/servertalk_server_connection.cpp index eb3e17247..4931c7143 100644 --- a/common/net/servertalk_server_connection.cpp +++ b/common/net/servertalk_server_connection.cpp @@ -32,7 +32,6 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet out.PutUInt16(4, opcode); std::unique_ptr cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]); - crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key); (*(uint64_t*)&m_nonce_ours[0])++; out.PutData(6, &cipher[0], p.Length() + crypto_secretbox_MACBYTES); @@ -218,6 +217,7 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b size_t cipher_len = p.Length() - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES; size_t message_len = cipher_len - crypto_secretbox_MACBYTES; std::unique_ptr decrypted_text(new unsigned char[message_len]); + if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)p.Data() + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, cipher_len, m_nonce_theirs, m_shared_key)) { Log.OutF(Logs::General, Logs::Error, "Error decrypting handshake from client, dropping connection."); @@ -235,7 +235,6 @@ void EQ::Net::ServertalkServerConnection::ProcessHandshake(EQ::Net::Packet &p, b } m_parent->ConnectionIdentified(this); - (*(uint64_t*)&m_nonce_theirs[0])++; } } @@ -293,6 +292,7 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p) if (m_encrypted) { size_t message_len = length - crypto_secretbox_MACBYTES; std::unique_ptr decrypted_text(new unsigned char[message_len]); + if (crypto_box_open_easy_afternm(&decrypted_text[0], (unsigned char*)&data[0], length, m_nonce_theirs, m_shared_key)) { Log.OutF(Logs::General, Logs::Error, "Error decrypting message from client"); diff --git a/common/servertalk.h b/common/servertalk.h index ea4ba0d4c..f92a0a982 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -62,7 +62,7 @@ #define ServerOP_ItemStatus 0x002C #define ServerOP_OOCMute 0x002D #define ServerOP_Revoke 0x002E -//#define 0x002F +#define ServerOP_WebInterfaceCall 0x002F #define ServerOP_GroupIDReq 0x0030 #define ServerOP_GroupIDReply 0x0031 #define ServerOP_GroupLeave 0x0032 // for disbanding out of zone folks @@ -227,7 +227,7 @@ public: ServerPacket(uint16 in_opcode, const EQ::Net::Packet &p) { this->compressed = false; - size = p.Length(); + size = (uint32)p.Length(); opcode = in_opcode; if (size == 0) { pBuffer = 0; diff --git a/common/tcp_basic_server.h b/common/tcp_basic_server.h deleted file mode 100644 index 1d317bc8f..000000000 --- a/common/tcp_basic_server.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef TCPBASICSERVER_H_ -#define TCPBASICSERVER_H_ - -#include "tcp_server.h" -#include "tcp_connection.h" - -class TCPBasicServer : public TCPServer { -public: - inline TCPBasicServer(uint16 iPort = 0) : TCPServer(iPort) { } - inline virtual void CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) { - TCPConnection *conn = new TCPConnection(ID, in_socket, irIP, irPort); - AddConnection(conn); - } -}; - -#endif /*TCPBASICSERVER_H_*/ - diff --git a/common/tcp_connection.cpp b/common/tcp_connection.cpp deleted file mode 100644 index d13cf89cc..000000000 --- a/common/tcp_connection.cpp +++ /dev/null @@ -1,942 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - 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 -*/ - -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" - -#include -#include -#include - -#include "tcp_connection.h" - -#ifdef FREEBSD //Timothy Whitman - January 7, 2003 - #define MSG_NOSIGNAL 0 -#endif -#ifdef DARWIN - #define MSG_NOSIGNAL SO_NOSIGPIPE // Corysia Taware - Sept. 27, 2013 - // See http://lists.apple.com/archives/macnetworkprog/2002/Dec/msg00091.html -#endif // DARWIN - -#ifdef _WINDOWS -InitWinsock winsock; -#endif - -#define LOOP_GRANULARITY 3 //# of ms between checking our socket/queues - -#define TCPN_DEBUG 0 -#define TCPN_DEBUG_Console 0 -#define TCPN_DEBUG_Memory 0 -#define TCPN_LOG_RAW_DATA_OUT 0 //1 = info, 2 = length limited dump, 3 = full dump -#define TCPN_LOG_RAW_DATA_IN 0 //1 = info, 2 = length limited dump, 3 = full dump - -//client version -TCPConnection::TCPConnection() -: ConnectionType(Outgoing), - connection_socket(0), - id(0), - rIP(0), - rPort(0) -{ - pState = TCPS_Ready; - pFree = false; - pEcho = false; - recvbuf = nullptr; - sendbuf = nullptr; - pRunLoop = false; - charAsyncConnect = 0; - pAsyncConnect = false; - m_previousLineEnd = false; -#if TCPN_DEBUG_Memory >= 7 - std::cout << "Constructor #2 on outgoing TCP# " << GetID() << std::endl; -#endif -} - -//server version -TCPConnection::TCPConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -: ConnectionType(Incoming), - connection_socket(in_socket), - id(ID), - rIP(irIP), - rPort(irPort) -{ - pState = TCPS_Connected; - pFree = false; - pEcho = false; - recvbuf = nullptr; - sendbuf = nullptr; - pRunLoop = false; - charAsyncConnect = 0; - pAsyncConnect = false; - m_previousLineEnd = false; -#if TCPN_DEBUG_Memory >= 7 - std::cout << "Constructor #2 on incoming TCP# " << GetID() << std::endl; -#endif -} - -TCPConnection::~TCPConnection() { - FinishDisconnect(); - ClearBuffers(); - if (ConnectionType == Outgoing) { - MRunLoop.lock(); - pRunLoop = false; - MRunLoop.unlock(); - MLoopRunning.lock(); - MLoopRunning.unlock(); -#if TCPN_DEBUG_Memory >= 6 - std::cout << "Deconstructor on outgoing TCP# " << GetID() << std::endl; -#endif - } -#if TCPN_DEBUG_Memory >= 5 - else { - std::cout << "Deconstructor on incoming TCP# " << GetID() << std::endl; - } -#endif - safe_delete_array(recvbuf); - safe_delete_array(sendbuf); - safe_delete_array(charAsyncConnect); -} - -void TCPConnection::SetState(State_t in_state) { - MState.lock(); - pState = in_state; - MState.unlock(); -} - -TCPConnection::State_t TCPConnection::GetState() const { - State_t ret; - MState.lock(); - ret = pState; - MState.unlock(); - return ret; -} - -bool TCPConnection::GetSockName(char *host, uint16 *port) -{ - bool result=false; - LockMutex lock(&MState); - if (!Connected()) - return false; - - struct sockaddr_in local; - -#ifdef _WINDOWS - int addrlen; -#else -#ifdef FREEBSD - socklen_t addrlen; -#else - size_t addrlen; -#endif -#endif - addrlen=sizeof(struct sockaddr_in); -#ifdef _WINDOWS - if (!getsockname(connection_socket,(struct sockaddr *)&local,&addrlen)) { -#else - if (!getsockname(connection_socket,(struct sockaddr *)&local,(socklen_t *)&addrlen)) { -#endif - unsigned long ip=local.sin_addr.s_addr; - sprintf(host,"%d.%d.%d.%d", - *(unsigned char *)&ip, - *((unsigned char *)&ip+1), - *((unsigned char *)&ip+2), - *((unsigned char *)&ip+3)); - *port=ntohs(local.sin_port); - - result=true; - } - - return result; -} - -void TCPConnection::Free() { - Disconnect(); - pFree = true; -} - -bool TCPConnection::Send(const uchar* data, int32 size) { - if (!Connected()) - return false; - if (!size) - return true; - ServerSendQueuePushEnd(data, size); - return true; -} - -void TCPConnection::ServerSendQueuePushEnd(const uchar* data, int32 size) { - MSendQueue.lock(); - if (sendbuf == nullptr) { - sendbuf = new uchar[size]; - sendbuf_size = size; - sendbuf_used = 0; - } - else if (size > (sendbuf_size - sendbuf_used)) { - sendbuf_size += size + 1024; - auto tmp = new uchar[sendbuf_size]; - memcpy(tmp, sendbuf, sendbuf_used); - safe_delete_array(sendbuf); - sendbuf = tmp; - } - memcpy(&sendbuf[sendbuf_used], data, size); - sendbuf_used += size; - MSendQueue.unlock(); -} - -void TCPConnection::ServerSendQueuePushEnd(uchar** data, int32 size) { - MSendQueue.lock(); - if (sendbuf == 0) { - sendbuf = *data; - sendbuf_size = size; - sendbuf_used = size; - MSendQueue.unlock(); - *data = 0; - return; - } - if (size > (sendbuf_size - sendbuf_used)) { - sendbuf_size += size; - auto tmp = new uchar[sendbuf_size]; - memcpy(tmp, sendbuf, sendbuf_used); - safe_delete_array(sendbuf); - sendbuf = tmp; - } - memcpy(&sendbuf[sendbuf_used], *data, size); - sendbuf_used += size; - MSendQueue.unlock(); - safe_delete_array(*data); -} - -void TCPConnection::ServerSendQueuePushFront(uchar* data, int32 size) { - MSendQueue.lock(); - if (sendbuf == 0) { - sendbuf = new uchar[size]; - sendbuf_size = size; - sendbuf_used = 0; - } - else if (size > (sendbuf_size - sendbuf_used)) { - sendbuf_size += size; - auto tmp = new uchar[sendbuf_size]; - memcpy(&tmp[size], sendbuf, sendbuf_used); - safe_delete_array(sendbuf); - sendbuf = tmp; - } - memcpy(sendbuf, data, size); - sendbuf_used += size; - MSendQueue.unlock(); -} - -bool TCPConnection::ServerSendQueuePop(uchar** data, int32* size) { - bool ret; - if (!MSendQueue.trylock()) - return false; - if (sendbuf) { - *data = sendbuf; - *size = sendbuf_used; - sendbuf = 0; - ret = true; - } - else { - ret = false; - } - MSendQueue.unlock(); - return ret; -} - -bool TCPConnection::ServerSendQueuePopForce(uchar** data, int32* size) { - bool ret; - MSendQueue.lock(); - if (sendbuf) { - *data = sendbuf; - *size = sendbuf_used; - sendbuf = 0; - ret = true; - } - else { - ret = false; - } - MSendQueue.unlock(); - return ret; -} - -char* TCPConnection::PopLine() { - char* ret; - if (!MLineOutQueue.trylock()) - return 0; - ret = (char*) LineOutQueue.pop(); - MLineOutQueue.unlock(); - return ret; -} - -bool TCPConnection::LineOutQueuePush(char* line) { - MLineOutQueue.lock(); - LineOutQueue.push(line); - MLineOutQueue.unlock(); - return(false); -} - - -void TCPConnection::FinishDisconnect() { - MState.lock(); - if (connection_socket != INVALID_SOCKET && connection_socket != 0) { - if (pState == TCPS_Connected || pState == TCPS_Disconnecting || pState == TCPS_Disconnected) { - bool sent_something = false; - SendData(sent_something); - } - pState = TCPS_Closing; - shutdown(connection_socket, 0x01); - shutdown(connection_socket, 0x00); -#ifdef _WINDOWS - closesocket(connection_socket); -#else - close(connection_socket); -#endif - connection_socket = 0; - rIP = 0; - rPort = 0; - ClearBuffers(); - } - pState = TCPS_Disconnected; - MState.unlock(); -} - -void TCPConnection::Disconnect() { - MState.lock(); - if(pState == TCPS_Connected || pState == TCPS_Connecting) { - pState = TCPS_Disconnecting; - } - MState.unlock(); -} - -bool TCPConnection::GetAsyncConnect() { - bool ret; - MAsyncConnect.lock(); - ret = pAsyncConnect; - MAsyncConnect.unlock(); - return ret; -} - -bool TCPConnection::SetAsyncConnect(bool iValue) { - bool ret; - MAsyncConnect.lock(); - ret = pAsyncConnect; - pAsyncConnect = iValue; - MAsyncConnect.unlock(); - return ret; -} - -bool TCPConnection::ConnectReady() const { - State_t s = GetState(); - if (s != TCPS_Ready && s != TCPS_Disconnected) - return(false); - return(ConnectionType == Outgoing); -} - -void TCPConnection::AsyncConnect(const char* irAddress, uint16 irPort) { - safe_delete_array(charAsyncConnect); - charAsyncConnect = new char[strlen(irAddress) + 1]; - strcpy(charAsyncConnect, irAddress); - AsyncConnect((uint32) 0, irPort); -} - -void TCPConnection::AsyncConnect(uint32 irIP, uint16 irPort) { - if (ConnectionType != Outgoing) { - // If this code runs, we got serious problems - // Crash and burn. - return; - } - if(!ConnectReady()) { -#if TCPN_DEBUG > 0 - printf("Trying to do async connect in invalid state %s\n", GetState()); -#endif - return; - } - MAsyncConnect.lock(); - if (pAsyncConnect) { - MAsyncConnect.unlock(); -#if TCPN_DEBUG > 0 - printf("Trying to do async connect when already doing one.\n"); -#endif - return; - } -#if TCPN_DEBUG > 0 - printf("Start async connect.\n"); -#endif - pAsyncConnect = true; - if(irIP != 0) - safe_delete_array(charAsyncConnect); - rIP = irIP; - rPort = irPort; - MAsyncConnect.unlock(); - if (!pRunLoop) { - pRunLoop = true; -#ifdef _WINDOWS - _beginthread(TCPConnectionLoop, 0, this); -#else - pthread_t thread; - pthread_create(&thread, nullptr, TCPConnectionLoop, this); -#endif - } - return; -} - -bool TCPConnection::Connect(const char* irAddress, uint16 irPort, char* errbuf) { - if (errbuf) - errbuf[0] = 0; - uint32 tmpIP = ResolveIP(irAddress); - if (!tmpIP) { - if (errbuf) { -#ifdef _WINDOWS - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Couldnt resolve hostname. Error: %i", WSAGetLastError()); -#else - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Couldnt resolve hostname. Error #%i: %s", errno, strerror(errno)); -#endif - } - return false; - } - return ConnectIP(tmpIP, irPort, errbuf); -} - -bool TCPConnection::ConnectIP(uint32 in_ip, uint16 in_port, char* errbuf) { - if (errbuf) - errbuf[0] = 0; - if (ConnectionType != Outgoing) { - // If this code runs, we got serious problems - // Crash and burn. - return false; - } - MState.lock(); - if (ConnectReady()) { - pState = TCPS_Connecting; - } else { - MState.unlock(); - SetAsyncConnect(false); - return false; - } - MState.unlock(); - if (!pRunLoop) { - pRunLoop = true; -#ifdef _WINDOWS - _beginthread(TCPConnectionLoop, 0, this); -#else - pthread_t thread; - pthread_create(&thread, nullptr, TCPConnectionLoop, this); -#endif - } - - connection_socket = INVALID_SOCKET; - struct sockaddr_in server_sin; - //struct in_addr in; - - if ((connection_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET || connection_socket == 0) { -#ifdef _WINDOWS - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Allocating socket failed. Error: %i", WSAGetLastError()); -#else - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Allocating socket failed. Error: %s", strerror(errno)); -#endif - SetState(TCPS_Ready); - SetAsyncConnect(false); - return false; - } - server_sin.sin_family = AF_INET; - server_sin.sin_addr.s_addr = in_ip; - server_sin.sin_port = htons(in_port); - - // Establish a connection to the server socket. -#ifdef _WINDOWS - if (connect(connection_socket, (PSOCKADDR) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): connect() failed. Error: %i", WSAGetLastError()); - closesocket(connection_socket); - connection_socket = 0; - SetState(TCPS_Ready); - SetAsyncConnect(false); - return false; - } -#else - if (connect(connection_socket, (struct sockaddr *) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): connect() failed. Error: %s", strerror(errno)); - close(connection_socket); - connection_socket = 0; - SetState(TCPS_Ready); - SetAsyncConnect(false); - return false; - } -#endif - int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k - setsockopt(connection_socket, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize)); -#ifdef _WINDOWS - unsigned long nonblocking = 1; - ioctlsocket(connection_socket, FIONBIO, &nonblocking); -#else - fcntl(connection_socket, F_SETFL, O_NONBLOCK); -#endif - - SetEcho(false); - ClearBuffers(); - - rIP = in_ip; - rPort = in_port; - SetState(TCPS_Connected); - SetAsyncConnect(false); - return true; -} - -void TCPConnection::ClearBuffers() { - LockMutex lock1(&MSendQueue); - LockMutex lock3(&MRunLoop); - LockMutex lock4(&MState); - safe_delete_array(recvbuf); - safe_delete_array(sendbuf); - - char* line = 0; - while ((line = LineOutQueue.pop())) - safe_delete_array(line); -} - -bool TCPConnection::CheckNetActive() { - MState.lock(); - if (pState == TCPS_Connected || pState == TCPS_Disconnecting) { - MState.unlock(); - return true; - } - MState.unlock(); - return false; -} - -/* This is always called from an IO thread. Either the server socket's thread, or a - * special thread we create when we make an outbound connection. */ -bool TCPConnection::Process() { - char errbuf[TCPConnection_ErrorBufferSize]; - switch(GetState()) { - case TCPS_Ready: - case TCPS_Connecting: - if (ConnectionType == Outgoing) { - if (GetAsyncConnect()) { - if (charAsyncConnect) - rIP = ResolveIP(charAsyncConnect); - ConnectIP(rIP, rPort); - } - } - return(true); - - case TCPS_Connected: - // only receive data in the connected state, no others... - if (!RecvData(errbuf)) { - struct in_addr in; - in.s_addr = GetrIP(); - return false; - } - /* we break to do the send */ - break; - - case TCPS_Disconnecting: { - //waiting for any sending data to go out... - MSendQueue.lock(); - if(sendbuf) { - if(sendbuf_used > 0) { - //something left to send, keep processing... - MSendQueue.unlock(); - break; - } - //else, send buffer is empty. - safe_delete_array(sendbuf); - } //else, no send buffer, we are done. - MSendQueue.unlock(); - } - /* Fallthrough */ - - case TCPS_Disconnected: - FinishDisconnect(); - MRunLoop.lock(); - pRunLoop = false; - MRunLoop.unlock(); -// SetState(TCPS_Ready); //reset the state in case they want to use it again... - return(false); - - case TCPS_Closing: - //I dont understand this state... - - case TCPS_Error: - MRunLoop.lock(); - pRunLoop = false; - MRunLoop.unlock(); - return(false); - } - - /* we get here in connected or disconnecting with more data to send */ - - bool sent_something = false; - if (!SendData(sent_something, errbuf)) { - struct in_addr in; - in.s_addr = GetrIP(); - std::cout << inet_ntoa(in) << ":" << GetrPort() << ": " << errbuf << std::endl; - return false; - } - - return true; -} - -bool TCPConnection::RecvData(char* errbuf) { - if (errbuf) - errbuf[0] = 0; - if (!Connected()) { - return false; - } - - int status = 0; - if (recvbuf == 0) { - recvbuf = new uchar[5120]; - recvbuf_size = 5120; - recvbuf_used = 0; - recvbuf_echo = 0; - } - else if ((recvbuf_size - recvbuf_used) < 2048) { - auto tmpbuf = new uchar[recvbuf_size + 5120]; - memcpy(tmpbuf, recvbuf, recvbuf_used); - recvbuf_size += 5120; - safe_delete_array(recvbuf); - recvbuf = tmpbuf; - if (recvbuf_size >= MaxTCPReceiveBuffferSize) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): recvbuf_size >= MaxTCPReceiveBuffferSize"); - return false; - } - } - - status = recv(connection_socket, (char *) &recvbuf[recvbuf_used], (recvbuf_size - recvbuf_used), 0); - - if (status >= 1) { -#if TCPN_LOG_RAW_DATA_IN >= 1 - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Read " << status << " bytes from network. (recvbuf_used = " << recvbuf_used << ") " << inet_ntoa(in) << ":" << GetrPort(); - std::cout << std::endl; - #if TCPN_LOG_RAW_DATA_IN == 2 - int32 tmp = status; - if (tmp > 32) - tmp = 32; - DumpPacket(&recvbuf[recvbuf_used], status); - #elif TCPN_LOG_RAW_DATA_IN >= 3 - DumpPacket(&recvbuf[recvbuf_used], status); - #endif -#endif - recvbuf_used += status; - if (!ProcessReceivedData(errbuf)) - return false; - } - else if (status == SOCKET_ERROR) { -#ifdef _WINDOWS - if (!(WSAGetLastError() == WSAEWOULDBLOCK)) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Error: %i", WSAGetLastError()); - return false; - } -#else - if (!(errno == EWOULDBLOCK)) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Error: %s", strerror(errno)); - return false; - } -#endif - } else if (status == 0) { - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Connection closed"); - return false; - } - - return true; -} - - -bool TCPConnection::GetEcho() { - bool ret; - ret = pEcho; - return ret; -} - -void TCPConnection::SetEcho(bool iValue) { - pEcho = iValue; -} - -bool TCPConnection::ProcessReceivedData(char* errbuf) { - if (errbuf) - errbuf[0] = 0; - if (!recvbuf) - return true; -#if TCPN_DEBUG_Console >= 4 - if (recvbuf_used) { - std::cout << "Starting Processing: recvbuf=" << recvbuf_used << std::endl; - DumpPacket(recvbuf, recvbuf_used); - } -#endif - for (int i=0; i < recvbuf_used; i++) { - if (GetEcho() && i >= recvbuf_echo) { - Send(&recvbuf[i], 1); - recvbuf_echo = i + 1; - } - switch(recvbuf[i]) { - case 0: { // 0 is the code for clear buffer - if (i==0) { - recvbuf_used--; - recvbuf_echo--; - memmove(recvbuf, &recvbuf[1], recvbuf_used); - i = -1; - } else { - if (i == recvbuf_used) { - safe_delete_array(recvbuf); - i = -1; - } - else { - uchar* tmpdel = recvbuf; - recvbuf = new uchar[recvbuf_size]; - memcpy(recvbuf, &tmpdel[i+1], recvbuf_used-i); - recvbuf_used -= i + 1; - recvbuf_echo -= i + 1; - safe_delete_array(tmpdel); - i = -1; - } - } -#if TCPN_DEBUG_Console >= 5 - std::cout << "Removed 0x00" << std::endl; - if (recvbuf_used) { - std::cout << "recvbuf left: " << recvbuf_used << std::endl; - DumpPacket(recvbuf, recvbuf_used); - } - else - std::cout << "recbuf left: None" << std::endl; -#endif - m_previousLineEnd = false; - break; - } - case 10: - case 13: // newline marker - { - char *line = nullptr; - if (i==0) { // empty line - if(!m_previousLineEnd) { - //char right before this was NOT a CR, report the empty line. - line = new char[1]; - line[0] = '\0'; - m_previousLineEnd = true; - } else { - m_previousLineEnd = false; - } - recvbuf_used--; - recvbuf_echo--; - memcpy(recvbuf, &recvbuf[1], recvbuf_used); - i = -1; - } else { - line = new char[i+1]; - memset(line, 0, i+1); - memcpy(line, recvbuf, i); -#if TCPN_DEBUG_Console >= 3 - std::cout << "Line Out: " << std::endl; - DumpPacket((uchar*) line, i); -#endif - //line[i] = 0; - uchar* tmpdel = recvbuf; - recvbuf = new uchar[recvbuf_size]; - recvbuf_used -= i+1; - recvbuf_echo -= i+1; - memcpy(recvbuf, &tmpdel[i+1], recvbuf_used); -#if TCPN_DEBUG_Console >= 5 - std::cout << "i+1=" << i+1 << std::endl; - if (recvbuf_used) { - std::cout << "recvbuf left: " << recvbuf_used << std::endl; - DumpPacket(recvbuf, recvbuf_used); - } - else - std::cout << "recbuf left: None" << std::endl; -#endif - safe_delete_array(tmpdel); - i = -1; - m_previousLineEnd = true; - } - - - if(line != nullptr) { - bool finish_proc = false; - finish_proc = LineOutQueuePush(line); - if(finish_proc) - return(true); //break early as requested by LineOutQueuePush - } - - break; - } - case 8: // backspace - { - if (i==0) { // nothin to backspace - recvbuf_used--; - recvbuf_echo--; - memmove(recvbuf, &recvbuf[1], recvbuf_used); - i = -1; - } else { - uchar* tmpdel = recvbuf; - recvbuf = new uchar[recvbuf_size]; - memcpy(recvbuf, tmpdel, i-1); - memcpy(&recvbuf[i-1], &tmpdel[i+1], recvbuf_used-i); - recvbuf_used -= 2; - recvbuf_echo -= 2; - safe_delete_array(tmpdel); - i -= 2; - } - break; - m_previousLineEnd = false; - } - default: - m_previousLineEnd = false; - } - } - if (recvbuf_used < 0) - safe_delete_array(recvbuf); - return true; -} - -bool TCPConnection::SendData(bool &sent_something, char* errbuf) { - if (errbuf) - errbuf[0] = 0; - /************ Get first send packet on queue and send it! ************/ - uchar* data = 0; - int32 size = 0; - int status = 0; - if (ServerSendQueuePop(&data, &size)) { -#ifdef _WINDOWS - status = send(connection_socket, (const char *) data, size, 0); -#else - status = send(connection_socket, data, size, MSG_NOSIGNAL); - if(errno==EPIPE) status = SOCKET_ERROR; -#endif - if (status >= 1) { -#if TCPN_LOG_RAW_DATA_OUT >= 1 - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Wrote " << status << " bytes to network. " << inet_ntoa(in) << ":" << GetrPort(); - std::cout << std::endl; - #if TCPN_LOG_RAW_DATA_OUT == 2 - int32 tmp = status; - if (tmp > 32) - tmp = 32; - DumpPacket(data, status); - #elif TCPN_LOG_RAW_DATA_OUT >= 3 - DumpPacket(data, status); - #endif -#endif - sent_something = true; - if (status < (signed)size) { -#if TCPN_LOG_RAW_DATA_OUT >= 1 - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Pushed " << (size - status) << " bytes back onto the send queue. " << inet_ntoa(in) << ":" << GetrPort(); - std::cout << std::endl; -#endif - // If there's network congestion, the number of bytes sent can be less than - // what we tried to give it... Push the extra back on the queue for later - ServerSendQueuePushFront(&data[status], size - status); - } - else if (status > (signed)size) { - return false; - } - // else if (status == size) {} - } - else { - ServerSendQueuePushFront(data, size); - } - - safe_delete_array(data); - if (status == SOCKET_ERROR) { -#ifdef _WINDOWS - if (WSAGetLastError() != WSAEWOULDBLOCK) -#else - if (errno != EWOULDBLOCK) -#endif - { - if (errbuf) { -#ifdef _WINDOWS - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %i", WSAGetLastError()); -#else - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %s", strerror(errno)); -#endif - } - - //if we get an error while disconnecting, just jump to disconnected - MState.lock(); - if(pState == TCPS_Disconnecting) - pState = TCPS_Disconnected; - MState.unlock(); - - return false; - } - } - } - return true; -} - -ThreadReturnType TCPConnection::TCPConnectionLoop(void* tmp) { -#ifdef _WINDOWS - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); -#endif - if (tmp == 0) { - THREAD_RETURN(nullptr); - } - TCPConnection* tcpc = (TCPConnection*) tmp; -#ifndef WIN32 - Log.Out(Logs::Detail, Logs::TCP_Connection, "%s Starting TCPConnectionLoop with thread ID %d", __FUNCTION__, pthread_self()); -#endif - tcpc->MLoopRunning.lock(); - while (tcpc->RunLoop()) { - Sleep(LOOP_GRANULARITY); - if (!tcpc->ConnectReady()) { - if (!tcpc->Process()) { - //the processing loop has detecting an error.. - //we want to drop the link immediately, so we clear buffers too. - tcpc->ClearBuffers(); - tcpc->Disconnect(); - } - Sleep(1); - } - else if (tcpc->GetAsyncConnect()) { - if (tcpc->charAsyncConnect) - tcpc->Connect(tcpc->charAsyncConnect, tcpc->GetrPort()); - else - tcpc->ConnectIP(tcpc->GetrIP(), tcpc->GetrPort()); - tcpc->SetAsyncConnect(false); - } - else - Sleep(10); //nothing to do. - } - tcpc->MLoopRunning.unlock(); - -#ifndef WIN32 - Log.Out(Logs::Detail, Logs::TCP_Connection, "%s Ending TCPConnectionLoop with thread ID %d", __FUNCTION__, pthread_self()); -#endif - - THREAD_RETURN(nullptr); -} - -bool TCPConnection::RunLoop() { - bool ret; - MRunLoop.lock(); - ret = pRunLoop; - MRunLoop.unlock(); - return ret; -} - diff --git a/common/tcp_connection.h b/common/tcp_connection.h deleted file mode 100644 index c3fa5cd51..000000000 --- a/common/tcp_connection.h +++ /dev/null @@ -1,176 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - 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 TCP_CONNECTION_H -#define TCP_CONNECTION_H -/* - Parent classes for interserver TCP Communication. - -Quagmire -*/ - -#ifdef _WINDOWS - #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) - #define snprintf _snprintf - #endif - #define strncasecmp _strnicmp - #define strcasecmp _stricmp - - #include -#else - #include - #include - #include - #include - #include - #include - #include - #include - #define INVALID_SOCKET -1 - #define SOCKET_ERROR -1 - #include "unix.h" - -#endif - -#include "types.h" -#include "mutex.h" -#include "queue.h" -#include "misc_functions.h" - - -#define TCPConnection_ErrorBufferSize 1024 -#define MaxTCPReceiveBuffferSize 524288 - - -#ifndef DEF_eConnectionType -#define DEF_eConnectionType -enum eConnectionType {Incoming, Outgoing}; -#endif - - -class TCPConnection { -protected: - typedef enum { - TCPS_Ready = 0, - TCPS_Connecting = 1, - TCPS_Connected = 100, - TCPS_Disconnecting = 200, //I do not know the difference between Disconnecting and Closing - TCPS_Disconnected = 201, - TCPS_Closing = 250, - TCPS_Error = 255 - } State_t; - -public: - //socket created by a server (incoming) - TCPConnection(uint32 ID, SOCKET iSock, uint32 irIP, uint16 irPort); - //socket created to connect to a server (outgoing) - TCPConnection(); // for outgoing connections - - virtual ~TCPConnection(); - - // Functions for outgoing connections - bool Connect(const char* irAddress, uint16 irPort, char* errbuf = 0); - virtual bool ConnectIP(uint32 irIP, uint16 irPort, char* errbuf = 0); - void AsyncConnect(const char* irAddress, uint16 irPort); - void AsyncConnect(uint32 irIP, uint16 irPort); - virtual void Disconnect(); - - bool Send(const uchar* data, int32 size); - - char* PopLine(); //returns ownership of allocated byte array - inline uint32 GetrIP() const { return rIP; } - inline uint16 GetrPort() const { return rPort; } - virtual State_t GetState() const; - inline bool Connected() const { return (GetState() == TCPS_Connected); } - bool ConnectReady() const; - void Free(); // Inform TCPServer that this connection object is no longer referanced - - inline uint32 GetID() const { return id; } - - bool GetEcho(); - void SetEcho(bool iValue); - bool GetSockName(char *host, uint16 *port); - - //should only be used by TCPServer: - bool CheckNetActive(); - inline bool IsFree() const { return pFree; } - virtual bool Process(); - -protected: - friend class BaseTCPServer; - void SetState(State_t iState); - - static ThreadReturnType TCPConnectionLoop(void* tmp); -// SOCKET sock; - bool RunLoop(); - Mutex MLoopRunning; - Mutex MAsyncConnect; - bool GetAsyncConnect(); - bool SetAsyncConnect(bool iValue); - char* charAsyncConnect; - bool pAsyncConnect; //this flag should really be turned into a state instead. - - virtual bool ProcessReceivedData(char* errbuf = 0); - virtual bool SendData(bool &sent_something, char* errbuf = 0); - virtual bool RecvData(char* errbuf = 0); - - virtual void ClearBuffers(); - - - bool m_previousLineEnd; - - eConnectionType ConnectionType; - Mutex MRunLoop; - bool pRunLoop; - - SOCKET connection_socket; - uint32 id; - uint32 rIP; - uint16 rPort; // host byte order - bool pFree; - - mutable Mutex MState; - State_t pState; - - //text based line out queue. - Mutex MLineOutQueue; - virtual bool LineOutQueuePush(char* line); //this is really kinda a hack for the transition to packet mode. Returns true to stop processing the output. - MyQueue LineOutQueue; - - uchar* recvbuf; - int32 recvbuf_size; - int32 recvbuf_used; - - int32 recvbuf_echo; - volatile bool pEcho; - - Mutex MSendQueue; - uchar* sendbuf; - int32 sendbuf_size; - int32 sendbuf_used; - bool ServerSendQueuePop(uchar** data, int32* size); - bool ServerSendQueuePopForce(uchar** data, int32* size); //does a lock() instead of a trylock() - void ServerSendQueuePushEnd(const uchar* data, int32 size); - void ServerSendQueuePushEnd(uchar** data, int32 size); - void ServerSendQueuePushFront(uchar* data, int32 size); - -private: - void FinishDisconnect(); -}; - - -#endif - diff --git a/common/tcp_server.cpp b/common/tcp_server.cpp deleted file mode 100644 index d632fb399..000000000 --- a/common/tcp_server.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include "global_define.h" -#include "tcp_server.h" -#include "../common/eqemu_logsys.h" - -#include -#include -#include - -#ifdef _WINDOWS - #include -#else - #include - #include - #include - #include - #include - -#define INVALID_SOCKET -1 - #define SOCKET_ERROR -1 -#endif - -#define SERVER_LOOP_GRANULARITY 3 //# of ms between checking our socket/queues - -BaseTCPServer::BaseTCPServer(uint16 in_port) { - NextID = 1; - pPort = in_port; - sock = 0; - pRunLoop = true; -#ifdef _WINDOWS - _beginthread(BaseTCPServer::TCPServerLoop, 0, this); -#else - pthread_t thread; - pthread_create(&thread, nullptr, &BaseTCPServer::TCPServerLoop, this); -#endif -} - -BaseTCPServer::~BaseTCPServer() { - StopLoopAndWait(); -} - -void BaseTCPServer::StopLoopAndWait() { - MRunLoop.lock(); - if(pRunLoop) { - pRunLoop = false; - MRunLoop.unlock(); - //wait for loop to stop. - MLoopRunning.lock(); - MLoopRunning.unlock(); - } else { - MRunLoop.unlock(); - } -} - -bool BaseTCPServer::RunLoop() { - bool ret; - MRunLoop.lock(); - ret = pRunLoop; - MRunLoop.unlock(); - return ret; -} - -ThreadReturnType BaseTCPServer::TCPServerLoop(void* tmp) { -#ifdef _WINDOWS - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); -#endif - if (tmp == 0) { - THREAD_RETURN(nullptr); - } - BaseTCPServer* tcps = (BaseTCPServer*) tmp; - -#ifndef WIN32 - Log.Out(Logs::Detail, Logs::None, "Starting TCPServerLoop with thread ID %d", pthread_self()); -#endif - - tcps->MLoopRunning.lock(); - while (tcps->RunLoop()) { - Sleep(SERVER_LOOP_GRANULARITY); - tcps->Process(); - } - tcps->MLoopRunning.unlock(); - -#ifndef WIN32 - Log.Out(Logs::Detail, Logs::None, "Ending TCPServerLoop with thread ID %d", pthread_self()); -#endif - - THREAD_RETURN(nullptr); -} - -void BaseTCPServer::Process() { - ListenNewConnections(); -} - -void BaseTCPServer::ListenNewConnections() { - SOCKET tmpsock; - struct sockaddr_in from; - struct in_addr in; - unsigned int fromlen; - unsigned short port; - - from.sin_family = AF_INET; - fromlen = sizeof(from); - LockMutex lock(&MSock); -#ifndef DARWIN // Corysia - On OSX, 0 is a valid fd. - if (!sock) - return; -#else - if (sock == -1) return; -#endif - - // Check for pending connects -#ifdef _WINDOWS - unsigned long nonblocking = 1; - while ((tmpsock = accept(sock, (struct sockaddr*) &from, (int *) &fromlen)) != INVALID_SOCKET) { - ioctlsocket (tmpsock, FIONBIO, &nonblocking); -#else -#ifdef __CYGWIN__ - while ((tmpsock = accept(sock, (struct sockaddr *) &from, (int *) &fromlen)) != INVALID_SOCKET) { -#else - while ((tmpsock = accept(sock, (struct sockaddr*) &from, &fromlen)) != INVALID_SOCKET) { -#endif - fcntl(tmpsock, F_SETFL, O_NONBLOCK); -#endif - int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k - setsockopt(tmpsock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize)); - port = from.sin_port; - in.s_addr = from.sin_addr.s_addr; - - // New TCP connection, this must consume the socket. - CreateNewConnection(GetNextID(), tmpsock, in.s_addr, ntohs(from.sin_port)); - } -} - -bool BaseTCPServer::Open(uint16 in_port, char* errbuf) { - if (errbuf) - errbuf[0] = 0; - LockMutex lock(&MSock); - if (sock != 0) { - if (errbuf) - snprintf(errbuf, TCPServer_ErrorBufferSize, "Listening socket already open"); - return false; - } - if (in_port != 0) { - pPort = in_port; - } - -#ifdef _WINDOWS - SOCKADDR_IN address; - unsigned long nonblocking = 1; -#else - struct sockaddr_in address; -#endif - int reuse_addr = 1; - -// Setup internet address information. -// This is used with the bind() call - memset((char *) &address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_port = htons(pPort); - address.sin_addr.s_addr = htonl(INADDR_ANY); - -// Setting up TCP port for new TCP connections - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) { - if (errbuf) - snprintf(errbuf, TCPServer_ErrorBufferSize, "socket(): INVALID_SOCKET"); - return false; - } - -// Quag: dont think following is good stuff for TCP, good for UDP -// Mis: SO_REUSEADDR shouldn't be a problem for tcp--allows you to restart -// without waiting for conns in TIME_WAIT to die - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse_addr, sizeof(reuse_addr)); - - - if (bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) { -#ifdef _WINDOWS - closesocket(sock); -#else - close(sock); -#endif - sock = 0; - if (errbuf) - sprintf(errbuf, "bind(): <0"); - return false; - } - - int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k - setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize)); -#ifdef _WINDOWS - ioctlsocket (sock, FIONBIO, &nonblocking); -#else - fcntl(sock, F_SETFL, O_NONBLOCK); -#endif - - if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { -#ifdef _WINDOWS - closesocket(sock); - if (errbuf) - snprintf(errbuf, TCPServer_ErrorBufferSize, "listen() failed, Error: %d", WSAGetLastError()); -#else - close(sock); - if (errbuf) - snprintf(errbuf, TCPServer_ErrorBufferSize, "listen() failed, Error: %s", strerror(errno)); -#endif - sock = 0; - return false; - } - - return true; -} - -void BaseTCPServer::Close() { - StopLoopAndWait(); - - LockMutex lock(&MSock); - if (sock) { -#ifdef _WINDOWS - closesocket(sock); -#else - close(sock); -#endif - } - sock = 0; -} - -bool BaseTCPServer::IsOpen() { - MSock.lock(); - bool ret = (bool) (sock != 0); - MSock.unlock(); - return ret; -} diff --git a/common/tcp_server.h b/common/tcp_server.h deleted file mode 100644 index 0bc1966c0..000000000 --- a/common/tcp_server.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef TCPSERVER_H_ -#define TCPSERVER_H_ - -#include "types.h" -#include "mutex.h" -#include -#include - -#define TCPServer_ErrorBufferSize 1024 - -//this is the non-connection type specific server. -class BaseTCPServer { -public: - BaseTCPServer(uint16 iPort = 0); - virtual ~BaseTCPServer(); - - bool Open(uint16 iPort = 0, char* errbuf = 0); // opens the port - void Close(); // closes the port - bool IsOpen(); - inline uint16 GetPort() { return pPort; } - inline uint32 GetNextID() { return NextID++; } - -protected: - static ThreadReturnType TCPServerLoop(void* tmp); - - //factory method: - virtual void CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) = 0; - - - virtual void Process(); - bool RunLoop(); - Mutex MLoopRunning; - - void StopLoopAndWait(); - - void ListenNewConnections(); - - uint32 NextID; - - Mutex MRunLoop; - bool pRunLoop; - - Mutex MSock; - SOCKET sock; - uint16 pPort; - -}; - -template -class TCPServer : public BaseTCPServer { -protected: - typedef typename std::vector vstore; - typedef typename std::vector::iterator vitr; -public: - TCPServer(uint16 iPort = 0) - : BaseTCPServer(iPort) { - } - - virtual ~TCPServer() { - StopLoopAndWait(); - - //im not sure what the right thing to do here is... - //we are freeing a connection which somebody likely has a pointer to.. - //but, we really shouldent ever get called anyhow.. - vitr cur, end; - cur = m_list.begin(); - end = m_list.end(); - for(; cur != end; ++cur) { - delete *cur; - } - } - - T * NewQueuePop() { - T * ret = nullptr; - MNewQueue.lock(); - if(!m_NewQueue.empty()) { - ret = m_NewQueue.front(); - m_NewQueue.pop(); - } - MNewQueue.unlock(); - return ret; - } - -protected: - virtual void Process() { - BaseTCPServer::Process(); - - vitr cur; - cur = m_list.begin(); - while(cur != m_list.end()) { - T *data = *cur; - if (data->IsFree() && (!data->CheckNetActive())) { - #if EQN_DEBUG >= 4 - std::cout << "TCPConnection Connection deleted." << std::endl; - #endif - delete data; - cur = m_list.erase(cur); - } else { - if (!data->Process()) - data->Disconnect(); - ++cur; - } - } - } - - void AddConnection(T *con) { - m_list.push_back(con); - MNewQueue.lock(); - m_NewQueue.push(con); - MNewQueue.unlock(); - } - - //queue of new connections, for the app to pull from - Mutex MNewQueue; - std::queue m_NewQueue; - - vstore m_list; -}; - - -#endif /*TCPSERVER_H_*/ - - - - - - - - - - - - - - diff --git a/common/worldconn.cpp b/common/worldconn.cpp deleted file mode 100644 index 432148f89..000000000 --- a/common/worldconn.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 -*/ - -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include - -#include "worldconn.h" -#include "eqemu_config.h" -#include "md5.h" -#include "servertalk.h" - -WorldConnection::WorldConnection(EmuTCPConnection::ePacketMode mode, const char *password) -: m_password(password) -{ - tcpc.SetPacketMode(mode); - pTryReconnect = true; - pConnected = false; -} - -WorldConnection::~WorldConnection() { -} - -bool WorldConnection::SendPacket(ServerPacket* pack) { - if (!Connected()) - return false; - return tcpc.SendPacket(pack); -} - -void WorldConnection::OnConnected() { - const EQEmuConfig *Config=EQEmuConfig::get(); - Log.Out(Logs::General, Logs::Netcode, "[WORLD] Connected to World: %s:%d", Config->WorldIP.c_str(), Config->WorldTCPPort); - - auto pack = new ServerPacket(ServerOP_ZAAuth, 16); - MD5::Generate((const uchar*) m_password.c_str(), m_password.length(), pack->pBuffer); - SendPacket(pack); - safe_delete(pack); -} - -void WorldConnection::Process() { - //persistent connection.... - if (!Connected()) { - pConnected = tcpc.Connected(); - if (pConnected) { - OnConnected(); - } - else - return; - } - -} - -void WorldConnection::AsyncConnect() { - const EQEmuConfig *Config=EQEmuConfig::get(); - tcpc.AsyncConnect(Config->WorldIP.c_str(), Config->WorldTCPPort); -} - -bool WorldConnection::Connect() { - const EQEmuConfig *Config=EQEmuConfig::get(); - char errbuf[TCPConnection_ErrorBufferSize]; - if (tcpc.Connect(Config->WorldIP.c_str(), Config->WorldTCPPort, errbuf)) { - return true; - } else { - Log.Out(Logs::General, Logs::Netcode, "[WORLD] WorldConnection connect: Connecting to the server %s:%d failed: %s", Config->WorldIP.c_str(), Config->WorldTCPPort, errbuf); - } - return false; -} - -void WorldConnection::Disconnect() { - tcpc.Disconnect(); -} - diff --git a/common/worldconn.h b/common/worldconn.h deleted file mode 100644 index 83d9a9cd7..000000000 --- a/common/worldconn.h +++ /dev/null @@ -1,59 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 WORLDCONNECTION_H -#define WORLDCONNECTION_H - -#include "../common/emu_tcp_connection.h" -#include - -class ServerPacket; - -/* - * This object is an arbitrary connection to world. - */ -class WorldConnection { -public: - WorldConnection(EmuTCPConnection::ePacketMode mode, const char *password = ""); - virtual ~WorldConnection(); - - virtual void Process(); - bool SendPacket(ServerPacket* pack); - - uint32 GetIP() const { return tcpc.GetrIP(); } - uint16 GetPort() const { return tcpc.GetrPort(); } - bool Connected() const { return (pConnected && tcpc.Connected()); } - - void SetPassword(const char *password) { m_password = password; } - bool Connect(); - void AsyncConnect(); - void Disconnect(); - inline bool TryReconnect() const { return pTryReconnect; } - -protected: - virtual void OnConnected(); - - std::string m_password; - EmuTCPConnection tcpc; - bool pTryReconnect; - bool pConnected; -}; - - -#endif - diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index df812e8c0..21893740f 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -20,13 +20,12 @@ #include "../common/global_define.h" #include "../common/string_util.h" #include "../common/eqemu_logsys.h" +#include "../common/misc_functions.h" #include "clientlist.h" #include "database.h" #include "chatchannel.h" -#include "../common/emu_tcp_connection.h" -#include "../common/emu_tcp_server.h" #include #include #include diff --git a/wi/.gitignore b/wi/.gitignore new file mode 100644 index 000000000..b449f1759 --- /dev/null +++ b/wi/.gitignore @@ -0,0 +1,47 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity diff --git a/wi/index.js b/wi/index.js new file mode 100644 index 000000000..09958863c --- /dev/null +++ b/wi/index.js @@ -0,0 +1,33 @@ +var servertalk = require('./servertalk_client.js'); +var fs = require('fs'); +var settings = JSON.parse(fs.readFileSync('settings.json', 'utf8')); + +var client = new servertalk.client(); + +client.Init(settings.addr, settings.port, false, 'WebInterface', settings.key); + +client.on('connecting', function(){ + console.log('Connecting...'); +}); + +client.on('connect', function(){ + console.log('Connected...'); + + this.Send(47, Buffer.from(JSON.stringify({ method: 'IsLocked', params: [], id: '12345' }))); + this.Send(47, Buffer.from(JSON.stringify({ method: 'Lock', params: [] }))); + this.Send(47, Buffer.from(JSON.stringify({ method: 'IsLocked', params: [], id: '12346' }))); + this.Send(47, Buffer.from(JSON.stringify({ method: 'Unlock', params: [] }))); + this.Send(47, Buffer.from(JSON.stringify({ method: 'IsLocked', params: [], id: '12347' }))); +}); + +client.on('close', function(){ + console.log('Closed'); +}); + +client.on('error', function(err){ + console.log(err); +}); + +client.on('message', function(opcode, packet) { + console.log(Buffer.from(packet).toString('utf8')); +}); diff --git a/wi/package.json b/wi/package.json new file mode 100644 index 000000000..883966b86 --- /dev/null +++ b/wi/package.json @@ -0,0 +1,15 @@ +{ + "name": "wi", + "version": "1.0.0", + "description": "Web interface connection for EQEmu", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "KimLS", + "license": "GPL-3.0", + "dependencies": { + "libsodium": "^0.4.8", + "libsodium-wrappers": "^0.4.8" + } +} diff --git a/wi/servertalk_client.js b/wi/servertalk_client.js new file mode 100644 index 000000000..7ccf41303 --- /dev/null +++ b/wi/servertalk_client.js @@ -0,0 +1,299 @@ +var net = require('net'); +var sodium = require('libsodium-wrappers'); +const EventEmitter = require('events'); + +var ServertalkPacketType = +{ + ServertalkClientHello: 1, + ServertalkServerHello: 2, + ServertalkClientHandshake: 3, + ServertalkClientDowngradeSecurityHandshake: 4, + ServertalkMessage: 5, +}; + +class ServertalkClient extends EventEmitter +{ + Init(addr, port, ipv6, identifier, credentials) { + this.m_addr = addr; + this.m_identifier = identifier; + this.m_credentials = credentials; + this.m_connecting = false; + this.m_port = port; + this.m_ipv6 = ipv6; + this.m_encrypted = false; + this.m_connection = null; + this.m_buffer = Buffer.alloc(0); + this.m_public_key_ours = null; + this.m_private_key_ours = null; + this.m_nonce_ours = null; + this.m_public_key_theirs = null; + this.m_nonce_theirs = null; + this.m_shared_key = null; + + var self = this; + setInterval(function() { self.Connect(); }, 100); + } + + Send(opcode, p) { + try { + var out; + if(this.m_encrypted) { + if(p.length == 0) { + p = Buffer.alloc(1); + } + + out = Buffer.alloc(6); + out.writeUInt32LE(p.length + sodium.crypto_secretbox_MACBYTES, 0); + out.writeUInt16LE(opcode, 4); + + var cipher = sodium.crypto_box_easy_afternm(p, this.m_nonce_ours, this.m_shared_key); + this.IncrementUint64(this.m_nonce_ours); + + out = Buffer.concat([out, Buffer.from(cipher)], out.length + cipher.length); + } else { + out = Buffer.alloc(6); + out.writeUInt32LE(p.length, 0); + out.writeUInt16LE(opcode, 4); + out = Buffer.concat([out, p], out.length + p.length); + } + + this.InternalSend(ServertalkPacketType.ServertalkMessage, out); + } catch(ex) { + this.emit('error', new Error(ex)); + } + } + + Connected() { + return this.m_connection && !this.m_connecting; + } + + Connect() { + if (this.m_port == 0 || this.m_connection || this.m_connecting) { + return; + } + + this.m_connecting = true; + + this.emit('connecting'); + + var self = this; + this.m_connection = net.connect({port: this.m_port, host: this.m_addr}, function() { + self.m_connection.on('close', function(had_error) { + self.emit('close'); + self.m_connection = null; + self.m_encrypted = false; + }); + + self.m_connection.on('data', function(buffer) { + self.ProcessData(buffer); + }); + + self.SendHello(); + self.m_connecting = false; + }); + + this.m_connection.on('error', function() { + self.emit('close'); + self.m_connection = null; + self.m_connecting = false; + }); + } + + ProcessData(buffer) { + this.m_buffer = Buffer.concat([this.m_buffer, buffer], this.m_buffer.length + buffer.length); + this.ProcessReadBuffer(); + } + + SendHello() { + var p = Buffer.alloc(0); + this.InternalSend(ServertalkPacketType.ServertalkClientHello, p); + } + + InternalSend(type, p) { + if(!this.m_connection) { + return; + } + + var out = Buffer.alloc(5); + out.writeUInt32LE(p.length, 0); + out.writeUInt8(type, 4); + + if (p.length > 0) { + out = Buffer.concat([out, p], out.length + p.length); + } + + this.m_connection.write(out); + } + + ProcessReadBuffer() { + var current = 0; + var total = this.m_buffer.length; + + while (current < total) { + var left = total - current; + + var length = 0; + var type = 0; + if (left < 5) { + break; + } + + length = this.m_buffer.readUInt32LE(current); + type = this.m_buffer.readUInt8(current + 4); + + if (current + 5 + length > total) { + break; + } + + if (length == 0) { + var p = Buffer.alloc(0); + switch (type) { + case ServertalkPacketType.ServertalkServerHello: + this.ProcessHello(p); + break; + case ServertalkPacketType.ServertalkMessage: + this.ProcessMessage(p); + break; + } + } + else { + var p = this.m_buffer.slice(current + 5, current + 5 + length); + switch (type) { + case ServertalkPacketType.ServertalkServerHello: + this.ProcessHello(p); + break; + case ServertalkPacketType.ServertalkMessage: + this.ProcessMessage(p); + break; + } + } + + current += length + 5; + } + + if (current == total) { + this.m_buffer = Buffer.alloc(0); + } + else { + this.m_buffer = this.m_buffer.slice(current); + } + } + + ProcessHello(p) { + this.m_encrypted = false; + this.m_public_key_ours = null; + this.m_public_key_theirs = null; + this.m_private_key_ours = null; + this.m_nonce_ours = null; + this.m_nonce_theirs = null; + this.m_shared_key = null; + + try { + var enc = p.readUInt8(0) == 1 ? true : false; + if (enc) { + if (p.length == (1 + sodium.crypto_box_PUBLICKEYBYTES + sodium.crypto_box_NONCEBYTES)) { + this.m_public_key_theirs = p.slice(1, 1 + sodium.crypto_box_PUBLICKEYBYTES); + this.m_nonce_theirs = p.slice(1 + sodium.crypto_box_PUBLICKEYBYTES, 1 + sodium.crypto_box_PUBLICKEYBYTES + sodium.crypto_box_NONCEBYTES); + this.m_encrypted = true; + this.SendHandshake(false); + + this.emit('connect'); + } + else { + this.emit('error', new Error('Could not process hello, size !=', 1 + sodium.crypto_box_PUBLICKEYBYTES + sodium.crypto_box_NONCEBYTES)); + } + } else { + this.SendHandshake(false); + + this.emit('connect'); + } + } catch(ex) { + this.emit('error', new Error(ex)); + } + } + + ProcessMessage(p) { + try { + var length = this.m_buffer.readUInt32LE(0); + var opcode = this.m_buffer.readUInt16LE(4); + if(length > 0) { + var data = p.slice(6); + + if(this.m_encrypted) { + var message_len = length - sodium.crypto_secretbox_MACBYTES; + + var decrypted = sodium.crypto_box_open_easy_afternm(data, this.m_nonce_theirs, this.m_shared_key); + + this.IncrementUint64(this.m_nonce_theirs); + + this.emit('message', opcode, decrypted); + } else { + this.emit('message', opcode, data); + } + } else { + this.emit('message', opcode, Buffer.alloc(0)); + } + } catch(ex) { + this.emit('error', new Error(ex)); + } + } + + SendHandshake() { + var handshake; + + if(this.m_encrypted) { + var keypair = sodium.crypto_box_keypair(); + this.m_public_key_ours = keypair.publicKey; + this.m_private_key_ours = keypair.privateKey; + this.m_nonce_ours = Buffer.from(sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES)); + this.m_shared_key = sodium.crypto_box_beforenm(this.m_public_key_theirs, this.m_private_key_ours); + + this.m_public_key_theirs = null; + this.m_private_key_ours = null; + + var message = Buffer.alloc(this.m_identifier.length + this.m_credentials.length + 2); + message.write(this.m_identifier, 0); + message.write(this.m_credentials, this.m_identifier.length + 1); + + var ciphertext = sodium.crypto_box_easy_afternm(message, this.m_nonce_ours, this.m_shared_key); + + handshake = Buffer.concat([Buffer.from(this.m_public_key_ours), Buffer.from(this.m_nonce_ours), Buffer.from(ciphertext)], sodium.crypto_box_PUBLICKEYBYTES + sodium.crypto_box_NONCEBYTES + ciphertext.length); + this.IncrementUint64(this.m_nonce_ours); + + this.m_public_key_ours = null; + } else { + handshake = Buffer.alloc(this.m_identifier.length + this.m_credentials.length + 2); + handshake.write(this.m_identifier, 0); + handshake.write(this.m_credentials, this.m_identifier.length() + 1); + } + + this.InternalSend(ServertalkPacketType.ServertalkClientHandshake, handshake); + } + + IncrementUint64(value) { + var bytes = []; + for(var i = 0; i < 8; ++i) { + bytes[i] = value[i]; + } + + bytes[0] += 1; + for(i = 0; i < 7; ++i) { + if(bytes[i] >= 0x100) { + bytes[0] = 0; + bytes[i + 1] += 1; + } + } + + if(bytes[7] >= 0x100) { + bytes[7] = 0; + } + + for(var i = 0; i < 8; ++i) { + value[i] = bytes[i]; + } + } +} + +module.exports = { + 'client': ServertalkClient +} \ No newline at end of file diff --git a/wi/settings.json b/wi/settings.json new file mode 100644 index 000000000..64c8c2d25 --- /dev/null +++ b/wi/settings.json @@ -0,0 +1,5 @@ +{ + "addr": "localhost", + "port": "9101", + "key": "ujwn2isnal1987scanb" +} \ No newline at end of file diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index cb981939c..e2a39225e 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -6,23 +6,17 @@ SET(world_sources client.cpp cliententry.cpp clientlist.cpp - CMakeLists.txt eql_config.cpp - eqw.cpp - eqw_http_handler.cpp - eqw_parser.cpp - http_request.cpp launcher_link.cpp launcher_list.cpp lfplist.cpp login_server.cpp login_server_list.cpp net.cpp - perl_eql_config.cpp - perl_eqw.cpp - perl_http_request.cpp queryserv.cpp ucs.cpp + web_interface.cpp + web_interface_eqw.cpp wguild_mgr.cpp world_config.cpp worlddb.cpp @@ -37,12 +31,7 @@ SET(world_headers client.h cliententry.h clientlist.h - CMakeLists.txt eql_config.h - eqw.h - eqw_http_handler.h - eqw_parser.h - http_request.h launcher_link.h launcher_list.h lfplist.h @@ -52,10 +41,11 @@ SET(world_headers queryserv.h sof_char_create_data.h ucs.h + web_interface.h + web_interface_eqw.h wguild_mgr.h world_config.h worlddb.h - world_tcp_connection.h zonelist.h zoneserver.h ) diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 4f93a5610..cc246a5d7 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -21,15 +21,15 @@ #include "zoneserver.h" #include "zonelist.h" #include "client.h" -#include "console.h" #include "worlddb.h" #include "../common/string_util.h" #include "../common/guilds.h" #include "../common/races.h" #include "../common/classes.h" #include "../common/packet_dump.h" -#include "wguild_mgr.h" #include "../common/misc.h" +#include "../common/misc_functions.h" +#include "wguild_mgr.h" #include diff --git a/world/console.cpp b/world/console.cpp deleted file mode 100644 index 6f37d0bf1..000000000 --- a/world/console.cpp +++ /dev/null @@ -1,854 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - 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 -*/ -#include "../common/global_define.h" -#include -#include -#include -#include -#include - - -#include "../common/version.h" -#include "console.h" -#include "zoneserver.h" -#include "worlddb.h" -#include "../common/packet_dump.h" -#include "../common/seperator.h" -#include "../common/eq_packet_structs.h" -#include "../common/eq_packet.h" -#include "login_server.h" -#include "login_server_list.h" -#include "../common/serverinfo.h" -#include "../common/md5.h" -#include "../common/opcodemgr.h" -#include "../common/rulesys.h" -#include "../common/ruletypes.h" -#include "../common/string_util.h" -#include "world_config.h" -#include "zoneserver.h" -#include "zonelist.h" -#include "clientlist.h" -#include "launcher_list.h" -#include "ucs.h" -#include "queryserv.h" - -#ifdef _WINDOWS - #define snprintf _snprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#endif - -extern ZSList zoneserver_list; -extern uint32 numzones; -extern LoginServerList loginserverlist; -extern ClientList client_list; -extern LauncherList launcher_list; -extern UCSConnection UCSLink; -extern QueryServConnection QSLink; -extern volatile bool RunLoops; - -ConsoleList console_list; -void CatchSignal(int sig_num); - -Console::Console(EmuTCPConnection* itcpc) -: WorldTCPConnection(), - timeout_timer(RuleI(Console, SessionTimeOut)), - prompt_timer(1000) -{ - tcpc = itcpc; - tcpc->SetEcho(true); - state = 0; - paccountid = 0; - memset(paccountname, 0, sizeof(paccountname)); - admin = 0; - pAcceptMessages = false; -} - -Console::~Console() { - if (tcpc) - tcpc->Free(); -} - -void Console::Die() { - state = CONSOLE_STATE_CLOSED; - struct in_addr in; - in.s_addr = GetIP(); - Log.Out(Logs::Detail, Logs::World_Server,"Removing console from %s:%d",inet_ntoa(in),GetPort()); - tcpc->Disconnect(); -} - -bool Console::SendChannelMessage(const ServerChannelMessage_Struct* scm) { - if (!pAcceptMessages) - return false; - switch (scm->chan_num) { - if(RuleB(Chat, ServerWideAuction)){ - case 4: { - SendMessage(1, "%s auctions, '%s'", scm->from, scm->message); - break; - } - } - if(RuleB(Chat, ServerWideOOC)){ - case 5: { - SendMessage(1, "%s says ooc, '%s'", scm->from, scm->message); - break; - } - } - case 6: { - SendMessage(1, "%s BROADCASTS, '%s'", scm->from, scm->message); - break; - } - case 7: { - SendMessage(1, "[%s] tells you, '%s'", scm->from, scm->message); - auto pack = new ServerPacket(ServerOP_ChannelMessage, - sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1); - memcpy(pack->pBuffer, scm, pack->size); - ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*) pack->pBuffer; - strcpy(scm2->deliverto, scm2->from); - scm2->noreply = true; - client_list.SendPacket(scm->from, pack); - safe_delete(pack); - break; - } - case 11: { - SendMessage(1, "%s GMSAYS, '%s'", scm->from, scm->message); - break; - } - default: { - return false; - } - } - return true; -} - -bool Console::SendEmoteMessage(uint32 type, const char* message, ...) { - if (!message) - return false; - if (!pAcceptMessages) - return false; - va_list argptr; - char buffer[1024]; - - va_start(argptr, message); - vsnprintf(buffer, sizeof(buffer), message, argptr); - va_end(argptr); - - SendMessage(1, message); - return true; -} - -bool Console::SendEmoteMessageRaw(uint32 type, const char* message) { - if (!message) - return false; - if (!pAcceptMessages) - return false; - SendMessage(1, message); - return true; -} - -void Console::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...) { - if (!message) - return; - if (to_guilddbid != 0 || to_minstatus > Admin()) - return; - va_list argptr; - char buffer[1024]; - - va_start(argptr, message); - vsnprintf(buffer, sizeof(buffer), message, argptr); - va_end(argptr); - - SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, buffer); -} - -void Console::SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message) { - if (!message) - return; - if (to_guilddbid != 0 || to_minstatus > Admin()) - return; - SendMessage(1, message); -} - -void Console::SendMessage(uint8 newline, const char* message, ...) { - if (!message) - return; - char* buffer = 0; - uint32 bufsize = 1500; - if (message) - bufsize += strlen(message); - buffer = new char[bufsize]; - memset(buffer, 0, bufsize); - if (message != 0) { - va_list argptr; - - va_start(argptr, message); - vsnprintf(buffer, bufsize - 512, message, argptr); - va_end(argptr); - } - - if (newline) { - char outbuf[3]; - outbuf[0] = 13; - outbuf[1] = 10; - outbuf[2] = 0; - for (int i=0; i < newline; i++) - strcat(buffer, outbuf); - } - tcpc->Send((uchar*) buffer, strlen(buffer)); - safe_delete_array(buffer); -} - -bool Console::Process() { - if (state == CONSOLE_STATE_CLOSED) - return false; - - if (!tcpc->Connected()) { - struct in_addr in; - in.s_addr = GetIP(); - Log.Out(Logs::Detail, Logs::World_Server,"Removing console (!tcpc->Connected) from %s:%d",inet_ntoa(in),GetPort()); - return false; - } - //if we have not gotten the special markers after this timer, send login prompt - if(prompt_timer.Check()) { - prompt_timer.Disable(); - if(tcpc->GetMode() == EmuTCPConnection::modeConsole) - tcpc->Send((const uchar*) "Username: ", strlen("Username: ")); - } - - if (timeout_timer.Check()) { - SendMessage(1, 0); - SendMessage(1, "Timeout, disconnecting..."); - struct in_addr in; - in.s_addr = GetIP(); - Log.Out(Logs::Detail, Logs::World_Server,"TCP connection timeout from %s:%d",inet_ntoa(in),GetPort()); - return false; - } - - if (tcpc->GetMode() == EmuTCPConnection::modePacket) { - struct in_addr in; - in.s_addr = GetIP(); - //if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeZone) { - // auto zs = new ZoneServer(tcpc); - // Log.Out(Logs::Detail, Logs::World_Server,"New zoneserver #%d from %s:%d", zs->GetID(), inet_ntoa(in), GetPort()); - // zoneserver_list.Add(zs); - // numzones++; - // tcpc = 0; - //} else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeLauncher) { - // Log.Out(Logs::Detail, Logs::World_Server,"New launcher from %s:%d", inet_ntoa(in), GetPort()); - // launcher_list.Add(tcpc); - // tcpc = 0; - //} - //else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS) - //{ - // Log.Out(Logs::Detail, Logs::World_Server,"New UCS Connection from %s:%d", inet_ntoa(in), GetPort()); - // UCSLink.SetConnection(tcpc); - // tcpc = 0; - //} - //else { - // Log.Out(Logs::Detail, Logs::World_Server,"Unsupported packet mode from %s:%d", inet_ntoa(in), GetPort()); - //} - return false; - } - char* command = 0; - while ((command = tcpc->PopLine())) { - timeout_timer.Start(); - ProcessCommand(command); - delete command; - } - return true; -} - -void ConsoleList::Add(Console* con) { - list.Insert(con); -} - -void ConsoleList::Process() { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - if (!iterator.GetData()->Process()) - iterator.RemoveCurrent(); - else - iterator.Advance(); - } -} - -void ConsoleList::KillAll() { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - iterator.GetData()->Die(); - iterator.RemoveCurrent(); - } -} - -void ConsoleList::SendConsoleWho(WorldTCPConnection* connection, const char* to, int16 admin, char** output, uint32* outsize, uint32* outlen) { - LinkedListIterator iterator(list); - iterator.Reset(); - struct in_addr in; - int x = 0; - - while(iterator.MoreElements()) { - in.s_addr = iterator.GetData()->GetIP(); - if (admin >= iterator.GetData()->Admin()) - AppendAnyLenString(output, outsize, outlen, " Console: %s:%i AccID: %i AccName: %s", inet_ntoa(in), iterator.GetData()->GetPort(), iterator.GetData()->AccountID(), iterator.GetData()->AccountName()); - else - AppendAnyLenString(output, outsize, outlen, " Console: AccID: %i AccName: %s", iterator.GetData()->AccountID(), iterator.GetData()->AccountName()); - if (*outlen >= 3584) { - connection->SendEmoteMessageRaw(to, 0, 0, 10, *output); - safe_delete(*output); - *outsize = 0; - *outlen = 0; - } - else { - if (connection->IsConsole()) - AppendAnyLenString(output, outsize, outlen, "\r\n"); - else - AppendAnyLenString(output, outsize, outlen, "\n"); - } - x++; - iterator.Advance(); - } - AppendAnyLenString(output, outsize, outlen, "%i consoles connected", x); -} - -void ConsoleList::SendChannelMessage(const ServerChannelMessage_Struct* scm) { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - iterator.GetData()->SendChannelMessage(scm); - iterator.Advance(); - } -} - -void ConsoleList::SendEmoteMessage(uint32 type, const char* message, ...) { - va_list argptr; - char buffer[1024]; - - va_start(argptr, message); - vsnprintf(buffer, sizeof(buffer), message, argptr); - va_end(argptr); - - SendEmoteMessageRaw(type, buffer); -} - -void ConsoleList::SendEmoteMessageRaw(uint32 type, const char* message) { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - iterator.GetData()->SendEmoteMessageRaw(type, message); - iterator.Advance(); - } -} - -Console* ConsoleList::FindByAccountName(const char* accname) { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - if (strcasecmp(iterator.GetData()->AccountName(), accname) == 0) - return iterator.GetData(); - - iterator.Advance(); - } - return 0; -} - -void Console::ProcessCommand(const char* command) { - switch(state) - { - case CONSOLE_STATE_USERNAME: - { - if (strlen(command) >= 16) { - SendMessage(1, 0); - SendMessage(2, "Username buffer overflow."); - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - return; - } - strcpy(paccountname, command); - state = CONSOLE_STATE_PASSWORD; - SendMessage(0, "Password: "); - tcpc->SetEcho(false); - break; - } - case CONSOLE_STATE_PASSWORD: - { - if (strlen(command) >= 16) { - SendMessage(1, 0); - SendMessage(2, "Password buffer overflow."); - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - return; - } - paccountid = database.CheckLogin(paccountname ,command); - if (paccountid == 0) { - SendMessage(1, 0); - SendMessage(2, "Login failed."); - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - return; - } - database.GetAccountName(paccountid, paccountname); // fixes case and stuff - admin = database.CheckStatus(paccountid); - if (!(admin >= consoleLoginStatus)) { - SendMessage(1, 0); - SendMessage(2, "Access denied."); - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - return; - } - Log.Out(Logs::Detail, Logs::World_Server,"TCP console authenticated: Username=%s, Admin=%d",paccountname,admin); - SendMessage(1, 0); - SendMessage(2, "Login accepted."); - state = CONSOLE_STATE_CONNECTED; - tcpc->SetEcho(true); - SendPrompt(); - break; - } - case CONSOLE_STATE_CONNECTED: { - Log.Out(Logs::Detail, Logs::World_Server,"TCP command: %s: \"%s\"",paccountname ,command); - Seperator sep(command); - if (strcasecmp(sep.arg[0], "help") == 0 || strcmp(sep.arg[0], "?") == 0) { - SendMessage(1, " whoami"); - SendMessage(1, " who"); - SendMessage(1, " zonestatus"); - SendMessage(1, " uptime [zoneID#]"); - SendMessage(1, " emote [zonename or charname or world] [type] [message]"); - SendMessage(1, " echo [on/off]"); - SendMessage(1, " acceptmessages [on/off]"); - SendMessage(1, " tell [name] [message]"); - SendMessage(1, " broadcast [message]"); - SendMessage(1, " gmsay [message]"); - SendMessage(1, " ooc [message]"); - SendMessage(1, " auction [message]"); - if (admin >= consoleKickStatus) - SendMessage(1, " kick [charname]"); - if (admin >= consoleLockStatus) - SendMessage(1, " lock/unlock"); - if (admin >= consoleZoneStatus) { - SendMessage(1, " zoneshutdown [zonename or ZoneServerID]"); - SendMessage(1, " zonebootup [ZoneServerID] [zonename]"); - SendMessage(1, " zonelock [list|lock|unlock] [zonename]"); - } - if (admin >= consoleFlagStatus) - SendMessage(1, " flag [status] [accountname]"); - if (admin >= consolePassStatus) - SendMessage(1, " setpass [accountname] [newpass]"); - if (admin >= consoleWorldStatus) { - SendMessage(1, " version"); - SendMessage(1, " worldshutdown"); - } - if (admin >= 201) { - SendMessage(1, " IPLookup [name]"); - } - if (admin >= 100) { - SendMessage(1, " signalcharbyname charname ID"); - SendMessage(1, " reloadworld"); - } - } - else if (strcasecmp(sep.arg[0], "ping") == 0) { - // do nothing - } - else if (strcasecmp(sep.arg[0], "signalcharbyname") == 0) { - SendMessage(1, "Signal Sent to %s with ID %i", (char*) sep.arg[1], atoi(sep.arg[2])); - uint32 message_len = strlen((char*) sep.arg[1]) + 1; - auto pack = new ServerPacket(ServerOP_CZSignalClientByName, - sizeof(CZClientSignalByName_Struct) + message_len); - CZClientSignalByName_Struct* CZSC = (CZClientSignalByName_Struct*) pack->pBuffer; - strn0cpy(CZSC->Name, (char*) sep.arg[1], 64); - CZSC->data = atoi(sep.arg[2]); - zoneserver_list.SendPacket(pack); - safe_delete(pack); - } - else if (strcasecmp(sep.arg[0], "setpass") == 0 && admin >= consolePassStatus) { - if (sep.argnum != 2) - SendMessage(1, "Format: setpass accountname password"); - else { - - int16 tmpstatus = 0; - uint32 tmpid = database.GetAccountIDByName(sep.arg[1], &tmpstatus); - if (!tmpid) - SendMessage(1, "Error: Account not found"); - else if (tmpstatus > admin) - SendMessage(1, "Cannot change password: Account's status is higher than yours"); - else if (database.SetLocalPassword(tmpid, sep.arg[2])) - SendMessage(1, "Password changed."); - else - SendMessage(1, "Error changing password."); - } - } - else if (strcasecmp(sep.arg[0], "uptime") == 0) { - if (sep.IsNumber(1) && atoi(sep.arg[1]) > 0) { - auto pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct)); - ServerUptime_Struct* sus = (ServerUptime_Struct*) pack->pBuffer; - snprintf(sus->adminname, sizeof(sus->adminname), "*%s", this->GetName()); - sus->zoneserverid = atoi(sep.arg[1]); - ZoneServer* zs = zoneserver_list.FindByID(sus->zoneserverid); - if (zs) - zs->SendPacket(pack); - else - SendMessage(1, "Zoneserver not found."); - delete pack; - } - else { - ZSList::ShowUpTime(this); - } - } - else if (strcasecmp(sep.arg[0], "md5") == 0) { - uint8 md5[16]; - MD5::Generate((const uchar*) sep.argplus[1], strlen(sep.argplus[1]), md5); - SendMessage(1, "MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", md5[0], md5[1], md5[2], md5[3], md5[4], md5[5], md5[6], md5[7], md5[8], md5[9], md5[10], md5[11], md5[12], md5[13], md5[14], md5[15]); - } - else if (strcasecmp(sep.arg[0], "whoami") == 0) { - SendMessage(1, "You are logged in as '%s'", this->AccountName()); - SendMessage(1, "You are known as '*%s'", this->AccountName()); - SendMessage(1, "AccessLevel: %d", this->Admin()); - } - else if (strcasecmp(sep.arg[0], "echo") == 0) { - if (strcasecmp(sep.arg[1], "on") == 0) - tcpc->SetEcho(true); - else if (strcasecmp(sep.arg[1], "off") == 0) { - if (pAcceptMessages) - SendMessage(1, "Echo can not be turned off while acceptmessages is on"); - else - tcpc->SetEcho(false); - } - else - SendMessage(1, "Usage: echo [on/off]"); - } - else if (strcasecmp(sep.arg[0], "acceptmessages") == 0) { - if (strcasecmp(sep.arg[1], "on") == 0) - if (tcpc->GetEcho()) - SendMessage(1, "AcceptMessages can not be turned on while echo is on"); - else - pAcceptMessages = true; - else if (strcasecmp(sep.arg[1], "off") == 0) - pAcceptMessages = false; - else - SendMessage(1, "Usage: acceptmessages [on/off]"); - } - else if (strcasecmp(sep.arg[0], "tell") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, sep.arg[1], 7, 0, sep.argplus[2]); - } - else if (strcasecmp(sep.arg[0], "broadcast") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "ooc") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "auction") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "gmsay") == 0 || strcasecmp(sep.arg[0], "pr") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "emote") == 0) { - if (strcasecmp(sep.arg[1], "world") == 0) - zoneserver_list.SendEmoteMessageRaw(0, 0, 0, atoi(sep.arg[2]), sep.argplus[3]); - else { - ZoneServer* zs = zoneserver_list.FindByName(sep.arg[1]); - if (zs != 0) - zs->SendEmoteMessageRaw(0, 0, 0, atoi(sep.arg[2]), sep.argplus[3]); - else - zoneserver_list.SendEmoteMessageRaw(sep.arg[1], 0, 0, atoi(sep.arg[2]), sep.argplus[3]); - } - } - else if (strcasecmp(sep.arg[0], "movechar") == 0) { - if(sep.arg[1][0]==0 || sep.arg[2][0] == 0) - SendMessage(1, "Usage: movechar [charactername] [zonename]"); - else { - if (!database.GetZoneID(sep.arg[2])) - SendMessage(1, "Error: Zone '%s' not found", sep.arg[2]); - else if (!database.CheckUsedName((char*) sep.arg[1])) { - if (!database.MoveCharacterToZone((char*) sep.arg[1], (char*) sep.arg[2])) - SendMessage(1, "Character Move Failed!"); - else - SendMessage(1, "Character has been moved."); - } - else - SendMessage(1, "Character Does Not Exist"); - } - } - else if (strcasecmp(sep.arg[0], "flag") == 0 && this->Admin() >= consoleFlagStatus) { -// SCORPIOUS2K - reversed parameter order for flag - if(sep.arg[2][0]==0 || !sep.IsNumber(1)) - SendMessage(1, "Usage: flag [status] [accountname]"); - else - { - if (atoi(sep.arg[1]) > this->Admin()) - SendMessage(1, "You cannot set people's status to higher than your own"); - else if (atoi(sep.arg[1]) < 0 && this->Admin() < consoleFlagStatus) - SendMessage(1, "You have too low of status to change flags"); - else if (!database.SetAccountStatus(sep.arg[2], atoi(sep.arg[1]))) - SendMessage(1, "Unable to flag account!"); - else - SendMessage(1, "Account Flaged"); - } - } - else if (strcasecmp(sep.arg[0], "kick") == 0 && admin >= consoleKickStatus) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - auto pack = new ServerPacket; - pack->opcode = ServerOP_KickPlayer; - pack->size = sizeof(ServerKickPlayer_Struct); - pack->pBuffer = new uchar[pack->size]; - ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer; - strcpy(skp->adminname, tmpname); - strcpy(skp->name, sep.arg[1]); - skp->adminrank = this->Admin(); - zoneserver_list.SendPacket(pack); - delete pack; - } - else if (strcasecmp(sep.arg[0], "who") == 0) { - auto whom = new Who_All_Struct; - memset(whom, 0, sizeof(Who_All_Struct)); - whom->lvllow = 0xFFFF; - whom->lvlhigh = 0xFFFF; - whom->wclass = 0xFFFF; - whom->wrace = 0xFFFF; - whom->gmlookup = 0xFFFF; - for (int i=1; i<=sep.argnum; i++) { - if (strcasecmp(sep.arg[i], "gm") == 0) - whom->gmlookup = 1; - else if (sep.IsNumber(i)) { - if (whom->lvllow == 0xFFFF) { - whom->lvllow = atoi(sep.arg[i]); - whom->lvlhigh = whom->lvllow; - } - else if (atoi(sep.arg[i]) > int(whom->lvllow)) - whom->lvlhigh = atoi(sep.arg[i]); - else - whom->lvllow = atoi(sep.arg[i]); - } - else - strn0cpy(whom->whom, sep.arg[i], sizeof(whom->whom)); - } - client_list.ConsoleSendWhoAll(0, admin, whom, this); - delete whom; - } - else if (strcasecmp(sep.arg[0], "zonestatus") == 0) { - zoneserver_list.SendZoneStatus(0, admin, this); - } - else if (strcasecmp(sep.arg[0], "exit") == 0 || strcasecmp(sep.arg[0], "quit") == 0) { - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - } - else if (strcasecmp(sep.arg[0], "zoneshutdown") == 0 && admin >= consoleZoneStatus) { - if (sep.arg[1][0] == 0) { - SendMessage(1, "Usage: zoneshutdown zoneshortname"); - } else { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - - auto pack = new ServerPacket; - pack->size = sizeof(ServerZoneStateChange_struct); - pack->pBuffer = new uchar[pack->size]; - memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct)); - ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *) pack->pBuffer; - pack->opcode = ServerOP_ZoneShutdown; - strcpy(s->adminname, tmpname); - if (sep.arg[1][0] >= '0' && sep.arg[1][0] <= '9') - s->ZoneServerID = atoi(sep.arg[1]); - else - s->zoneid = database.GetZoneID(sep.arg[1]); - - ZoneServer* zs = 0; - if (s->ZoneServerID != 0) - zs = zoneserver_list.FindByID(s->ZoneServerID); - else if (s->zoneid != 0) - zs = zoneserver_list.FindByName(database.GetZoneName(s->zoneid)); - else - SendMessage(1, "Error: ZoneShutdown: neither ID nor name specified"); - - if (zs == 0) - SendMessage(1, "Error: ZoneShutdown: zoneserver not found"); - else - zs->SendPacket(pack); - - delete pack; - } - } - else if (strcasecmp(sep.arg[0], "zonebootup") == 0 && admin >= consoleZoneStatus) { - if (sep.arg[2][0] == 0 || !sep.IsNumber(1)) { - SendMessage(1, "Usage: zonebootup ZoneServerID# zoneshortname"); - } else { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - - Log.Out(Logs::Detail, Logs::World_Server,"Console ZoneBootup: %s, %s, %s",tmpname,sep.arg[2],sep.arg[1]); - zoneserver_list.SOPZoneBootup(tmpname, atoi(sep.arg[1]), sep.arg[2], (bool) (strcasecmp(sep.arg[3], "static") == 0)); - } - } - else if (strcasecmp(sep.arg[0], "worldshutdown") == 0 && admin >= consoleWorldStatus) { - int32 time, interval; - if(sep.IsNumber(1) && sep.IsNumber(2) && ((time=atoi(sep.arg[1]))>0) && ((interval=atoi(sep.arg[2]))>0)) { - zoneserver_list.WorldShutDown(time, interval); - } - else if(strcasecmp(sep.arg[1], "now") == 0) { - zoneserver_list.WorldShutDown(0, 0); - } - else if(strcasecmp(sep.arg[1], "disable") == 0) { - SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World shutdown aborted."); - zoneserver_list.SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World shutdown aborted."); - zoneserver_list.shutdowntimer->Disable(); - zoneserver_list.reminder->Disable(); - } - else { - SendMessage(1, "Usage: worldshutdown [now] [disable] ([time] [interval])"); - //Go ahead and shut down since that's what this used to do when invoked this way. - zoneserver_list.WorldShutDown(0, 0); - } - } - else if (strcasecmp(sep.arg[0], "lock") == 0 && admin >= consoleLockStatus) { - WorldConfig::LockWorld(); - if (loginserverlist.Connected()) { - loginserverlist.SendStatus(); - SendMessage(1, "World locked."); - } - else { - SendMessage(1, "World locked, but login server not connected."); - } - } - else if (strcasecmp(sep.arg[0], "unlock") == 0 && admin >= consoleLockStatus) { - WorldConfig::UnlockWorld(); - if (loginserverlist.Connected()) { - loginserverlist.SendStatus(); - SendMessage(1, "World unlocked."); - } - else { - SendMessage(1, "World unlocked, but login server not connected."); - } - } - else if (strcasecmp(sep.arg[0], "version") == 0 && admin >= consoleWorldStatus) { - SendMessage(1, "Current version information."); - SendMessage(1, " %s", CURRENT_VERSION); - SendMessage(1, " Compiled on: %s at %s", COMPILE_DATE, COMPILE_TIME); - SendMessage(1, " Last modified on: %s", LAST_MODIFIED); - } - else if (strcasecmp(sep.arg[0], "serverinfo") == 0 && admin >= 200) { - if (strcasecmp(sep.arg[1], "os") == 0) { - #ifdef _WINDOWS - GetOS(); - char intbuffer [sizeof(unsigned long)]; - SendMessage(1, "Operating system information."); - SendMessage(1, " %s", Ver_name); - SendMessage(1, " Build number: %s", ultoa(Ver_build, intbuffer, 10)); - SendMessage(1, " Minor version: %s", ultoa(Ver_min, intbuffer, 10)); - SendMessage(1, " Major version: %s", ultoa(Ver_maj, intbuffer, 10)); - SendMessage(1, " Platform Id: %s", ultoa(Ver_pid, intbuffer, 10)); - #else - char os_string[100]; - SendMessage(1, "Operating system information."); - SendMessage(1, " %s", GetOS(os_string)); - #endif - } - else { - SendMessage(1, "Usage: Serverinfo [type]"); - SendMessage(1, " OS - Operating system version information."); - } - } - 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], "zonelock") == 0 && admin >= consoleZoneStatus) { - if (strcasecmp(sep.arg[1], "list") == 0) { - zoneserver_list.ListLockedZones(0, this); - } - else if (strcasecmp(sep.arg[1], "lock") == 0 && admin >= 101) { - uint16 tmp = database.GetZoneID(sep.arg[2]); - if (tmp) { - if (zoneserver_list.SetLockedZone(tmp, true)) - zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone locked: %s", database.GetZoneName(tmp)); - else - SendMessage(1, "Failed to change lock"); - } - else - SendMessage(1, "Usage: #zonelock lock [zonename]"); - } - else if (strcasecmp(sep.arg[1], "unlock") == 0 && admin >= 101) { - uint16 tmp = database.GetZoneID(sep.arg[2]); - if (tmp) { - if (zoneserver_list.SetLockedZone(tmp, false)) - zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone unlocked: %s", database.GetZoneName(tmp)); - else - SendMessage(1, "Failed to change lock"); - } - else - SendMessage(1, "Usage: #zonelock unlock [zonename]"); - } - else { - SendMessage(1, "#zonelock sub-commands"); - SendMessage(1, " list"); - if (admin >= 101) { - SendMessage(1, " lock [zonename]"); - SendMessage(1, " unlock [zonename]"); - } - } - } - else if (strcasecmp(sep.arg[0], "reloadworld") == 0 && admin > 101) - { - SendEmoteMessage(0,0,0,15,"Reloading World..."); - auto pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); - ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer; - RW->Option = 1; - zoneserver_list.SendPacket(pack); - safe_delete(pack); - } - else if (strcasecmp(sep.arg[0], "") == 0){ - /* Hit Enter with no command */ - } - else { - SendMessage(1, "Command unknown."); - } - if (state == CONSOLE_STATE_CONNECTED) - SendPrompt(); - break; - } - default: { - break; - } - } -} - -void Console::SendPrompt() { - if (tcpc->GetEcho()) - SendMessage(0, "%s> ", paccountname); -} - diff --git a/world/console.h b/world/console.h deleted file mode 100644 index e0a72f590..000000000 --- a/world/console.h +++ /dev/null @@ -1,109 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - 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 CONSOLE_H -#define CONSOLE_H - -enum { - consoleLoginStatus = 50, //ability to log in, basic commands. - httpLoginStatus = 100, //can log into the HTTP interface - consoleFlagStatus = 200, //flag - consoleKickStatus = 150, //kick - consoleLockStatus = 150, //world lock/unlock - consoleZoneStatus = 150, //zone up/down/lock - consolePassStatus = 200, //change password - consoleWorldStatus = 200, //world shutdown - consoleOpcodesStatus = 250 -}; - -#define CONSOLE_STATE_USERNAME 0 -#define CONSOLE_STATE_PASSWORD 1 -#define CONSOLE_STATE_CONNECTED 2 -#define CONSOLE_STATE_CLOSED 3 - -#include "../common/linked_list.h" -#include "../common/timer.h" -#include "../common/queue.h" -#include "../common/emu_tcp_connection.h" -#include "world_tcp_connection.h" -#include "../common/mutex.h" - -struct ServerChannelMessage_Struct; - -class Console : public WorldTCPConnection { -public: - Console(EmuTCPConnection* itcpc); - virtual ~Console(); - virtual inline bool IsConsole() { return true; } - - bool Process(); - void Send(const char* message); - int16 Admin() { return admin; } - uint32 GetIP() { return tcpc->GetrIP(); } - uint16 GetPort() { return tcpc->GetrPort(); } - void ProcessCommand(const char* command); - void Die(); - - bool SendChannelMessage(const ServerChannelMessage_Struct* scm); - bool SendEmoteMessage(uint32 type, const char* message, ...); - bool SendEmoteMessageRaw(uint32 type, const char* message); - void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...); - void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message); - void SendMessage(uint8 newline, const char* message, ...); - - const char* GetName() { return paccountname; } - const char* AccountName() { return paccountname; } - uint32 AccountID() { return paccountid; } -private: - EmuTCPConnection* tcpc; - - Timer timeout_timer; - Timer prompt_timer; - - void SendPrompt(); - - uint32 paccountid; - char paccountname[30]; - bool pAcceptMessages; - - uint8 state; - - int16 admin; - uchar textbuf[1024]; - int bufindex; -}; - -class ConsoleList -{ -public: - ConsoleList() {} - ~ConsoleList() {} - - void Add(Console* con); - void Process(); - void KillAll(); - - void SendChannelMessage(const ServerChannelMessage_Struct* scm); - void SendConsoleWho(WorldTCPConnection* connection, const char* to, int16 admin, char** output, uint32* outsize, uint32* outlen); - void SendEmoteMessage(uint32 type, const char* message, ...); - void SendEmoteMessageRaw(uint32 type, const char* message); - Console* FindByAccountName(const char* accname); -private: - LinkedList list; -}; -#endif - diff --git a/world/eqw_http_handler.cpp b/world/eqw_http_handler.cpp deleted file mode 100644 index c30620747..000000000 --- a/world/eqw_http_handler.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 -*/ -#include "../common/global_define.h" -#include "eqw_http_handler.h" -#include "../common/SocketLib/Base64.h" -#include "eqw_parser.h" -#include "eqw.h" -#include "http_request.h" - -#include "worlddb.h" -#include "console.h" - -Mime EQWHTTPHandler::s_mime; -#ifdef EMBPERL -EQWParser *EQWHTTPHandler::s_parser = nullptr; -#endif -const int EQWHTTPHandler::READ_BUFFER_LEN = 1024; //for page IO, was a static const member, but VC6 got mad. - -EQWHTTPHandler::EQWHTTPHandler(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -: HttpdSocket(ID,in_socket,irIP,irPort), - m_closeOnFinish(false) -{ -} - -EQWHTTPHandler::~EQWHTTPHandler() { - -} - -#ifdef EMBPERL -EQWParser *EQWHTTPHandler::GetParser() { - if(s_parser == nullptr) { - EQW::Singleton()->ClearOutput(); - s_parser = new EQWParser(); - const std::string &res = EQW::Singleton()->GetOutput(); - if(!res.empty()) { - printf("EQWParser Init output:\n%s\n\n", res.c_str()); - EQW::Singleton()->ClearOutput(); - } - } - return(s_parser); -} -#endif - -/*void EQWHTTPHandler::OnWrite() { - HttpdSocket::OnWrite(); - if(m_closeOnFinish && GetOutputLength() == 0) { -// printf("CLOSING\n"); - Close(); - } -}*/ - - -void EQWHTTPHandler::Exec() { - m_sentHeaders = false; - m_responseCode = "200"; -// printf("Request: %s, %s, %s, %s.\n", GetMethod().c_str(), GetUrl().c_str(), GetUri().c_str(), GetQueryString().c_str()); - - SetHttpVersion("HTTP/1.0"); - AddResponseHeader("Connection", "close"); - - if(GetUri().find("..") != std::string::npos) { - SendResponse("403", "Forbidden"); - printf("%s is forbidden.\n", GetUri().c_str()); - return; - } - - if(!CheckAuth()) { - AddResponseHeader("Content-type", "text/plain"); - AddResponseHeader("WWW-Authenticate", "Basic realm=\"EQEmulator\""); - SendResponse("401", "Authorization Required"); - SendString("Gotta Authenticate."); - } else { - std::string::size_type start = GetUri().find_first_not_of('/'); - std::string page; - if(start != std::string::npos) - page = GetUri().substr(start); - else - page = "index.html"; - SendPage(page); - } -/* if (!Detach()) { - printf("Unable to detach...\n"); - } - if(GetOutputLength() > 0) { - //we cannot close yet - m_closeOnFinish = true; - } else { - Close(); - }*/ - Free(); //the "app" side (us) is done with this connection too... - Disconnect(); -} - -void EQWHTTPHandler::OnHeader(const std::string& key,const std::string& value) { - HttpdSocket::OnHeader(key, value); - - if (!strcasecmp(key.c_str(),"Authorization")) { - if(strncasecmp(value.c_str(), "Basic ", 6)) { - printf("Invalid auth type. Expected Basic: %s\n", value.c_str()); - return; - } - - std::string dec; - Base64::decode(value.c_str() + 6, dec); - - std::string::size_type cpos; - cpos = dec.find_first_of(':'); - if(cpos == std::string::npos) { - printf("Invalid auth string: %s\n", dec.c_str()); - return; - } - - m_username = dec.substr(0, cpos); - m_password = dec.substr(cpos+1); - } -} - -//we should prolly cache login info here... if we load a fresh page, we could be checking -//their auth dozens of times rather quickly... -bool EQWHTTPHandler::CheckAuth() const { - if(m_username.length() < 1) - return(false); - - int16 status = 0; - uint32 acctid = database.CheckLogin(m_username.c_str(), m_password.c_str(), &status); - if(acctid == 0) { - Log.Out(Logs::Detail, Logs::World_Server, "Login autentication failed for %s with '%s'", m_username.c_str(), m_password.c_str()); - return(false); - } - if(status < httpLoginStatus) { - Log.Out(Logs::Detail, Logs::World_Server, "Login of %s failed: status too low.", m_username.c_str()); - return(false); - } - - return(true); -} - -void EQWHTTPHandler::SendPage(const std::string &file) { - - std::string path = "templates/"; - path += file; - - FILE *f = fopen(path.c_str(), "rb"); - if(f == nullptr) { - SendResponse("404", "Not Found"); - SendString("Not found."); - printf("%s not found.\n", file.c_str()); - return; - } - - std::string type = s_mime.GetMimeFromFilename(file); - AddResponseHeader("Content-type", type); - - bool process = false; -#ifdef EMBPERL - if(type == "text/html") - process = true; - else { - //not processing, send headers right away -#endif - SendResponse("200", "OK"); -#ifdef EMBPERL - } -#endif - - auto buffer = new char[READ_BUFFER_LEN + 1]; - size_t len; - std::string to_process; - while((len = fread(buffer, 1, READ_BUFFER_LEN, f)) > 0) { - buffer[len] = '\0'; - if(process) - to_process += buffer; - else - SendBuf(buffer, len); - } - delete[] buffer; - fclose(f); -#ifdef EMBPERL - if(process) { - //convert the base form into a useful perl exportable form - HTTPRequest req(this, GetHttpForm()); - GetParser()->SetHTTPRequest("testing", &req); - - //parse out the page and potentially pass some stuff on to perl. - ProcessAndSend(to_process); - - //clear out the form, just in case (since it gets destroyed next) - GetParser()->SetHTTPRequest("testing", nullptr); - } -#endif -} - -bool EQWHTTPHandler::LoadMimeTypes(const char *filename) { - return(s_mime.LoadMimeFile(filename)); -} - -#ifdef EMBPERL -void EQWHTTPHandler::ProcessAndSend(const std::string &str) { - std::string::size_type len = str.length(); - std::string::size_type start = 0; - std::string::size_type pos, end; - - while((pos = str.find("", pos+2); - if(end == std::string::npos) { - //terminal ?> not found... should issue a warning or something... - std::string scriptBody = str.substr(pos+2); - ProcessScript(scriptBody); - start = len; - break; - } else { - //script only consumes some of this buffer... - std::string scriptBody = str.substr(pos+2, end-pos-2); - ProcessScript(scriptBody); - start = end + 2; - } - } - - //send whatever is left over - if(start != len) - ProcessText(str.c_str() + start, len-start); -} - -void EQWHTTPHandler::ProcessScript(const std::string &script_body) { - const char *script = script_body.c_str(); - if(strcmp("perl", script) == 0) - script += 4; //allow EQW_eval("testing", script_body.c_str()); - const std::string &res = EQW::Singleton()->GetOutput(); - if(!res.empty()) { - ProcessText(res.c_str(), res.length()); - EQW::Singleton()->ClearOutput(); - } -} - -void EQWHTTPHandler::ProcessText(const char *txt, int len) { - if(!m_sentHeaders) { - SendResponse(m_responseCode, "OK"); - m_sentHeaders = true; - } - SendBuf(txt, len); -} -#endif - - -EQWHTTPServer::EQWHTTPServer() -: m_port(0) -{ -} - -void EQWHTTPServer::CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) { - auto conn = new EQWHTTPHandler(ID, in_socket, irIP, irPort); - AddConnection(conn); -} - -void EQWHTTPServer::Stop() { - Log.Out(Logs::Detail, Logs::World_Server, "Requesting that HTTP Service stop."); - m_running = false; - Close(); -} - -bool EQWHTTPServer::Start(uint16 port, const char *mime_file) { - if(m_running) { - Log.Out(Logs::Detail, Logs::World_Server, "HTTP Service is already running on port %d", m_port); - return(false); - } - - //load up our nice mime types - if(!EQWHTTPHandler::LoadMimeTypes(mime_file)) { - Log.Out(Logs::Detail, Logs::World_Server, "Failed to load mime types from '%s'", mime_file); - return(false); - } else { - Log.Out(Logs::Detail, Logs::World_Server, "Loaded mime types from %s", mime_file); - } - - //fire up the server thread - char errbuf[TCPServer_ErrorBufferSize]; - if(!Open(port, errbuf)) { - Log.Out(Logs::Detail, Logs::World_Server, "Unable to bind to port %d for HTTP service: %s", port, errbuf); - return(false); - } - - m_running = true; - m_port = port; - - /* - -#ifdef _WINDOWS - _beginthread(ThreadProc, 0, this); -#else - pthread_create(&m_thread, nullptr, ThreadProc, this); -#endif*/ - - return(true); -} - -/* -void EQWHTTPServer::Run() { - Log.LogDebugType(Logs::Detail, Logs::World_Server, "HTTP Processing thread started on port %d", m_port); - do { -#warning DELETE THIS IF YOU DONT USE IT - Sleep(10); - } while(m_running); - Log.LogDebugType(Logs::Detail, Logs::World_Server, "HTTP Processing thread terminating on port %d", m_port); -} - -ThreadReturnType EQWHTTPServer::ThreadProc(void *data) { - ((EQWHTTPServer *) data)->Run(); - THREAD_RETURN(nullptr); -}*/ - diff --git a/world/eqw_http_handler.h b/world/eqw_http_handler.h deleted file mode 100644 index 0545adb42..000000000 --- a/world/eqw_http_handler.h +++ /dev/null @@ -1,98 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 EQWHTTPHandler_H -#define EQWHTTPHandler_H - -#include "../common/tcp_server.h" -#include "../common/tcp_connection.h" -#include "../common/SocketLib/HttpdSocket.h" -#include "../common/SocketLib/Mime.h" -#include "../common/types.h" - -class EQWParser; - -class EQWHTTPHandler : public HttpdSocket { - static const int READ_BUFFER_LEN; -public: - EQWHTTPHandler(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort); - virtual ~EQWHTTPHandler(); - - void SetResponseCode(const char *code) { m_responseCode = code; } - - //HttpdSocket interface: - virtual void Exec(); - virtual void OnHeader(const std::string& key,const std::string& value); - - static bool LoadMimeTypes(const char *filename); -protected: - bool CheckAuth() const; - void SendPage(const std::string &file); - - //credentials - std::string m_username; - std::string m_password; - - bool m_closeOnFinish; - std::string m_responseCode; - bool m_sentHeaders; - - - //our mime type manager - static Mime s_mime; - - -#ifdef EMBPERL - void ProcessAndSend(const std::string &entire_html_page); - void ProcessScript(const std::string &script_body); - void ProcessText(const char *txt, int len); - - static EQWParser *GetParser(); - -private: - static EQWParser *s_parser; -#endif -}; - -class EQWHTTPServer : protected TCPServer { -public: - EQWHTTPServer(); - - bool Start(uint16 port, const char *mime_file); - void Stop(); - - -protected: - volatile bool m_running; - uint16 m_port; - - virtual void CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort); - -/* //I decided to put this into its own thread so that the HTTP pages - //cannot block the main world server's operation. - static ThreadReturnType ThreadProc(void* tmp); - void Run(); - - - -#ifndef WIN32 - pthread_t m_thread; -#endif*/ -}; - -#endif - diff --git a/world/eqw_parser.cpp b/world/eqw_parser.cpp deleted file mode 100644 index e01f3db3b..000000000 --- a/world/eqw_parser.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 -*/ - -//a lot of this is copied from embperl.cpp, but I didnt feel like factoring the common stuff out - -#ifdef EMBPERL - -#include "../common/global_define.h" -#include "eqw_parser.h" -#include "eqw.h" -#include "../common/eqdb.h" - -#include "worlddb.h" - -#ifndef GvCV_set -#define GvCV_set(gv,cv) (GvCV(gv) = (cv)) -#endif - -XS(XS_EQWIO_PRINT); - -//so embedded scripts can use xs extensions (ala 'use socket;') -EXTERN_C void boot_DynaLoader(pTHX_ CV* cv); -EXTERN_C XS(boot_EQW); -EXTERN_C XS(boot_EQDB); -EXTERN_C XS(boot_EQDBRes); -EXTERN_C XS(boot_HTTPRequest); -EXTERN_C XS(boot_EQLConfig); - -EXTERN_C void xs_init(pTHX) -{ - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = '\0'; - - char buf[128]; //shouldent have any function names longer than this. - - //add the strcpy stuff to get rid of const warnings.... - - newXS(strcpy(buf, "DynaLoader::boot_DynaLoader"), boot_DynaLoader, file); - newXS(strcpy(buf, "EQW::boot_EQW"), boot_EQW, file); - newXS(strcpy(buf, "EQDB::boot_EQDB"), boot_EQDB, file); - newXS(strcpy(buf, "EQDBRes::boot_EQDBRes"), boot_EQDBRes, file); - newXS(strcpy(buf, "HTTPRequest::boot_HTTPRequest"), boot_HTTPRequest, file); - newXS(strcpy(buf, "EQLConfig::boot_EQLConfig"), boot_EQLConfig, file); - newXS(strcpy(buf, "EQWIO::PRINT"), XS_EQWIO_PRINT, file); -} - -EQWParser::EQWParser() { - //setup perl... - my_perl = perl_alloc(); - _empty_sv = newSV(0); - if(!my_perl) - Log.Out(Logs::Detail, Logs::World_Server, "Error: perl_alloc failed!"); - else - DoInit(); -} - -void EQWParser::DoInit() { - const char *argv_eqemu[] = { "", - "-w", "-W", - "-e", "0;", nullptr }; - - int argc = 5; - - char **argv = (char **)argv_eqemu; - char **env = { nullptr }; - - PL_perl_destruct_level = 1; - - perl_construct(my_perl); - - PERL_SYS_INIT3(&argc, &argv, &env); - - perl_parse(my_perl, xs_init, argc, argv, env); - - perl_run(my_perl); - - //a little routine we use a lot. - eval_pv("sub my_eval {eval $_[0];}", TRUE); //dies on error - - //ruin the perl exit and command: - eval_pv("sub my_exit {}",TRUE); - eval_pv("sub my_sleep {}",TRUE); - if(gv_stashpv("CORE::GLOBAL", FALSE)) { - GV *exitgp = gv_fetchpv("CORE::GLOBAL::exit", TRUE, SVt_PVCV); - GvCV_set(exitgp, perl_get_cv("my_exit", TRUE)); //dies on error - GvIMPORTED_CV_on(exitgp); - GV *sleepgp = gv_fetchpv("CORE::GLOBAL::sleep", TRUE, SVt_PVCV); - GvCV_set(sleepgp, perl_get_cv("my_sleep", TRUE)); //dies on error - GvIMPORTED_CV_on(sleepgp); - } - - //setup eval_file - eval_pv( - "our %Cache;" - "use Symbol qw(delete_package);" - "sub eval_file {" - "my($package, $filename) = @_;" - "$filename=~s/\'//g;" - "if(! -r $filename) { print \"Unable to read perl file '$filename'\\n\"; return; }" - "my $mtime = -M $filename;" - "if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){" - " return;" - "} else {" - //we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here. - " eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require '$filename'; \");" - "}" - "}" - ,FALSE); - - //make a tie-able class to capture IO and get it where it needs to go - eval_pv( - "package EQWIO; " -// "&boot_EQEmuIO;" - "sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '.$me); return($me); } " - "sub WRITE { } " - "sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } " - "sub CLOSE { my $me = shift; $me->PRINT('Closing '.$me); } " - "sub DESTROY { my $me = shift; $me->PRINT('Destroying '.$me); } " -//this ties us for all packages - "package MAIN;" - " if(tied *STDOUT) { untie(*STDOUT); }" - " if(tied *STDERR) { untie(*STDERR); }" - " tie *STDOUT, 'EQWIO';" - " tie *STDERR, 'EQWIO';" - ,FALSE); - - eval_pv( - "package world; " - ,FALSE - ); - - //make sure the EQW pointer is set up in this package - EQW *curc = EQW::Singleton(); - SV *l = get_sv("world::EQW", true); - if(curc != nullptr) { - sv_setref_pv(l, "EQW", curc); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l, _empty_sv); - } - - //make sure the EQDB pointer is set up in this package - EQDB::SetMySQL(database.getMySQL()); - EQDB *curc_db = EQDB::Singleton(); - SV *l_db = get_sv("world::EQDB", true); - if(curc_db != nullptr) { - sv_setref_pv(l_db, "EQDB", curc_db); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l_db, _empty_sv); - } - - //load up EQW - eval_pv( - "package EQW;" - "&boot_EQW;" //load our EQW XS - "package EQDB;" - "&boot_EQDB;" //load our EQW XS - "package EQDBRes;" - "&boot_EQDBRes;" //load our EQW XS - "package HTTPRequest;" - "&boot_HTTPRequest;" //load our HTTPRequest XS - "package EQLConfig;" - "&boot_EQLConfig;" //load our EQLConfig XS - , FALSE ); - - -#ifdef EMBPERL_PLUGIN - Log.Out(Logs::Detail, Logs::World_Server, "Loading worldui perl plugins."); - std::string err; - if(!eval_file("world", "worldui.pl", err)) { - Log.Out(Logs::Detail, Logs::World_Server, "Warning - world.pl: %s", err.c_str()); - } - - eval_pv( - "package world; " - "if(opendir(D,'worldui')) { " - " my @d = readdir(D);" - " closedir(D);" - " foreach(@d){ " - " next unless(/\\.pl$); " - " require 'templates/'.$_;" - " }" - "}" - ,FALSE); -#endif //EMBPERL_PLUGIN -} - -EQWParser::~EQWParser() { - //removed to try to stop perl from exploding on reload, we'll see -/* eval_pv( - "package quest;" - " untie *STDOUT;" - " untie *STDERR;" - ,FALSE); -*/ - perl_free(my_perl); -} - -bool EQWParser::eval_file(const char * packagename, const char * filename, std::string &error) -{ - std::vector args; - args.push_back(packagename); - args.push_back(filename); - return(dosub("eval_file", args, error)); -} - -bool EQWParser::dosub(const char * subname, const std::vector &args, std::string &error, int mode) { - bool err = false; - dSP; // initialize stack pointer - ENTER; // everything created after here - SAVETMPS; // ...is a temporary variable - PUSHMARK(SP); // remember the stack pointer - if(!args.empty()) - { - for (auto i = args.begin(); i != args.end(); ++i) { /* push the arguments onto the perl stack */ - XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length()))); - } - } - PUTBACK; // make local stack pointer global - call_pv(subname, mode); /*eval our code*/ - SPAGAIN; // refresh stack pointer - if(SvTRUE(ERRSV)) { - err = true; - } - FREETMPS; // free temp values - LEAVE; // ...and the XPUSHed "mortal" args. - - if(err) { - error = "Perl runtime error: "; - error += SvPVX(ERRSV); - return(false); - } - return(true); -} - -bool EQWParser::eval(const char * code, std::string &error) { - std::vector arg; - arg.push_back(code); - return(dosub("my_eval", arg, error, G_SCALAR|G_DISCARD|G_EVAL|G_KEEPERR)); -} - -void EQWParser::EQW_eval(const char *pkg, const char *code) { - char namebuf[64]; - - snprintf(namebuf, 64, "package %s;", pkg); - eval_pv(namebuf, FALSE); - - //make sure the EQW pointer is set up - EQW *curc = EQW::Singleton(); - snprintf(namebuf, 64, "EQW"); -// snprintf(namebuf, 64, "%s::EQW", pkg); - SV *l = get_sv(namebuf, true); - if(curc != nullptr) { - sv_setref_pv(l, "EQW", curc); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l, _empty_sv); - } - //make sure the EQDB pointer is set up - EQDB *curc_db = EQDB::Singleton(); - snprintf(namebuf, 64, "EQDB"); -// snprintf(namebuf, 64, "%s::EQW", pkg); - SV *l_db = get_sv(namebuf, true); - if(curc_db != nullptr) { - sv_setref_pv(l_db, "EQDB", curc_db); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l_db, _empty_sv); - } - - std::string err; - if(!eval(code, err)) { - EQW::Singleton()->AppendOutput(err.c_str()); - } -} - -void EQWParser::SetHTTPRequest(const char *pkg, HTTPRequest *it) { - char namebuf[64]; - - snprintf(namebuf, 64, "package %s;", pkg); - eval_pv(namebuf, FALSE); - - snprintf(namebuf, 64, "request"); -// snprintf(namebuf, 64, "%s::EQW", pkg); - SV *l = get_sv(namebuf, true); - if(it != nullptr) { - sv_setref_pv(l, "HTTPRequest", it); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l, _empty_sv); - } - -} -/* -$editors = array(); -$editors["merchant"] = new MerchantEditor(); -#... for other editors - -if(defined($editors[$editor])) { - $edit = $editors[$editor]; - $edit->dispatch($action); -} - -class MerchantEditor extends BaseEditor { - MerchantEditor() { - $this->RegisterAction(0, "get_merchantlist", "merchant/merchant.tmpl.php", "no"); - $this->RegisterAction(1, "get_merchantlist", "merchant/merchant.edit.tmpl.php", "no"); - } -} - -function dispatch() { - my $dispatcher = $this->_dispatchers[$action]; - $body = new Template($dispatcher["template"]); - my $proc = $dispatcher["proc"]; - $vars = $this->$proc(); - if($dispatcher["guestmode"] == "no") { - check_authorization(); - } - if ($vars) { - foreach ($vars as $key=>$value) { - $body->set($key, $value); - } - } -} - -*/ - -#endif //EMBPERL - diff --git a/world/eqw_parser.h b/world/eqw_parser.h deleted file mode 100644 index 564ea0b11..000000000 --- a/world/eqw_parser.h +++ /dev/null @@ -1,72 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 EQWPARSER_H_ -#define EQWPARSER_H_ - - - -#ifdef EMBPERL - -#include -#include -#include -#include -#include - -#include "../common/useperl.h" - -class HTTPRequest; - -class EQWParser { -public: - EQWParser(); - ~EQWParser(); - - void EQW_eval(const char *pkg, const char *code); - void SetHTTPRequest(const char *pkg, HTTPRequest *it); - - //put an integer into a perl varable - void seti(const char *varname, int val) const { - SV *t = get_sv(varname, true); - sv_setiv(t, val); - } - //put a real into a perl varable - void setd(const char *varname, float val) const { - SV *t = get_sv(varname, true); - sv_setnv(t, val); - } - //put a string into a perl varable - void setstr(const char *varname, const char *val) const { - SV *t = get_sv(varname, true); - sv_setpv(t, val); - } - -protected: - void DoInit(); - bool eval(const char * code, std::string &error); - bool dosub(const char * subname, const std::vector &args, std::string &error, int mode = G_SCALAR|G_DISCARD|G_EVAL); - bool eval_file(const char * packagename, const char * filename, std::string &error); - - //the embedded interpreter - PerlInterpreter * my_perl; - SV *_empty_sv; -}; -#endif //EMBPERL - -#endif /*EQWPARSER_H_*/ - diff --git a/world/launcher_link.cpp b/world/launcher_link.cpp index c6cc4d56a..8b1e94446 100644 --- a/world/launcher_link.cpp +++ b/world/launcher_link.cpp @@ -24,8 +24,8 @@ #include "../common/md5.h" #include "../common/packet_dump.h" #include "../common/servertalk.h" -#include "../common/emu_tcp_connection.h" #include "../common/string_util.h" +#include "../common/misc_functions.h" #include "worlddb.h" #include "eql_config.h" diff --git a/world/login_server.cpp b/world/login_server.cpp index 5fe555d25..b2a0a1bae 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -23,6 +23,7 @@ #include #include "../common/version.h" #include "../common/servertalk.h" +#include "../common/misc_functions.h" #include "login_server.h" #include "login_server_list.h" #include "../common/eq_packet_structs.h" @@ -166,7 +167,7 @@ bool LoginServer::Connect() { return false; } - char errbuf[TCPConnection_ErrorBufferSize]; + char errbuf[1024]; if ((LoginServerIP = ResolveIP(LoginServerAddress, errbuf)) == 0) { Log.Out(Logs::Detail, Logs::World_Server, "Unable to resolve '%s' to an IP.",LoginServerAddress); return false; diff --git a/world/login_server_list.h b/world/login_server_list.h index 3791803cb..05bff76d5 100644 --- a/world/login_server_list.h +++ b/world/login_server_list.h @@ -7,7 +7,6 @@ #include "../common/queue.h" #include "../common/eq_packet_structs.h" #include "../common/mutex.h" -#include "../common/emu_tcp_connection.h" class LoginServer; diff --git a/world/net.cpp b/world/net.cpp index 23231fd8b..1154c9366 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -21,10 +21,8 @@ #include #include #include - #include -#include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "../common/queue.h" #include "../common/timer.h" @@ -67,14 +65,11 @@ #endif -#include "../common/emu_tcp_server.h" #include "../common/patches/patches.h" #include "../common/random.h" #include "zoneserver.h" -#include "console.h" #include "login_server.h" #include "login_server_list.h" -#include "eqw_http_handler.h" #include "world_config.h" #include "zoneserver.h" #include "zonelist.h" @@ -85,16 +80,15 @@ #include "adventure_manager.h" #include "ucs.h" #include "queryserv.h" +#include "web_interface.h" #include "../common/net/tcp_server.h" #include "../common/net/servertalk_server.h" -EmuTCPServer tcps; ClientList client_list; GroupLFPList LFPGroupList; ZSList zoneserver_list; LoginServerList loginserverlist; -EQWHTTPServer http_server; UCSConnection UCSLink; QueryServConnection QSLink; LauncherList launcher_list; @@ -106,6 +100,7 @@ uint32 numzones = 0; bool holdzones = false; const WorldConfig *Config; EQEmuLogSys Log; +WebInterfaceList web_interface; void CatchSignal(int sig_num); @@ -130,22 +125,21 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::World_Server, "Loading server configuration failed."); return 1; } - Config=WorldConfig::get(); + + Config = WorldConfig::get(); Log.Out(Logs::General, Logs::World_Server, "CURRENT_VERSION: %s", CURRENT_VERSION); - #ifdef _DEBUG - _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); - #endif - if (signal(SIGINT, CatchSignal) == SIG_ERR) { Log.Out(Logs::General, Logs::World_Server, "Could not set signal handler"); return 1; } + if (signal(SIGTERM, CatchSignal) == SIG_ERR) { Log.Out(Logs::General, Logs::World_Server, "Could not set signal handler"); return 1; } + #ifndef WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { Log.Out(Logs::General, Logs::World_Server, "Could not set signal handler"); @@ -281,13 +275,6 @@ int main(int argc, char** argv) { } } - if(Config->WorldHTTPEnabled) { - Log.Out(Logs::General, Logs::World_Server, "Starting HTTP world service..."); - http_server.Start(Config->WorldHTTPPort, Config->WorldHTTPMimeFile.c_str()); - } else { - Log.Out(Logs::General, Logs::World_Server, "HTTP world service disabled."); - } - if(!ignore_db) { Log.Out(Logs::General, Logs::World_Server, "Checking Database Conversions.."); database.CheckDatabaseConversions(); @@ -445,12 +432,26 @@ int main(int argc, char** argv) { }); server_connection->OnConnectionRemoved("UCS", [](std::shared_ptr connection) { - Log.OutF(Logs::General, Logs::World_Server, "UCS Query Server connection from {0}", + Log.OutF(Logs::General, Logs::World_Server, "Removed Query Server connection from {0}", connection->GetUUID()); UCSLink.SetConnection(nullptr); }); + server_connection->OnConnectionIdentified("WebInterface", [](std::shared_ptr connection) { + Log.OutF(Logs::General, Logs::World_Server, "New WebInterface Server connection from {2} at {0}:{1}", + connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID()); + + web_interface.AddConnection(connection); + }); + + server_connection->OnConnectionRemoved("WebInterface", [](std::shared_ptr connection) { + Log.OutF(Logs::General, Logs::World_Server, "Removed WebInterface Server connection from {0}", + connection->GetUUID()); + + web_interface.RemoveConnection(connection); + }); + EQ::Net::EQStreamManagerOptions opts(9000, false, false); EQ::Net::EQStreamManager eqsm(opts); @@ -538,9 +539,7 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::World_Server, "Shutting down zone connections (if any)."); zoneserver_list.KillAll(); Log.Out(Logs::General, Logs::World_Server, "Zone (TCP) listener stopped."); - //tcps.Close(); Log.Out(Logs::General, Logs::World_Server, "Signaling HTTP service to stop..."); - http_server.Stop(); Log.CloseFileLogs(); return 0; diff --git a/world/perl_eql_config.cpp b/world/perl_eql_config.cpp deleted file mode 100644 index 7cd7d0e2a..000000000 --- a/world/perl_eql_config.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* -* This file was generated automatically by xsubpp version 1.9508 from the -* contents of tmp. Do not edit this file, edit tmp instead. -* -* ANY CHANGES MADE HERE WILL BE LOST! -* -*/ - - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 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 -*/ - -typedef const char Const_char; - -#ifdef EMBPERL -#include "../common/global_define.h" -#include "eqw_parser.h" -#include "eql_config.h" - -#ifdef seed -#undef seed -#endif - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -XS(XS_EQLConfig_GetName); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_GetName) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQLConfig::GetName(THIS)"); - { - EQLConfig * THIS; - Const_char * RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetName(); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_EQLConfig_GetStaticCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_GetStaticCount) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQLConfig::GetStaticCount(THIS)"); - { - EQLConfig * THIS; - int RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetStaticCount(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_EQLConfig_IsConnected); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_IsConnected) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQLConfig::IsConnected(THIS)"); - { - EQLConfig * THIS; - bool RETVAL; - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->IsConnected(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQLConfig_DeleteLauncher); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_DeleteLauncher) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQLConfig::DeleteLauncher(THIS)"); - { - EQLConfig * THIS; - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->DeleteLauncher(); - } - XSRETURN_EMPTY; -} - -XS(XS_EQLConfig_RestartZone); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_RestartZone) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQLConfig::RestartZone(THIS, zone_ref)"); - { - EQLConfig * THIS; - Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1)); - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->RestartZone(zone_ref); - } - XSRETURN_EMPTY; -} - -XS(XS_EQLConfig_StopZone); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_StopZone) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQLConfig::StopZone(THIS, zone_ref)"); - { - EQLConfig * THIS; - Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1)); - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->StopZone(zone_ref); - } - XSRETURN_EMPTY; -} - -XS(XS_EQLConfig_StartZone); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_StartZone) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQLConfig::StartZone(THIS, zone_ref)"); - { - EQLConfig * THIS; - Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1)); - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->StartZone(zone_ref); - } - XSRETURN_EMPTY; -} - -XS(XS_EQLConfig_BootStaticZone); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_BootStaticZone) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQLConfig::BootStaticZone(THIS, short_name, port)"); - { - EQLConfig * THIS; - bool RETVAL; - Const_char * short_name = (Const_char *)SvPV_nolen(ST(1)); - uint16 port = (uint16)SvUV(ST(2)); - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->BootStaticZone(short_name, port); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQLConfig_ChangeStaticZone); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_ChangeStaticZone) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQLConfig::ChangeStaticZone(THIS, short_name, port)"); - { - EQLConfig * THIS; - bool RETVAL; - Const_char * short_name = (Const_char *)SvPV_nolen(ST(1)); - uint16 port = (uint16)SvUV(ST(2)); - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->ChangeStaticZone(short_name, port); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQLConfig_DeleteStaticZone); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_DeleteStaticZone) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQLConfig::DeleteStaticZone(THIS, short_name)"); - { - EQLConfig * THIS; - bool RETVAL; - Const_char * short_name = (Const_char *)SvPV_nolen(ST(1)); - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->DeleteStaticZone(short_name); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQLConfig_SetDynamicCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_SetDynamicCount) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQLConfig::SetDynamicCount(THIS, count)"); - { - EQLConfig * THIS; - bool RETVAL; - int count = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->SetDynamicCount(count); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQLConfig_GetDynamicCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_GetDynamicCount) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQLConfig::GetDynamicCount(THIS)"); - { - EQLConfig * THIS; - int RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetDynamicCount(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_EQLConfig_ListZones); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_ListZones) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQLConfig::ListZones(THIS)"); - { - EQLConfig * THIS; - std::vector RETVAL; - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->ListZones(); - ST(0) = sv_newmortal(); - { - U32 ix_RETVAL; - /* pop crap off the stack we dont really want */ - POPs; - POPs; - /* grow the stack to the number of elements being returned */ - EXTEND(SP, RETVAL.size()); - for (ix_RETVAL = 0; ix_RETVAL < RETVAL.size(); ix_RETVAL++) { - const std::string &it = RETVAL[ix_RETVAL]; - ST(ix_RETVAL) = sv_newmortal(); - sv_setpvn(ST(ix_RETVAL), it.c_str(), it.length()); - } - /* hackish, but im over it. The normal xsubpp return will be right below this */ - XSRETURN(RETVAL.size()); - } - } - XSRETURN(1); -} - -XS(XS_EQLConfig_GetZoneDetails); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQLConfig_GetZoneDetails) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQLConfig::GetZoneDetails(THIS, zone_ref)"); - { - EQLConfig * THIS; - std::map RETVAL; - Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1)); - - if (sv_derived_from(ST(0), "EQLConfig")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(EQLConfig *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type EQLConfig"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetZoneDetails(zone_ref); - ST(0) = sv_newmortal(); - if (RETVAL.begin()!=RETVAL.end()) - { - //NOTE: we are leaking the original ST(0) right now - HV *hv = newHV(); - sv_2mortal((SV*)hv); - ST(0) = newRV((SV*)hv); - - std::map::const_iterator cur, end; - cur = RETVAL.begin(); - end = RETVAL.end(); - for(; cur != end; cur++) { - /* get the element from the hash, creating if needed (will be needed) */ - SV**ele = hv_fetch(hv, cur->first.c_str(), cur->first.length(), TRUE); - if(ele == nullptr) { - Perl_croak(aTHX_ "Unable to create a hash element for RETVAL"); - break; - } - /* put our string in the SV associated with this element in the hash */ - sv_setpvn(*ele, cur->second.c_str(), cur->second.length()); - } - } - } - XSRETURN(1); -} - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_EQLConfig); /* prototype to pass -Wmissing-prototypes */ -XS(boot_EQLConfig) -{ - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if(items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK ; - - newXSproto(strcpy(buf, "GetName"), XS_EQLConfig_GetName, file, "$"); - newXSproto(strcpy(buf, "GetStaticCount"), XS_EQLConfig_GetStaticCount, file, "$"); - newXSproto(strcpy(buf, "IsConnected"), XS_EQLConfig_IsConnected, file, "$"); - newXSproto(strcpy(buf, "DeleteLauncher"), XS_EQLConfig_DeleteLauncher, file, "$"); - newXSproto(strcpy(buf, "RestartZone"), XS_EQLConfig_RestartZone, file, "$$"); - newXSproto(strcpy(buf, "StopZone"), XS_EQLConfig_StopZone, file, "$$"); - newXSproto(strcpy(buf, "StartZone"), XS_EQLConfig_StartZone, file, "$$"); - newXSproto(strcpy(buf, "BootStaticZone"), XS_EQLConfig_BootStaticZone, file, "$$$"); - newXSproto(strcpy(buf, "ChangeStaticZone"), XS_EQLConfig_ChangeStaticZone, file, "$$$"); - newXSproto(strcpy(buf, "DeleteStaticZone"), XS_EQLConfig_DeleteStaticZone, file, "$$"); - newXSproto(strcpy(buf, "SetDynamicCount"), XS_EQLConfig_SetDynamicCount, file, "$$"); - newXSproto(strcpy(buf, "GetDynamicCount"), XS_EQLConfig_GetDynamicCount, file, "$"); - newXSproto(strcpy(buf, "ListZones"), XS_EQLConfig_ListZones, file, "$"); - newXSproto(strcpy(buf, "GetZoneDetails"), XS_EQLConfig_GetZoneDetails, file, "$$"); - XSRETURN_YES; -} - -#endif //EMBPERL_XS_CLASSES - diff --git a/world/perl_eqw.cpp b/world/perl_eqw.cpp deleted file mode 100644 index 27b937721..000000000 --- a/world/perl_eqw.cpp +++ /dev/null @@ -1,1020 +0,0 @@ -/* -* This file was generated automatically by xsubpp version 1.9508 from the -* contents of tmp. Do not edit this file, edit tmp instead. -* -* ANY CHANGES MADE HERE WILL BE LOST! -* -*/ - - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 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 -*/ - -typedef const char Const_char; - -#ifdef EMBPERL -#include "../common/global_define.h" -#include "eqw_parser.h" -#include "eqw.h" - -#ifdef seed -#undef seed -#endif - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -XS(XS_EQW_GetConfig); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_GetConfig) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::GetConfig(THIS, var_name)"); - { - EQW * THIS; - Const_char * RETVAL; - dXSTARG; - Const_char * var_name = (Const_char *)SvPV_nolen(ST(1)); - - 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."); - - RETVAL = THIS->GetConfig(var_name); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_EQW_LockWorld); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_LockWorld) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQW::LockWorld(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->LockWorld(); - } - XSRETURN_EMPTY; -} - -XS(XS_EQW_UnlockWorld); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_UnlockWorld) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQW::UnlockWorld(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->UnlockWorld(); - } - XSRETURN_EMPTY; -} - -XS(XS_EQW_LSConnected); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_LSConnected) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQW::LSConnected(THIS)"); - { - EQW * THIS; - bool RETVAL; - - 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."); - - RETVAL = THIS->LSConnected(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_CountZones); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_CountZones) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQW::CountZones(THIS)"); - { - EQW * THIS; - int RETVAL; - dXSTARG; - - 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."); - - RETVAL = THIS->CountZones(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_EQW_ListBootedZones); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_ListBootedZones) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQW::ListBootedZones(THIS)"); - { - EQW * THIS; - std::vector RETVAL; - - 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."); - - RETVAL = THIS->ListBootedZones(); - ST(0) = sv_newmortal(); - { - U32 ix_RETVAL; - /* pop crap off the stack we dont really want */ - POPs; - POPs; - /* grow the stack to the number of elements being returned */ - EXTEND(SP, RETVAL.size()); - for (ix_RETVAL = 0; ix_RETVAL < RETVAL.size(); ix_RETVAL++) { - const std::string &it = RETVAL[ix_RETVAL]; - ST(ix_RETVAL) = sv_newmortal(); - sv_setpvn(ST(ix_RETVAL), it.c_str(), it.length()); - } - /* hackish, but im over it. The normal xsubpp return will be right below this */ - XSRETURN(RETVAL.size()); - } - } - XSRETURN(1); -} - -XS(XS_EQW_GetZoneDetails); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_GetZoneDetails) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::GetZoneDetails(THIS, zone_ref)"); - { - EQW * THIS; - std::map RETVAL; - Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1)); - - 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."); - - RETVAL = THIS->GetZoneDetails(zone_ref); - ST(0) = sv_newmortal(); - if (RETVAL.begin()!=RETVAL.end()) - { - //NOTE: we are leaking the original ST(0) right now - HV *hv = newHV(); - sv_2mortal((SV*)hv); - ST(0) = newRV((SV*)hv); - - std::map::const_iterator cur, end; - cur = RETVAL.begin(); - end = RETVAL.end(); - for(; cur != end; cur++) { - /* get the element from the hash, creating if needed (will be needed) */ - SV**ele = hv_fetch(hv, cur->first.c_str(), cur->first.length(), TRUE); - if(ele == nullptr) { - Perl_croak(aTHX_ "Unable to create a hash element for RETVAL"); - break; - } - /* put our string in the SV associated with this element in the hash */ - sv_setpvn(*ele, cur->second.c_str(), cur->second.length()); - } - } - } - XSRETURN(1); -} - -XS(XS_EQW_CountPlayers); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_CountPlayers) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQW::CountPlayers(THIS)"); - { - EQW * THIS; - int RETVAL; - dXSTARG; - - 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."); - - RETVAL = THIS->CountPlayers(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_EQW_ListPlayers); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_ListPlayers) -{ - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: EQW::ListPlayers(THIS, zone_name= \"\")"); - { - EQW * THIS; - std::vector RETVAL; - Const_char * zone_name; - - 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."); - - if (items < 2) - zone_name = ""; - else { - zone_name = (Const_char *)SvPV_nolen(ST(1)); - } - - RETVAL = THIS->ListPlayers(zone_name); - ST(0) = sv_newmortal(); - { - U32 ix_RETVAL; - /* pop crap off the stack we dont really want */ - POPs; - POPs; - /* grow the stack to the number of elements being returned */ - EXTEND(SP, RETVAL.size()); - for (ix_RETVAL = 0; ix_RETVAL < RETVAL.size(); ix_RETVAL++) { - const std::string &it = RETVAL[ix_RETVAL]; - ST(ix_RETVAL) = sv_newmortal(); - sv_setpvn(ST(ix_RETVAL), it.c_str(), it.length()); - } - /* hackish, but im over it. The normal xsubpp return will be right below this */ - XSRETURN(RETVAL.size()); - } - } - XSRETURN(1); -} - -XS(XS_EQW_GetPlayerDetails); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_GetPlayerDetails) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::GetPlayerDetails(THIS, player_ref)"); - { - EQW * THIS; - std::map RETVAL; - Const_char * player_ref = (Const_char *)SvPV_nolen(ST(1)); - - 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."); - - RETVAL = THIS->GetPlayerDetails(player_ref); - ST(0) = sv_newmortal(); - if (RETVAL.begin()!=RETVAL.end()) - { - //NOTE: we are leaking the original ST(0) right now - HV *hv = newHV(); - sv_2mortal((SV*)hv); - ST(0) = newRV((SV*)hv); - - std::map::const_iterator cur, end; - cur = RETVAL.begin(); - end = RETVAL.end(); - for(; cur != end; cur++) { - /* get the element from the hash, creating if needed (will be needed) */ - SV**ele = hv_fetch(hv, cur->first.c_str(), cur->first.length(), TRUE); - if(ele == nullptr) { - Perl_croak(aTHX_ "Unable to create a hash element for RETVAL"); - break; - } - /* put our string in the SV associated with this element in the hash */ - sv_setpvn(*ele, cur->second.c_str(), cur->second.length()); - } - } - } - XSRETURN(1); -} - -XS(XS_EQW_CountLaunchers); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_CountLaunchers) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::CountLaunchers(THIS, active_only)"); - { - EQW * THIS; - int RETVAL; - dXSTARG; - bool active_only = (bool)SvTRUE(ST(1)); - - 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."); - - RETVAL = THIS->CountLaunchers(active_only); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_EQW_ListLaunchers); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_ListLaunchers) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQW::ListLaunchers(THIS)"); - { - EQW * THIS; - std::vector RETVAL; - - 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."); - - RETVAL = THIS->ListLaunchers(); - ST(0) = sv_newmortal(); - { - U32 ix_RETVAL; - /* pop crap off the stack we dont really want */ - POPs; - POPs; - /* grow the stack to the number of elements being returned */ - EXTEND(SP, RETVAL.size()); - for (ix_RETVAL = 0; ix_RETVAL < RETVAL.size(); ix_RETVAL++) { - const std::string &it = RETVAL[ix_RETVAL]; - ST(ix_RETVAL) = sv_newmortal(); - sv_setpvn(ST(ix_RETVAL), it.c_str(), it.length()); - } - /* hackish, but im over it. The normal xsubpp return will be right below this */ - XSRETURN(RETVAL.size()); - } - } - XSRETURN(1); -} - -XS(XS_EQW_GetLauncher); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_GetLauncher) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::GetLauncher(THIS, launcher_name)"); - { - EQW * THIS; - EQLConfig * RETVAL; - Const_char * launcher_name = (Const_char *)SvPV_nolen(ST(1)); - - 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."); - - RETVAL = THIS->GetLauncher(launcher_name); - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "EQLConfig", (void*)RETVAL); - } - XSRETURN(1); -} - -XS(XS_EQW_CreateLauncher); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_CreateLauncher) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::CreateLauncher(THIS, launcher_name, dynamic_count)"); - { - EQW * THIS; - Const_char * launcher_name = (Const_char *)SvPV_nolen(ST(1)); - int dynamic_count = (int)SvIV(ST(2)); - - 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->CreateLauncher(launcher_name, dynamic_count); - } - XSRETURN_EMPTY; -} - -XS(XS_EQW_CreateGuild); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_CreateGuild) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::CreateGuild(THIS, name, leader_char_id)"); - { - EQW * THIS; - uint32 RETVAL; - dXSTARG; - char* name = (char *)SvPV_nolen(ST(1)); - uint32 leader_char_id = (uint32)SvUV(ST(2)); - - 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."); - - RETVAL = THIS->CreateGuild(name, leader_char_id); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_EQW_DeleteGuild); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_DeleteGuild) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::DeleteGuild(THIS, guild_id)"); - { - EQW * THIS; - bool RETVAL; - uint32 guild_id = (uint32)SvUV(ST(1)); - - 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."); - - RETVAL = THIS->DeleteGuild(guild_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_RenameGuild); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_RenameGuild) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::RenameGuild(THIS, guild_id, name)"); - { - EQW * THIS; - bool RETVAL; - uint32 guild_id = (uint32)SvUV(ST(1)); - char* name = (char *)SvPV_nolen(ST(2)); - - 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."); - - RETVAL = THIS->RenameGuild(guild_id, name); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_SetGuildMOTD); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_SetGuildMOTD) -{ - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: EQW::SetGuildMOTD(THIS, guild_id, motd, setter)"); - { - EQW * THIS; - bool RETVAL; - uint32 guild_id = (uint32)SvUV(ST(1)); - char* motd = (char *)SvPV_nolen(ST(2)); - char * setter = (char *)SvPV_nolen(ST(3)); - - 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."); - - RETVAL = THIS->SetGuildMOTD(guild_id, motd, setter); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_SetGuildLeader); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_SetGuildLeader) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::SetGuildLeader(THIS, guild_id, leader_char_id)"); - { - EQW * THIS; - bool RETVAL; - uint32 guild_id = (uint32)SvUV(ST(1)); - uint32 leader_char_id = (uint32)SvUV(ST(2)); - - 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."); - - RETVAL = THIS->SetGuildLeader(guild_id, leader_char_id); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_SetGuild); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_SetGuild) -{ - dXSARGS; - if (items != 4) - Perl_croak(aTHX_ "Usage: EQW::SetGuild(THIS, charid, guild_id, rank)"); - { - EQW * THIS; - bool RETVAL; - uint32 charid = (uint32)SvUV(ST(1)); - uint32 guild_id = (uint32)SvUV(ST(2)); - uint8 rank = (uint8)SvUV(ST(3)); - - 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."); - - RETVAL = THIS->SetGuild(charid, guild_id, rank); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_SetGuildRank); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_SetGuildRank) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::SetGuildRank(THIS, charid, rank)"); - { - EQW * THIS; - bool RETVAL; - uint32 charid = (uint32)SvUV(ST(1)); - uint8 rank = (uint8)SvUV(ST(2)); - - 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."); - - RETVAL = THIS->SetGuildRank(charid, rank); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_SetBankerFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_SetBankerFlag) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::SetBankerFlag(THIS, charid, is_banker)"); - { - EQW * THIS; - bool RETVAL; - uint32 charid = (uint32)SvUV(ST(1)); - bool is_banker = (bool)SvTRUE(ST(2)); - - 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."); - - RETVAL = THIS->SetBankerFlag(charid, is_banker); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_SetTributeFlag); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_SetTributeFlag) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::SetTributeFlag(THIS, charid, enabled)"); - { - EQW * THIS; - bool RETVAL; - uint32 charid = (uint32)SvUV(ST(1)); - bool enabled = (bool)SvTRUE(ST(2)); - - 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."); - - RETVAL = THIS->SetTributeFlag(charid, enabled); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_SetPublicNote); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_SetPublicNote) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::SetPublicNote(THIS, charid, note)"); - { - EQW * THIS; - bool RETVAL; - uint32 charid = (uint32)SvUV(ST(1)); - char * note = (char *)SvPV_nolen(ST(2)); - - 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."); - - RETVAL = THIS->SetPublicNote(charid, note); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_EQW_CountBugs); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_CountBugs) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: EQW::CountBugs(THIS)"); - { - EQW * THIS; - int RETVAL; - dXSTARG; - - 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."); - - RETVAL = THIS->CountBugs(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_EQW_ListBugs); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_ListBugs) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::ListBugs(THIS, id)"); - { - EQW * THIS; - uint32 id = (uint32)SvUV(ST(1)); - std::vector RETVAL; - - - 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."); - - RETVAL = THIS->ListBugs(id); - ST(0) = sv_newmortal(); - { - U32 ix_RETVAL; - /* pop crap off the stack we dont really want */ - POPs; - POPs; - /* grow the stack to the number of elements being returned */ - EXTEND(SP, RETVAL.size()); - for (ix_RETVAL = 0; ix_RETVAL < RETVAL.size(); ix_RETVAL++) { - const std::string &it = RETVAL[ix_RETVAL]; - ST(ix_RETVAL) = sv_newmortal(); - sv_setpvn(ST(ix_RETVAL), it.c_str(), it.length()); - } - /* hackish, but im over it. The normal xsubpp return will be right below this */ - XSRETURN(RETVAL.size()); - } - } - XSRETURN(1); -} - -XS(XS_EQW_GetBugDetails); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_GetBugDetails) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::GetBugDetails(THIS, bug_ref)"); - { - EQW * THIS; - std::map RETVAL; - Const_char * bug_ref = (Const_char *)SvPV_nolen(ST(1)); - - 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."); - - RETVAL = THIS->GetBugDetails(bug_ref); - ST(0) = sv_newmortal(); - if (RETVAL.begin()!=RETVAL.end()) - { - //NOTE: we are leaking the original ST(0) right now - HV *hv = newHV(); - sv_2mortal((SV*)hv); - ST(0) = newRV((SV*)hv); - - std::map::const_iterator cur, end; - cur = RETVAL.begin(); - end = RETVAL.end(); - for(; cur != end; cur++) { - /* get the element from the hash, creating if needed (will be needed) */ - SV**ele = hv_fetch(hv, cur->first.c_str(), cur->first.length(), TRUE); - if(ele == nullptr) { - Perl_croak(aTHX_ "Unable to create a hash element for RETVAL"); - break; - } - /* put our string in the SV associated with this element in the hash */ - sv_setpvn(*ele, cur->second.c_str(), cur->second.length()); - } - } - } - XSRETURN(1); -} - -XS(XS_EQW_ResolveBug); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_ResolveBug) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: EQW::ResolveBug(THIS, id)"); - { - EQW * THIS; - const char *id = (const char*)SvPV_nolen(ST(1)); - - 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->ResolveBug(id); - } - XSRETURN_EMPTY; -} - -XS(XS_EQW_SendMessage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_SendMessage) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::SendMessage(THIS, type, message)"); - { - EQW * THIS; - dXSTARG; - uint32 msgtype = (uint32)SvUV(ST(1)); - char* msg = (char *)SvPV_nolen(ST(2)); - - 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 == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - THIS->SendMessage(msgtype, msg); - } - XSRETURN_EMPTY; -} - -XS(XS_EQW_WorldShutDown); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQW_WorldShutDown) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: EQW::WorldShutDown(THIS, time, interval)"); - { - EQW * THIS; - dXSTARG; - uint32 time = (uint32)SvUV(ST(1)); - uint32 interval = (uint32)SvUV(ST(2)); - - 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 == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - THIS->WorldShutDown(time, interval); - } - XSRETURN_EMPTY; -} - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_EQW); /* prototype to pass -Wmissing-prototypes */ -XS(boot_EQW) -{ - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if(items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK ; - - newXSproto(strcpy(buf, "GetConfig"), XS_EQW_GetConfig, file, "$$"); - 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, "CountZones"), XS_EQW_CountZones, file, "$"); - newXSproto(strcpy(buf, "ListBootedZones"), XS_EQW_ListBootedZones, file, "$"); - newXSproto(strcpy(buf, "GetZoneDetails"), XS_EQW_GetZoneDetails, file, "$$"); - newXSproto(strcpy(buf, "CountPlayers"), XS_EQW_CountPlayers, file, "$"); - newXSproto(strcpy(buf, "ListPlayers"), XS_EQW_ListPlayers, file, "$;$"); - newXSproto(strcpy(buf, "GetPlayerDetails"), XS_EQW_GetPlayerDetails, file, "$$"); - newXSproto(strcpy(buf, "CountLaunchers"), XS_EQW_CountLaunchers, file, "$$"); - newXSproto(strcpy(buf, "ListLaunchers"), XS_EQW_ListLaunchers, file, "$"); - newXSproto(strcpy(buf, "GetLauncher"), XS_EQW_GetLauncher, file, "$$"); - newXSproto(strcpy(buf, "CreateLauncher"), XS_EQW_CreateLauncher, file, "$$$"); - newXSproto(strcpy(buf, "CreateGuild"), XS_EQW_CreateGuild, file, "$$$"); - newXSproto(strcpy(buf, "DeleteGuild"), XS_EQW_DeleteGuild, file, "$$"); - newXSproto(strcpy(buf, "RenameGuild"), XS_EQW_RenameGuild, file, "$$$"); - newXSproto(strcpy(buf, "SetGuildMOTD"), XS_EQW_SetGuildMOTD, file, "$$$$"); - newXSproto(strcpy(buf, "SetGuildLeader"), XS_EQW_SetGuildLeader, file, "$$$"); - newXSproto(strcpy(buf, "SetGuild"), XS_EQW_SetGuild, file, "$$$$"); - newXSproto(strcpy(buf, "SetGuildRank"), XS_EQW_SetGuildRank, file, "$$$"); - newXSproto(strcpy(buf, "SetBankerFlag"), XS_EQW_SetBankerFlag, file, "$$$"); - newXSproto(strcpy(buf, "SetTributeFlag"), XS_EQW_SetTributeFlag, file, "$$$"); - newXSproto(strcpy(buf, "SetPublicNote"), XS_EQW_SetPublicNote, file, "$$$"); - newXSproto(strcpy(buf, "CountBugs"), XS_EQW_CountBugs, file, "$"); - newXSproto(strcpy(buf, "ListBugs"), XS_EQW_ListBugs, file, "$$"); - newXSproto(strcpy(buf, "GetBugDetails"), XS_EQW_GetBugDetails, file, "$$"); - newXSproto(strcpy(buf, "ResolveBug"), XS_EQW_ResolveBug, file, "$$"); - newXSproto(strcpy(buf, "SendMessage"), XS_EQW_SendMessage, file, "$$$"); - newXSproto(strcpy(buf, "WorldShutDown"), XS_EQW_WorldShutDown, file, "$$$"); - XSRETURN_YES; -} - -#endif //EMBPERL_XS_CLASSES - diff --git a/world/perl_http_request.cpp b/world/perl_http_request.cpp deleted file mode 100644 index cdd7e60f1..000000000 --- a/world/perl_http_request.cpp +++ /dev/null @@ -1,330 +0,0 @@ -/* -* This file was generated automatically by xsubpp version 1.9508 from the -* contents of tmp. Do not edit this file, edit tmp instead. -* -* ANY CHANGES MADE HERE WILL BE LOST! -* -*/ - - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 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 -*/ - -typedef const char Const_char; - -#ifdef EMBPERL -#include "../common/global_define.h" -#include "eqw_parser.h" -#include "http_request.h" - -#ifdef seed -#undef seed -#endif - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -XS(XS_HTTPRequest_get); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HTTPRequest_get) -{ - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: HTTPRequest::get(THIS, name, default_value= \"\")"); - { - HTTPRequest * THIS; - Const_char * RETVAL; - dXSTARG; - Const_char * name = (Const_char *)SvPV_nolen(ST(1)); - Const_char * default_value; - - if (sv_derived_from(ST(0), "HTTPRequest")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(HTTPRequest *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type HTTPRequest"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 3) - default_value = ""; - else { - default_value = (Const_char *)SvPV_nolen(ST(2)); - } - - RETVAL = THIS->get(name, default_value); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_HTTPRequest_getInt); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HTTPRequest_getInt) -{ - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: HTTPRequest::getInt(THIS, name, default_value= 0)"); - { - HTTPRequest * THIS; - int RETVAL; - dXSTARG; - Const_char * name = (Const_char *)SvPV_nolen(ST(1)); - int default_value; - - if (sv_derived_from(ST(0), "HTTPRequest")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(HTTPRequest *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type HTTPRequest"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 3) - default_value = 0; - else { - default_value = (int)SvIV(ST(2)); - } - - RETVAL = THIS->getInt(name, default_value); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_HTTPRequest_getFloat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HTTPRequest_getFloat) -{ - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: HTTPRequest::getFloat(THIS, name, default_value= 0.0)"); - { - HTTPRequest * THIS; - float RETVAL; - dXSTARG; - Const_char * name = (Const_char *)SvPV_nolen(ST(1)); - float default_value; - - if (sv_derived_from(ST(0), "HTTPRequest")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(HTTPRequest *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type HTTPRequest"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 3) - default_value = 0.0; - else { - default_value = (float)SvNV(ST(2)); - } - - RETVAL = THIS->getFloat(name, default_value); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_HTTPRequest_getEscaped); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HTTPRequest_getEscaped) -{ - dXSARGS; - if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: HTTPRequest::getEscaped(THIS, name, default_value= \"\")"); - { - HTTPRequest * THIS; - Const_char * RETVAL; - dXSTARG; - Const_char * name = (Const_char *)SvPV_nolen(ST(1)); - Const_char * default_value; - - if (sv_derived_from(ST(0), "HTTPRequest")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(HTTPRequest *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type HTTPRequest"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 3) - default_value = ""; - else { - default_value = (Const_char *)SvPV_nolen(ST(2)); - } - - RETVAL = THIS->getEscaped(name, default_value); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - -XS(XS_HTTPRequest_get_all); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HTTPRequest_get_all) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: HTTPRequest::get_all(THIS)"); - { - HTTPRequest * THIS; - std::map RETVAL; - - if (sv_derived_from(ST(0), "HTTPRequest")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(HTTPRequest *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type HTTPRequest"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->get_all(); - ST(0) = sv_newmortal(); - if (RETVAL.begin()!=RETVAL.end()) - { - //NOTE: we are leaking the original ST(0) right now - HV *hv = newHV(); - sv_2mortal((SV*)hv); - ST(0) = newRV((SV*)hv); - - std::map::const_iterator cur, end; - cur = RETVAL.begin(); - end = RETVAL.end(); - for(; cur != end; cur++) { - /* get the element from the hash, creating if needed (will be needed) */ - SV**ele = hv_fetch(hv, cur->first.c_str(), cur->first.length(), TRUE); - if(ele == nullptr) { - Perl_croak(aTHX_ "Unable to create a hash element for RETVAL"); - break; - } - /* put our string in the SV associated with this element in the hash */ - sv_setpvn(*ele, cur->second.c_str(), cur->second.length()); - } - } - } - XSRETURN(1); -} - -XS(XS_HTTPRequest_redirect); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HTTPRequest_redirect) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: HTTPRequest::redirect(THIS, URL)"); - { - HTTPRequest * THIS; - Const_char * URL = (Const_char *)SvPV_nolen(ST(1)); - - if (sv_derived_from(ST(0), "HTTPRequest")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(HTTPRequest *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type HTTPRequest"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->redirect(URL); - } - XSRETURN_EMPTY; -} - -XS(XS_HTTPRequest_SetResponseCode); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HTTPRequest_SetResponseCode) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: HTTPRequest::SetResponseCode(THIS, code)"); - { - HTTPRequest * THIS; - Const_char * code = (Const_char *)SvPV_nolen(ST(1)); - - if (sv_derived_from(ST(0), "HTTPRequest")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(HTTPRequest *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type HTTPRequest"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetResponseCode(code); - } - XSRETURN_EMPTY; -} - -XS(XS_HTTPRequest_header); /* prototype to pass -Wmissing-prototypes */ -XS(XS_HTTPRequest_header) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: HTTPRequest::header(THIS, name, value)"); - { - HTTPRequest * THIS; - Const_char * name = (Const_char *)SvPV_nolen(ST(1)); - Const_char * value = (Const_char *)SvPV_nolen(ST(2)); - - if (sv_derived_from(ST(0), "HTTPRequest")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(HTTPRequest *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type HTTPRequest"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->header(name, value); - } - XSRETURN_EMPTY; -} - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_HTTPRequest); /* prototype to pass -Wmissing-prototypes */ -XS(boot_HTTPRequest) -{ - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if(items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK ; - - newXSproto(strcpy(buf, "get"), XS_HTTPRequest_get, file, "$$;$"); - newXSproto(strcpy(buf, "getInt"), XS_HTTPRequest_getInt, file, "$$;$"); - newXSproto(strcpy(buf, "getFloat"), XS_HTTPRequest_getFloat, file, "$$;$"); - newXSproto(strcpy(buf, "getEscaped"), XS_HTTPRequest_getEscaped, file, "$$;$"); - newXSproto(strcpy(buf, "get_all"), XS_HTTPRequest_get_all, file, "$"); - newXSproto(strcpy(buf, "redirect"), XS_HTTPRequest_redirect, file, "$$"); - newXSproto(strcpy(buf, "SetResponseCode"), XS_HTTPRequest_SetResponseCode, file, "$$"); - newXSproto(strcpy(buf, "header"), XS_HTTPRequest_header, file, "$$$"); - XSRETURN_YES; -} - -#endif //EMBPERL_XS_CLASSES - diff --git a/world/queryserv.cpp b/world/queryserv.cpp index 552b45659..b943ca57f 100644 --- a/world/queryserv.cpp +++ b/world/queryserv.cpp @@ -7,7 +7,6 @@ #include "../common/md5.h" -#include "../common/emu_tcp_connection.h" #include "../common/packet_dump.h" extern ClientList client_list; diff --git a/world/ucs.cpp b/world/ucs.cpp index 49632276a..7830561ac 100644 --- a/world/ucs.cpp +++ b/world/ucs.cpp @@ -3,9 +3,8 @@ #include "ucs.h" #include "world_config.h" - +#include "../common/misc_functions.h" #include "../common/md5.h" -#include "../common/emu_tcp_connection.h" #include "../common/packet_dump.h" UCSConnection::UCSConnection() diff --git a/world/web_interface.cpp b/world/web_interface.cpp new file mode 100644 index 000000000..250f9d3b8 --- /dev/null +++ b/world/web_interface.cpp @@ -0,0 +1,164 @@ +#include "web_interface.h" +#include "../common/json/json.h" + +#include "web_interface_eqw.h" + +#include + +WebInterface::WebInterface(std::shared_ptr connection) +{ + m_connection = connection; + m_connection->OnMessage(ServerOP_WebInterfaceCall, std::bind(&WebInterface::OnCall, this, std::placeholders::_1, std::placeholders::_2)); + RegisterEQW(this); +} + +WebInterface::~WebInterface() +{ +} + +void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p) +{ + Json::Value root; + try { + auto json_str = p.GetCString(0); + std::stringstream ss(json_str); + ss >> root; + } + catch (std::exception) { + SendError("Could not parse request"); + return; + } + + std::string method; + Json::Value params; + std::string id; + + try { + method = root["method"].asString(); + if (method.length() == 0) { + SendError("Invalid request: method not supplied"); + return; + } + } + catch (std::exception) { + SendError("Invalid request: method not supplied"); + return; + } + + //optional "params" -> Json::Value + try { + params = root["params"]; + } + catch (std::exception) { + params = nullptr; + } + + //optional "id" needs to be string + try { + id = root["id"].asString(); + } + catch (std::exception) { + id = ""; + } + + //check for registered method + auto iter = m_calls.find(method); + if (iter == m_calls.end()) { + //if not exist then error + SendError("Invalid request: method not found"); + return; + } + + iter->second(this, method, id, params); +} + +void WebInterface::Send(const Json::Value &value) +{ + try { + std::stringstream ss; + ss << value; + + EQ::Net::DynamicPacket p; + p.PutString(0, ss.str()); + m_connection->Send(ServerOP_WebInterfaceCall, p); + } + catch (std::exception) { + //Log error + } +} + +void WebInterface::SendError(const std::string &message) +{ + Json::Value error; + error["error"] = Json::Value(); + error["error"]["message"] = message; + + Send(error); +} + +void WebInterface::SendError(const std::string &message, const std::string &id) +{ + Json::Value error; + error["error"] = Json::Value(); + error["error"]["message"] = message; + + Send(error); +} + +void WebInterface::AddCall(const std::string &method, WebInterfaceCall call) +{ + m_calls.insert(std::make_pair(method, call)); +} + +void WebInterface::SendResponse(const std::string &id, const Json::Value &response) +{ + Json::Value out; + if(!id.empty()) + out["id"] = id; + out["response"] = response; + + Send(out); +} + +WebInterfaceList::WebInterfaceList() +{ +} + +WebInterfaceList::~WebInterfaceList() +{ +} + +void WebInterfaceList::AddConnection(std::shared_ptr connection) +{ + m_interfaces.insert(std::make_pair(connection->GetUUID(), std::unique_ptr(new WebInterface(connection)))); +} + +void WebInterfaceList::RemoveConnection(std::shared_ptr connection) +{ + auto iter = m_interfaces.find(connection->GetUUID()); + if (iter != m_interfaces.end()) { + m_interfaces.erase(iter); + return; + } +} + +void WebInterfaceList::SendResponse(const std::string &uuid, std::string &id, const Json::Value &response) { + auto iter = m_interfaces.find(uuid); + if (iter != m_interfaces.end()) { + iter->second->SendResponse(id, response); + } +} + +void WebInterfaceList::SendError(const std::string &uuid, const std::string &message) { + auto iter = m_interfaces.find(uuid); + if (iter != m_interfaces.end()) { + iter->second->SendError(message); + } +} + +void WebInterfaceList::SendError(const std::string &uuid, const std::string &message, const std::string &id) { + auto iter = m_interfaces.find(uuid); + if (iter != m_interfaces.end()) { + iter->second->SendError(message, id); + } +} diff --git a/world/web_interface.h b/world/web_interface.h new file mode 100644 index 000000000..76ce325e2 --- /dev/null +++ b/world/web_interface.h @@ -0,0 +1,45 @@ +#pragma once + +#include "../common/net/servertalk_server_connection.h" +#include "../common/json/json.h" +#include +#include +#include + + + +class WebInterface +{ +public: + typedef std::function WebInterfaceCall; + WebInterface(std::shared_ptr connection); + ~WebInterface(); + + std::string GetUUID() const { return m_connection->GetUUID(); } + void SendResponse(const std::string &id, const Json::Value &response); + void SendError(const std::string &message); + void SendError(const std::string &message, const std::string &id); + void AddCall(const std::string &method, WebInterfaceCall call); +private: + void OnCall(uint16 opcode, EQ::Net::Packet &p); + void Send(const Json::Value &value); + + std::shared_ptr m_connection; + std::map m_calls; +}; + +class WebInterfaceList +{ +public: + WebInterfaceList(); + ~WebInterfaceList(); + + void AddConnection(std::shared_ptr connection); + void RemoveConnection(std::shared_ptr connection); + void SendResponse(const std::string &uuid, std::string &id, const Json::Value &response); + void SendError(const std::string &uuid, const std::string &message); + void SendError(const std::string &uuid, const std::string &message, const std::string &id); + +private: + std::map> m_interfaces; +}; diff --git a/world/web_interface_eqw.cpp b/world/web_interface_eqw.cpp new file mode 100644 index 000000000..597639c05 --- /dev/null +++ b/world/web_interface_eqw.cpp @@ -0,0 +1,40 @@ +#include "web_interface_eqw.h" +#include "web_interface.h" +#include "world_config.h" +#include "login_server_list.h" + +extern LoginServerList loginserverlist; + +void EQW__IsLocked(WebInterface *i, const std::string& method, const std::string& id, const Json::Value& params) { + Json::Value ret = WorldConfig::get()->Locked; + i->SendResponse(id, ret); +} + +void EQW__Lock(WebInterface *i, const std::string& method, const std::string& id, const Json::Value& params) { + WorldConfig::LockWorld(); + if (loginserverlist.Connected()) { + loginserverlist.SendStatus(); + } + + Json::Value ret; + ret["status"] = "complete"; + i->SendResponse(id, ret); +} + +void EQW__Unlock(WebInterface *i, const std::string& method, const std::string& id, const Json::Value& params) { + WorldConfig::UnlockWorld(); + if (loginserverlist.Connected()) { + loginserverlist.SendStatus(); + } + + Json::Value ret; + ret["status"] = "complete"; + i->SendResponse(id, ret); +} + +void RegisterEQW(WebInterface *i) +{ + i->AddCall("IsLocked", std::bind(EQW__IsLocked, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + i->AddCall("Lock", std::bind(EQW__Lock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + i->AddCall("Unlock", std::bind(EQW__Unlock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); +} diff --git a/world/web_interface_eqw.h b/world/web_interface_eqw.h new file mode 100644 index 000000000..6ebceae15 --- /dev/null +++ b/world/web_interface_eqw.h @@ -0,0 +1,5 @@ +#pragma once + +class WebInterface; + +void RegisterEQW(WebInterface *i); \ No newline at end of file diff --git a/world/zonelist.cpp b/world/zonelist.cpp index c44573f20..3c9460fce 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -18,10 +18,9 @@ #include "../common/global_define.h" #include "zonelist.h" #include "zoneserver.h" -#include "world_tcp_connection.h" #include "worlddb.h" -#include "console.h" #include "world_config.h" +#include "../common/misc_functions.h" #include "../common/servertalk.h" #include "../common/string_util.h" #include "../common/random.h" diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index da44cdf6a..d4fe4eae5 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -22,7 +22,6 @@ #include "login_server_list.h" #include "zonelist.h" #include "worlddb.h" -#include "console.h" #include "client.h" #include "../common/md5.h" #include "world_config.h"