From ab1edbf537c03c6a6af417bbfe1fbc61d09c94af Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:22:54 -0800 Subject: [PATCH] Remove unused and unmaintained sources --- common/CMakeLists.txt | 4 +- common/SocketLib/Base64.cpp | 266 ----- common/SocketLib/Base64.h | 67 -- common/SocketLib/File.cpp | 126 --- common/SocketLib/File.h | 76 -- common/SocketLib/HTTPSocket.cpp | 366 ------- common/SocketLib/HTTPSocket.h | 137 --- common/SocketLib/HttpdCookies.cpp | 250 ----- common/SocketLib/HttpdCookies.h | 91 -- common/SocketLib/HttpdForm.cpp | 621 ------------ common/SocketLib/HttpdForm.h | 115 --- common/SocketLib/HttpdSocket.cpp | 352 ------- common/SocketLib/HttpdSocket.h | 99 -- common/SocketLib/IFile.h | 65 -- common/SocketLib/MemFile.cpp | 212 ---- common/SocketLib/MemFile.h | 93 -- common/SocketLib/Mime.cpp | 92 -- common/SocketLib/Mime.h | 55 - common/SocketLib/Parse.cpp | 327 ------ common/SocketLib/Parse.h | 95 -- common/SocketLib/README.eqemu | 5 - common/SocketLib/README.macosx | 5 - common/SocketLib/Utility.cpp | 167 ---- common/SocketLib/Utility.h | 70 -- common/SocketLib/gpl.txt | 340 ------- common/SocketLib/socket_include.cpp | 87 -- common/SocketLib/socket_include.h | 218 ---- common/eq_stream.cpp | 1440 --------------------------- common/eq_stream.h | 314 ------ common/eq_stream_factory.cpp | 298 ------ common/eq_stream_factory.h | 57 -- common/eq_stream_type.h | 12 - common/guilds.cpp | 28 - common/tcp_connection.cpp | 942 ------------------ common/tcp_server.cpp | 231 ----- world/eqw.cpp | 375 ------- world/eqw.h | 93 -- world/eqw_http_handler.cpp | 335 ------- world/eqw_parser.cpp | 348 ------- world/http_request.cpp | 80 -- world/http_request.h | 58 -- 41 files changed, 1 insertion(+), 9011 deletions(-) delete mode 100644 common/SocketLib/Base64.cpp delete mode 100644 common/SocketLib/Base64.h delete mode 100644 common/SocketLib/File.cpp delete mode 100644 common/SocketLib/File.h delete mode 100644 common/SocketLib/HTTPSocket.cpp delete mode 100644 common/SocketLib/HTTPSocket.h delete mode 100644 common/SocketLib/HttpdCookies.cpp delete mode 100644 common/SocketLib/HttpdCookies.h delete mode 100644 common/SocketLib/HttpdForm.cpp delete mode 100644 common/SocketLib/HttpdForm.h delete mode 100644 common/SocketLib/HttpdSocket.cpp delete mode 100644 common/SocketLib/HttpdSocket.h delete mode 100644 common/SocketLib/IFile.h delete mode 100644 common/SocketLib/MemFile.cpp delete mode 100644 common/SocketLib/MemFile.h delete mode 100644 common/SocketLib/Mime.cpp delete mode 100644 common/SocketLib/Mime.h delete mode 100644 common/SocketLib/Parse.cpp delete mode 100644 common/SocketLib/Parse.h delete mode 100644 common/SocketLib/README.eqemu delete mode 100644 common/SocketLib/README.macosx delete mode 100644 common/SocketLib/Utility.cpp delete mode 100644 common/SocketLib/Utility.h delete mode 100644 common/SocketLib/gpl.txt delete mode 100644 common/SocketLib/socket_include.cpp delete mode 100644 common/SocketLib/socket_include.h delete mode 100644 common/eq_stream.cpp delete mode 100644 common/eq_stream.h delete mode 100644 common/eq_stream_factory.cpp delete mode 100644 common/eq_stream_factory.h delete mode 100644 common/eq_stream_type.h delete mode 100644 common/guilds.cpp delete mode 100644 common/tcp_connection.cpp delete mode 100644 common/tcp_server.cpp delete mode 100644 world/eqw.cpp delete mode 100644 world/eqw.h delete mode 100644 world/eqw_http_handler.cpp delete mode 100644 world/eqw_parser.cpp delete mode 100644 world/http_request.cpp delete mode 100644 world/http_request.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f250adbb1..d5fb90abb 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -45,7 +45,6 @@ set(common_sources faction.cpp file.cpp guild_base.cpp - guilds.cpp inventory_profile.cpp inventory_slot.cpp ip_util.cpp @@ -759,7 +758,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) mark_as_advanced(EQEMU_SFMT19937) endif() -include_directories(Patches SocketLib StackWalker) +include_directories(Patches StackWalker) add_library(common ${common_sources} ${common_headers} ${repositories}) @@ -807,7 +806,6 @@ endif() if(UNIX) target_link_libraries(common PUBLIC uuid) - set_source_files_properties("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) set_source_files_properties("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) endif() diff --git a/common/SocketLib/Base64.cpp b/common/SocketLib/Base64.cpp deleted file mode 100644 index eb6a2fd0a..000000000 --- a/common/SocketLib/Base64.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/** \file Base64.cpp - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 "Base64.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -const char *Base64::bstr = - "ABCDEFGHIJKLMNOPQ" - "RSTUVWXYZabcdefgh" - "ijklmnopqrstuvwxy" - "z0123456789+/"; - -const char Base64::rstr[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, - 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0}; - - -void Base64::encode(FILE *fil, std::string& output, bool add_crlf) -{ - size_t remain; - size_t i = 0; - size_t o = 0; - char input[4]; - - output = ""; - remain = fread(input,1,3,fil); - while (remain > 0) - { - if (add_crlf && o && o % 76 == 0) - output += "\n"; - switch (remain) - { - case 1: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) ]; - output += "=="; - break; - case 2: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; - output += "="; - break; - default: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; - output += bstr[ (input[i + 2] & 0x3f) ]; - } - o += 4; - // - remain = fread(input,1,3,fil); - } -} - - -void Base64::encode(const std::string& str_in, std::string& str_out, bool add_crlf) -{ - encode(str_in.c_str(), str_in.size(), str_out, add_crlf); -} - - -void Base64::encode(const char* input,size_t l,std::string& output, bool add_crlf) -{ - size_t i = 0; - size_t o = 0; - - output = ""; - while (i < l) - { - size_t remain = l - i; - if (add_crlf && o && o % 76 == 0) - output += "\n"; - switch (remain) - { - case 1: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) ]; - output += "=="; - break; - case 2: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; - output += "="; - break; - default: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; - output += bstr[ (input[i + 2] & 0x3f) ]; - } - o += 4; - i += 3; - } -} - - -void Base64::encode(unsigned char* input,size_t l,std::string& output,bool add_crlf) -{ - size_t i = 0; - size_t o = 0; - - output = ""; - while (i < l) - { - size_t remain = l - i; - if (add_crlf && o && o % 76 == 0) - output += "\n"; - switch (remain) - { - case 1: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) ]; - output += "=="; - break; - case 2: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; - output += "="; - break; - default: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; - output += bstr[ (input[i + 2] & 0x3f) ]; - } - o += 4; - i += 3; - } -} - - -void Base64::decode(const std::string& input,std::string& output) -{ - size_t i = 0; - size_t l = input.size(); - - output = ""; - while (i < l) - { - while (i < l && (input[i] == 13 || input[i] == 10)) - i++; - if (i < l) - { - char b1 = (char)((rstr[(int)input[i]] << 2 & 0xfc) + - (rstr[(int)input[i + 1]] >> 4 & 0x03)); - output += b1; - if (input[i + 2] != '=') - { - char b2 = (char)((rstr[(int)input[i + 1]] << 4 & 0xf0) + - (rstr[(int)input[i + 2]] >> 2 & 0x0f)); - output += b2; - } - if (input[i + 3] != '=') - { - char b3 = (char)((rstr[(int)input[i + 2]] << 6 & 0xc0) + - rstr[(int)input[i + 3]]); - output += b3; - } - i += 4; - } - } -} - - -void Base64::decode(const std::string& input, unsigned char *output, size_t& sz) -{ - size_t i = 0; - size_t l = input.size(); - size_t j = 0; - - while (i < l) - { - while (i < l && (input[i] == 13 || input[i] == 10)) - i++; - if (i < l) - { - unsigned char b1 = (unsigned char)((rstr[(int)input[i]] << 2 & 0xfc) + - (rstr[(int)input[i + 1]] >> 4 & 0x03)); - if (output) - { - output[j] = b1; - } - j++; - if (input[i + 2] != '=') - { - unsigned char b2 = (unsigned char)((rstr[(int)input[i + 1]] << 4 & 0xf0) + - (rstr[(int)input[i + 2]] >> 2 & 0x0f)); - if (output) - { - output[j] = b2; - } - j++; - } - if (input[i + 3] != '=') - { - unsigned char b3 = (unsigned char)((rstr[(int)input[i + 2]] << 6 & 0xc0) + - rstr[(int)input[i + 3]]); - if (output) - { - output[j] = b3; - } - j++; - } - i += 4; - } - } - sz = j; -} - - -size_t Base64::decode_length(const std::string& str64) -{ - if (!str64.size() || str64.size() % 4) - return 0; - size_t l = 3 * (str64.size() / 4 - 1) + 1; - if (str64[str64.size() - 2] != '=') - l++; - if (str64[str64.size() - 1] != '=') - l++; - return l; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/Base64.h b/common/SocketLib/Base64.h deleted file mode 100644 index 95608e30a..000000000 --- a/common/SocketLib/Base64.h +++ /dev/null @@ -1,67 +0,0 @@ -/** \file Base64.h - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _BASE64_H -#define _BASE64_H - -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -/** \defgroup util Utilities */ - -/** Base64 encode/decode. - \ingroup util */ -class Base64 { -public: - - static void encode(FILE *, std::string& , bool add_crlf = true); - static void encode(const std::string&, std::string& , bool add_crlf = true); - static void encode(const char *, size_t, std::string& , bool add_crlf = true); - static void encode(unsigned char *, size_t, std::string& , bool add_crlf = true); - - static void decode(const std::string&, std::string& ); - static void decode(const std::string& in, unsigned char *out, size_t&); - - static size_t decode_length(const std::string& ); - -private: -static const char *bstr; -static const char rstr[128]; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _BASE64_H diff --git a/common/SocketLib/File.cpp b/common/SocketLib/File.cpp deleted file mode 100644 index a49e6caad..000000000 --- a/common/SocketLib/File.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/** \file File.cpp - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 -#include -#include -#include -#ifndef _WIN32 -#include -#endif - -#include "File.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -File::File() -:m_fil(nullptr) -{ -} - - -File::~File() -{ -} - - -bool File::fopen(const std::string& path, const std::string& mode) -{ - m_path = path; - m_mode = mode; - m_fil = ::fopen(path.c_str(), mode.c_str()); - return m_fil ? true : false; -} - - -void File::fclose() -{ - if (m_fil) - ::fclose(m_fil); -} - - - -size_t File::fread(char *ptr, size_t size, size_t nmemb) -{ - return m_fil ? ::fread(ptr, size, nmemb, m_fil) : 0; -} - - -size_t File::fwrite(const char *ptr, size_t size, size_t nmemb) -{ - return m_fil ? ::fwrite(ptr, size, nmemb, m_fil) : 0; -} - - - -char *File::fgets(char *s, int size) -{ - return m_fil ? ::fgets(s, size, m_fil) : nullptr; -} - - -void File::fprintf(char *format, ...) -{ - va_list ap; - va_start(ap, format); - vfprintf(m_fil, format, ap); - va_end(ap); -} - - -off_t File::size() -{ - struct stat st; - if (stat(m_path.c_str(), &st) == -1) - { - return 0; - } - return st.st_size; -} - - -bool File::eof() -{ - if (m_fil) - { - if (feof(m_fil)) - return true; - } - return false; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/File.h b/common/SocketLib/File.h deleted file mode 100644 index a575d0973..000000000 --- a/common/SocketLib/File.h +++ /dev/null @@ -1,76 +0,0 @@ -/** \file File.h - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _FILE_H -#define _FILE_H - -#include "IFile.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -/** IFile implementation of a disk file. - \ingroup file */ -class File : public IFile -{ -public: - File(); - ~File(); - - bool fopen(const std::string&, const std::string&); - void fclose(); - - size_t fread(char *, size_t, size_t); - size_t fwrite(const char *, size_t, size_t); - - char *fgets(char *, int); - void fprintf(char *format, ...); - - off_t size(); - bool eof(); - -private: - File(const File& ) {} // copy constructor - File& operator=(const File& ) { return *this; } // assignment operator - - std::string m_path; - std::string m_mode; - FILE *m_fil; -}; - - - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _FILE_H diff --git a/common/SocketLib/HTTPSocket.cpp b/common/SocketLib/HTTPSocket.cpp deleted file mode 100644 index da4f2264c..000000000 --- a/common/SocketLib/HTTPSocket.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* EQEMu: Everquest Server Emulator - * - * This code originated from `C++ Sockets Library` referenced below. - * Taken and stripped/modified to remove dependancies on parts of - * the library which we are not using, and to suit other needs. - * 2006 - EQEMu Development Team (http://eqemulator.net) - * - * - */ - -/** \file HTTPSocket.cpp - ** \date 2004-04-06 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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. -*/ -#ifdef _WIN32 -#pragma warning(disable:4786) -#endif -#include "../global_define.h" -#include -#include -#include -#include "Parse.h" -#include "HTTPSocket.h" -#include "../tcp_connection.h" -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - - - -HTTPSocket::HTTPSocket(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -:TCPConnection(ID,in_socket,irIP,irPort) -,m_first(true) -,m_header(true) -,m_http_version("HTTP/1.0") -,m_request(false) -,m_response(false) -{ -} - - -HTTPSocket::~HTTPSocket() -{ -} - -/* - * eqemu stuff - */ - -bool HTTPSocket::ProcessReceivedData(char *errbuf) -{ - if (errbuf) - errbuf[0] = 0; - if (!recvbuf) - return true; - - char *buff=(char *)recvbuf; - unsigned long bufflen=recvbuf_used; - - while(1) { - if (m_header) { - char *ptr=(char *)memchr(buff,'\n',bufflen); - if (!ptr) - break; - int length=(ptr-buff)+1; - std::string line; - line.append(buff,length-2); - OnLine(line); - - buff+=length; - bufflen-=length; - } else { - OnData(buff,bufflen); - buff+=bufflen; - bufflen=0; - break; - } - } - - if (bufflen) { - memmove(recvbuf,buff,bufflen); - recvbuf_used=bufflen; - } else { - safe_delete_array(recvbuf); - } -} - -bool HTTPSocket::SendString(const char *str) { - return(TCPConnection::Send((const uchar *) str, strlen(str))); -} - -bool HTTPSocket::SendBuf(const char *dat, unsigned int len) { - return(TCPConnection::Send((const uchar *) dat, len)); -} - -/* - * /eqemu stuff - */ - -void HTTPSocket::OnLine(const std::string& line) -{ - if (m_first) - { - Parse pa(line); - std::string str = pa.getword(); - if (str.substr(0,4) == "HTTP") // response - { - m_http_version = str; - m_status = pa.getword(); - m_status_text = pa.getrest(); - m_response = true; - } - else // request - { - m_method = str; - m_url = pa.getword(); - size_t spl = m_url.find("?"); - if (spl != std::string::npos) - { - m_uri = m_url.substr(0,spl); - m_query_string = m_url.substr(spl + 1); - } - else - { - m_uri = m_url; - } - m_http_version = pa.getword(); - m_request = true; - } - m_first = false; - OnFirst(); - return; - } - if (!line.size()) - { -// SetLineProtocol(false); - m_header = false; - OnHeaderComplete(); - return; - } - Parse pa(line,":"); - std::string key = pa.getword(); - std::string value = pa.getrest(); - OnHeader(key,value); - /* If remote end tells us to keep connection alive, and we're operating - in http/1.1 mode (not http/1.0 mode), then we mark the socket to be - retained. */ -/* if (!strcasecmp(key.c_str(), "connection") && - !strcasecmp(value.c_str(), "keep-alive") ) - { - SetRetain(); - }*/ -} - - -void HTTPSocket::SendResponse() -{ - std::string msg; - msg = m_http_version + " " + m_status + " " + m_status_text + "\r\n"; - for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); it++) - { - std::string key = (*it).first; - std::string val = (*it).second; - msg += key + ": " + val + "\r\n"; - } - msg += "\r\n"; - SendString( msg.c_str() ); -} - - -void HTTPSocket::AddResponseHeader(const std::string& header, const char *format, ...) -{ - static char slask[5000]; - va_list ap; - - va_start(ap, format); -#ifdef _WIN32 - vsprintf(slask, format, ap); -#else - vsnprintf(slask, 5000, format, ap); -#endif - va_end(ap); - - m_response_header[header] = slask; -} - - -void HTTPSocket::SendRequest() -{ - std::string msg; - msg = m_method + " " + m_url + " " + m_http_version + "\r\n"; - for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); it++) - { - std::string key = (*it).first; - std::string val = (*it).second; - msg += key + ": " + val + "\r\n"; - } - msg += "\r\n"; - SendString( msg.c_str() ); -} - - -std::string HTTPSocket::MyUseragent() -{ - std::string version = "C++Sockets/"; -#ifdef _VERSION - version += _VERSION; -#endif - return version; -} - - -void HTTPSocket::Reset() -{ - m_first = true; - m_header = true; - m_request = false; - m_response = false; -// SetLineProtocol(true); - while (m_response_header.size()) - { - string_m::iterator it = m_response_header.begin(); - m_response_header.erase(it); - } - -} - - -const std::string& HTTPSocket::GetMethod() -{ - return m_method; -} - - -void HTTPSocket::SetMethod(const std::string& x) -{ - m_method = x; -} - - -const std::string& HTTPSocket::GetUrl() -{ - return m_url; -} - - -void HTTPSocket::SetUrl(const std::string& x) -{ - m_url = x; -} - - -const std::string& HTTPSocket::GetUri() -{ - return m_uri; -} - - -const std::string& HTTPSocket::GetQueryString() -{ - return m_query_string; -} - - -const std::string& HTTPSocket::GetHttpVersion() -{ - return m_http_version; -} - - -const std::string& HTTPSocket::GetStatus() -{ - return m_status; -} - - -const std::string& HTTPSocket::GetStatusText() -{ - return m_status_text; -} - - -bool HTTPSocket::IsRequest() -{ - return m_request; -} - - -bool HTTPSocket::IsResponse() -{ - return m_response; -} - - -void HTTPSocket::SetHttpVersion(const std::string& x) -{ - m_http_version = x; -} - - -void HTTPSocket::SetStatus(const std::string& num, const std::string& text) { - m_status = num; - m_status_text = text; -} - -void HTTPSocket::SetStatus(const std::string& x) -{ - m_status = x; -} - - -void HTTPSocket::SetStatusText(const std::string& x) -{ - m_status_text = x; -} - - -void HTTPSocket::AddResponseHeader(const std::string& x,const std::string& y) -{ - m_response_header[x] = y; -} - - -void HTTPSocket::SetUri(const std::string& x) -{ - m_uri = x; -} - -void HTTPSocket::SendResponse(const std::string& status_num, const std::string& status_text) { - SetStatus(status_num, status_text); - SendResponse(); -} - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/HTTPSocket.h b/common/SocketLib/HTTPSocket.h deleted file mode 100644 index 409c90bce..000000000 --- a/common/SocketLib/HTTPSocket.h +++ /dev/null @@ -1,137 +0,0 @@ -/* EQEMu: Everquest Server Emulator - * - * This code originated from `C++ Sockets Library` referenced below. - * Taken and stripped/modified to remove dependancies on parts of - * the library which we are not using, and to suit other needs. - * 2006 - EQEMu Development Team (http://eqemulator.net) - * - * - */ - -/** \file HTTPSocket.h Class HTTPSocket definition. - ** \date 2004-04-06 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _HTTPSOCKET_H -#define _HTTPSOCKET_H - -#include -#include -#include "../tcp_connection.h" - - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -/** \defgroup http HTTP Sockets */ -/** HTTP request/response base class. - \ingroup http */ -class HTTPSocket : public TCPConnection -{ - /** map to hold http header values. */ - typedef std::map string_m; -public: - HTTPSocket(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort); - virtual ~HTTPSocket(); - - void OnLine(const std::string& line); - - /** Callback executes when first line has been received. - GetMethod, GetUrl/GetUri, and GetHttpVersion are valid when this callback is executed. */ - virtual void OnFirst() = 0; - /** For each header line this callback is executed. - \param key Http header name - \param value Http header value */ - virtual void OnHeader(const std::string& key,const std::string& value) = 0; - /** Callback fires when all http headers have been received. */ - virtual void OnHeaderComplete() = 0; - /** Chunk of http body data recevied. */ - virtual void OnData(const char *,size_t) = 0; - - const std::string& GetMethod(); - void SetMethod(const std::string& x); - const std::string& GetUrl(); - void SetUrl(const std::string& x); - const std::string& GetUri(); - void SetUri(const std::string& x); - const std::string& GetQueryString(); - const std::string& GetHttpVersion(); - const std::string& GetStatus(); - const std::string& GetStatusText(); - bool IsRequest(); - bool IsResponse(); - - void SetHttpVersion(const std::string& x); - void SetStatus(const std::string& x); - void SetStatus(const std::string& num, const std::string& text); - void SetStatusText(const std::string& x); - void AddResponseHeader(const std::string& x,const std::string& y); - void AddResponseHeader(const std::string& x,const char *format, ...); - void SendResponse(); - void SendResponse(const std::string& status_num, const std::string& status_text); - void SendRequest(); - - /** Implement this to return your own User-agent string. */ - virtual std::string MyUseragent(); - -protected: - /** Reset state of socket to sucessfully implement keep-alive. */ - virtual void Reset(); - - //stubs for crap which used to be in our parent class (TcpSocket) - bool SendString(const char *str); - bool SendBuf(const char *dat, unsigned int len); - - virtual bool ProcessReceivedData(char* errbuf = 0); - -private: -// HTTPSocket& operator=(const HTTPSocket& ) { return *this; } - bool m_first; - bool m_header; - std::string m_line; - std::string m_method; - std::string m_url; - std::string m_uri; - std::string m_query_string; - std::string m_http_version; - std::string m_status; - std::string m_status_text; - bool m_request; - bool m_response; - string_m m_response_header; -}; - - - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _HTTPSOCKET_H diff --git a/common/SocketLib/HttpdCookies.cpp b/common/SocketLib/HttpdCookies.cpp deleted file mode 100644 index a40200aab..000000000 --- a/common/SocketLib/HttpdCookies.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/** \file HttpdCookies.cpp -*/ -/* -Copyright (C) 2003-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 "../global_define.h" -#ifdef _WIN32 -#pragma warning(disable:4786) -#endif -#include "Parse.h" -#include "Utility.h" -#include "HTTPSocket.h" -#include "HttpdCookies.h" -#include "../types.h" -#include -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -HttpdCookies::HttpdCookies() -{ -} - -HttpdCookies::HttpdCookies(const std::string& s) -{ - Parse *pa = new Parse(s,";"); - - std::string slask = pa -> getword(); - while (slask.size()) - { - Parse *pa2 = new Parse(slask,"="); - std::string name = pa2 -> getword(); - std::string value = pa2 -> getword(); - delete pa2; - COOKIE *c = new COOKIE(name,value); - m_cookies.push_back(c); - // - slask = pa -> getword(); - } - delete pa; -} - -HttpdCookies::~HttpdCookies() -{ - for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++) - { - COOKIE *c = *it; - delete c; - } -} - -bool HttpdCookies::getvalue(const std::string& name,std::string& buffer) //char *buffer,size_t length) -{ - for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++) - { - COOKIE *c = *it; - if (!strcasecmp(c -> name.c_str(),name.c_str())) - { - buffer = c -> value; - return true; - } - } - buffer = ""; - return false; -} - -void HttpdCookies::replacevalue(const std::string& name,const std::string& value) -{ - COOKIE *c = nullptr; - - for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++) - { - c = *it; - if (!strcasecmp(c -> name.c_str(),name.c_str())) - break; - c = nullptr; - } - - if (c) - { - c -> value = value; - } - else - { - c = new COOKIE(name,value); - m_cookies.push_back(c); - } -} - -void HttpdCookies::replacevalue(const std::string& name,long l) -{ - replacevalue(name, Utility::l2string(l)); -} - -void HttpdCookies::replacevalue(const std::string& name,int i) -{ - replacevalue(name, Utility::l2string(i)); -} - -size_t HttpdCookies::getlength(const std::string& name) -{ - COOKIE *c = nullptr; - - for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++) - { - c = *it; - if (!strcasecmp(c -> name.c_str(),name.c_str())) - break; - c = nullptr; - } - return c ? c -> value.size() : 0; -} - -void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, const std::string& value) -{ - char *str = new char[name.size() + value.size() + domain.size() + path.size() + 100]; - - // set-cookie response - if (domain.size()) - { - sprintf(str, "%s=%s; domain=%s; path=%s; expires=%s", - name.c_str(), value.c_str(), - domain.c_str(), - path.c_str(), - expiredatetime().c_str()); - } - else - { - sprintf(str, "%s=%s; path=%s; expires=%s", - name.c_str(), value.c_str(), - path.c_str(), - expiredatetime().c_str()); - } - sock -> AddResponseHeader("Set-cookie", str); - delete[] str; - - replacevalue(name, value); -} - -void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, long value) -{ - char *str = new char[name.size() + domain.size() + path.size() + 100]; - char dt[80]; - - // set-cookie response - if (domain.size()) - { - sprintf(str, "%s=%ld; domain=%s; path=%s; expires=%s", - name.c_str(), value, - domain.c_str(), - path.c_str(), - expiredatetime().c_str()); - } - else - { - sprintf(str, "%s=%ld; path=%s; expires=%s", - name.c_str(), value, - path.c_str(), - expiredatetime().c_str()); - } - sock -> AddResponseHeader("Set-cookie", str); - delete[] str; - - sprintf(dt, "%ld", value); - replacevalue(name, dt); -} - -void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, int value) -{ - char *str = new char[name.size() + domain.size() + path.size() + 100]; - char dt[80]; - - // set-cookie response - if (domain.size()) - { - sprintf(str, "%s=%d; domain=%s; path=%s; expires=%s", - name.c_str(), value, - domain.c_str(), - path.c_str(), - expiredatetime().c_str()); - } - else - { - sprintf(str, "%s=%d; path=%s; expires=%s", - name.c_str(), value, - path.c_str(), - expiredatetime().c_str()); - } - sock -> AddResponseHeader("Set-cookie", str); - delete[] str; - - sprintf(dt, "%d", value); - replacevalue(name, dt); -} - - -const std::string& HttpdCookies::expiredatetime() -{ - time_t t = time(nullptr); - struct tm * tp = gmtime(&t); - const char *days[7] = {"Sunday", "Monday", - "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; - const char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - char dt[100]; - - sprintf(dt, "%s, %02d-%s-%04d %02d:%02d:%02d GMT", - days[tp -> tm_wday], - tp -> tm_mday, - months[tp -> tm_mon], - tp -> tm_year + 1910, - tp -> tm_hour, - tp -> tm_min, - tp -> tm_sec); - m_date = dt; - return m_date; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/HttpdCookies.h b/common/SocketLib/HttpdCookies.h deleted file mode 100644 index 7dea224b6..000000000 --- a/common/SocketLib/HttpdCookies.h +++ /dev/null @@ -1,91 +0,0 @@ -/** \file HttpdCookies.h -*/ -/* -Copyright (C) 2003-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _COOKIES_H -#define _COOKIES_H - -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -//! Store the cookies name/value pairs. - - - -//! Retrieve and manage cookies during a cgi call. -class HTTPSocket; - -/** HTTP Cookie parse/container class. -\sa HttpdSocket -\sa HttpdForm -\ingroup webserver */ -class HttpdCookies -{ - /** Name/value pair store struct. - \ingroup webserver */ - struct COOKIE - { - COOKIE(const std::string& n,const std::string& v) : name(n),value(v) {} - std::string name; - std::string value; - }; - /** list of key/value structs. */ - typedef std::list cookie_v; -public: - HttpdCookies(); - HttpdCookies(const std::string& query_string); - ~HttpdCookies(); - -// int getvalue(const std::string& ,char *,size_t); // (name, buffer, length) - bool getvalue(const std::string&,std::string&); - void replacevalue(const std::string& ,const std::string& ); - void replacevalue(const std::string& ,long); - void replacevalue(const std::string& ,int); - size_t getlength(const std::string& ); - void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,const std::string& v); - void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,long v); - void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,int v); - const std::string& expiredatetime(); - - cookie_v& GetHttpdCookies() { return m_cookies; } - -private: - cookie_v m_cookies; - std::string m_date; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _COOKIES_H diff --git a/common/SocketLib/HttpdForm.cpp b/common/SocketLib/HttpdForm.cpp deleted file mode 100644 index b7eb4ada8..000000000 --- a/common/SocketLib/HttpdForm.cpp +++ /dev/null @@ -1,621 +0,0 @@ -/** \file HttpdForm.cpp - read stdin, parse cgi input - ** - ** Written: 1999-Feb-10 grymse@alhem.net - **/ - -/* -Copyright (C) 1999-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 -#ifdef _WIN32 -#pragma warning(disable:4786) -#include -#endif -#include "socket_include.h" -#include "Parse.h" -#include "IFile.h" -#include "HttpdForm.h" -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -HttpdForm::HttpdForm(IFile *infil) : raw(false) -{ - CGI *cgi = nullptr; - char *c_t = getenv("CONTENT_TYPE"); - char *c_l = getenv("CONTENT_LENGTH"); - size_t extra = 2; - char name[200]; - - m_current = m_cgi.end(); - *name = 0; - - if (c_t && !strncmp(c_t, "multipart/form-data",19)) - { - Parse pa(c_t,";="); - char *tempcmp = nullptr; - size_t tc = 0; - size_t l = 0; - std::string str = pa.getword(); - m_strBoundary = ""; - while (str.size()) - { - if (!strcmp(str.c_str(),"boundary")) - { - m_strBoundary = pa.getword(); - l = m_strBoundary.size(); - tempcmp = new char[l + extra]; - } - // - str = pa.getword(); - } - if (m_strBoundary.size()) - { - std::string content_type; - std::string current_name; - std::string current_filename; - char slask[2000]; - infil -> fgets(slask, 200); - while (!infil -> eof()) - { - while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10)) - { - slask[strlen(slask) - 1] = 0; - } - content_type = ""; - current_name = ""; - current_filename = ""; - if ((strstr(slask,m_strBoundary.c_str()) || strstr(m_strBoundary.c_str(),slask)) && strcmp(slask, m_strBoundary.c_str())) - { - m_strBoundary = slask; - l = m_strBoundary.size(); - delete[] tempcmp; - tempcmp = new char[l + extra]; - } - if (!strcmp(slask, m_strBoundary.c_str())) - { - // Get headers until empty line - infil -> fgets(slask, 200); - while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10)) - { - slask[strlen(slask) - 1] = 0; - } - while (!infil -> eof() && *slask) - { - Parse pa(slask,";"); - std::string h = pa.getword(); - if (!strcasecmp(h.c_str(),"Content-type:")) - { - content_type = pa.getword(); - } - else - if (!strcasecmp(h.c_str(),"Content-Disposition:")) - { - h = pa.getword(); - if (!strcmp(h.c_str(),"form-data")) - { - pa.EnableQuote(true); - h = pa.getword(); - while (h.size()) - { - Parse pa2(slask,"="); - std::string name = pa2.getword(); - std::string h = pa2.getrest(); - if (!strcmp(name.c_str(),"name")) - { - if (h.size() && h[0] == '"') - { - current_name = h.substr(1, h.size() - 2); - } - else - { - current_name = h; - } - } - else - if (!strcmp(name.c_str(),"filename")) - { - if (h.size() && h[0] == '"') - { - current_filename = h.substr(1, h.size() - 2); - } - else - { - current_filename = h; - } - size_t x = 0; - for (size_t i = 0; i < current_filename.size(); i++) - { - if (current_filename[i] == '/' || current_filename[i] == '\\') - x = i + 1; - } - if (x) - { - current_filename = current_filename.substr(x); - } - } - h = pa.getword(); - } - } - } - // get next header value - infil -> fgets(slask, 200); - while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10)) - { - slask[strlen(slask) - 1] = 0; - } - } - // Read content, save...? - if (!current_filename.size()) // not a file - { - std::string val; - infil -> fgets(slask,1000); - while (!infil -> eof() && strncmp(slask,m_strBoundary.c_str(),m_strBoundary.size() )) - { - val += slask; - infil -> fgets(slask,1000); - } - // remove trailing cr/linefeed - while (val.size() && (val[val.size() - 1] == 13 || val[val.size() - 1] == 10)) - { - val = val.substr(0,val.size() - 1); - } - cgi = new CGI(current_name, val); - m_cgi.push_back(cgi); - } - else // current_filename.size() > 0 - { - // read until m_strBoundary... - FILE *fil; - int out = 0; - char c; - char fn[1000]; // where post'd file will be saved -#ifdef _WIN32 - { - char tmp_path[1000]; - ::GetTempPath(1000, tmp_path); - if (tmp_path[strlen(tmp_path) - 1] != '\\') - { - strcat(tmp_path, "\\"); - } - sprintf(fn,"%s%s",tmp_path,current_filename.c_str()); - } -#else - sprintf(fn,"/tmp/%s",current_filename.c_str()); -#endif - if ((fil = fopen(fn, "wb")) != nullptr) - { - infil -> fread(&c,1,1); - while (!infil -> eof()) - { - if (out) - { - fwrite(&tempcmp[tc],1,1,fil); - } - tempcmp[tc] = c; - tc++; - if (tc >= l + extra) - { - tc = 0; - out = 1; - } - if (tc) - { - if (!strncmp(tempcmp + tc + extra, m_strBoundary.c_str(), l - tc) && - !strncmp(tempcmp, m_strBoundary.c_str() + l - tc, tc)) - { - break; - } - } - else - { - if (!strncmp(tempcmp + extra, m_strBoundary.c_str(), l)) - { - break; - } - } - infil -> fread(&c,1,1); - } - fclose(fil); - - cgi = new CGI(current_name,fn,fn); - m_cgi.push_back(cgi); - - strcpy(slask, m_strBoundary.c_str()); - infil -> fgets(slask + strlen(slask), 200); // next line - } - else - { - // couldn't open file - break; - } - } - } - else - { - // Probably '--' - break; - } - } // while (!infil -> eof()) - } // if (m_strBoundary) - if (tempcmp) - { - delete[] tempcmp; - } - } - else - { - int i = 0; - int cl = c_l ? atoi(c_l) : -1; - char c,chigh,clow; - char *slask = new char[8888]; - bool got_name = false; - m_current = m_cgi.end(); - - *name = 0; - - infil -> fread(&c,1,1); - cl--; - while (cl >= 0) - { - switch (c) - { - case '=': /* end of name */ - slask[i] = 0; - i = 0; - strcpy(name,slask); - got_name = true; - break; - case '&': /* end of value */ - slask[i] = 0; - i = 0; - if(got_name) { - got_name = false; - cgi = new CGI(name,slask); - m_cgi.push_back(cgi); - } else { - cgi = new CGI(slask,""); - m_cgi.push_back(cgi); - } - break; - case '+': /* space */ - slask[i++] = ' '; - break; - case '%': /* hex value */ - infil -> fread(&chigh,1,1); - cl--; - chigh -= 48; - chigh &= 0xff - 32; - if (chigh > 9) - chigh -= 7; - infil -> fread(&clow,1,1); - cl--; - clow -= 48; - clow &= 0xff - 32; - if (clow > 9) - clow -= 7; - slask[i++] = (char)(chigh * 16 + clow); - break; - default: /* just another char */ - slask[i++] = c; - break; - } - if(infil -> eof()) - break; - // - if (cl > 0) - { - infil -> fread(&c,1,1); - } - cl--; - } - slask[i] = 0; - i = 0; - if(got_name) { - cgi = new CGI(name,slask); - m_cgi.push_back(cgi); - } else { - cgi = new CGI(slask,""); - m_cgi.push_back(cgi); - } - delete[] slask; - } -} - - -// HttpdForm(buffer,l) -- request_method GET - -HttpdForm::HttpdForm(const std::string& buffer,size_t l) : raw(false) -{ - CGI *cgi = nullptr; - char slask[8888]; - char name[200]; - int i = 0; - char c,chigh,clow; - bool got_name = false; - size_t ptr = 0; - - m_current = m_cgi.end(); - - *name = 0; - - ptr = 0; - while (ptr < l) - { - c = buffer[ptr++]; - switch (c) - { - case '=': /* end of name */ - slask[i] = 0; - i = 0; - got_name = true; - strcpy(name,slask); - break; - case '&': /* end of value */ - slask[i] = 0; - i = 0; - if(got_name) { - got_name = false; - cgi = new CGI(name,slask); - m_cgi.push_back(cgi); - } else { - cgi = new CGI(slask, ""); - m_cgi.push_back(cgi); - } - break; - case '+': /* space */ - slask[i++] = ' '; - break; - case '%': /* hex value */ - chigh = buffer[ptr++]; - chigh -= 48; - chigh &= 0xff - 32; - if (chigh > 9) - chigh -= 7; - clow = buffer[ptr++]; - clow -= 48; - clow &= 0xff - 32; - if (clow > 9) - clow -= 7; - slask[i++] = (char)(chigh * 16 + clow); - break; - default: /* just another char */ - slask[i++] = c; - break; - } - } - slask[i] = 0; - i = 0; - if(got_name) { - cgi = new CGI(name,slask); - m_cgi.push_back(cgi); - } else { - cgi = new CGI(slask, ""); - m_cgi.push_back(cgi); - } -} - - -HttpdForm::~HttpdForm() -{ - CGI *cgi = nullptr; //,*tmp; - - for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) - { - cgi = *it; - delete cgi; - } -} - - -void HttpdForm::EnableRaw(bool b) -{ - raw = b; -} - - -void HttpdForm::strcpyval(std::string& v,const char *value) //,size_t len) -{ - v = ""; - for (size_t i = 0; i < strlen(value); i++) - { - if (value[i] == '<') - { - v += "<"; - } - else - if (value[i] == '>') - { - v += ">"; - } - else - if (value[i] == '&') - { - v += "&"; - } - else - { - v += value[i]; - } - } -} - - -bool HttpdForm::getfirst(std::string& n) //char *n,size_t len) -{ - m_current = m_cgi.begin(); - return getnext(n); -} - - -bool HttpdForm::getnext(std::string& n) //char *n,size_t len) -{ - if (m_current != m_cgi.end() ) - { - CGI *current = *m_current; - n = current -> name; - m_current++; - return true; - } - else - { - n = ""; - } - return false; -} - - -bool HttpdForm::getfirst(std::string& n,std::string& v) //char *n,size_t len,char *v,size_t vlen) -{ - m_current = m_cgi.begin(); - return getnext(n,v); -} - - -bool HttpdForm::getnext(std::string& n,std::string& v) //char *n,size_t len,char *v,size_t vlen) -{ - if (m_current != m_cgi.end() ) - { - CGI *current = *m_current; - n = current -> name; - if (raw) - { - v = current -> value; - } - else - { - strcpyval(v,current -> value.c_str()); - } - m_current++; - return true; - } - else - { - n = ""; - } - return false; -} - - -int HttpdForm::getvalue(const std::string& n,std::string& v) //char *v,size_t len) -{ - CGI *cgi = nullptr; - int r = 0; - - for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) - { - cgi = *it; - if (cgi -> name == n) - break; - cgi = nullptr; - } - if (cgi) - { - if (raw) - { - v = cgi -> value; - } - else - { - strcpyval(v,cgi -> value.c_str()); - } - r++; - } - else - { - v = ""; - } - - return r; -} - - -std::string HttpdForm::getvalue(const std::string& n) -{ - for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) - { - CGI *cgi = *it; - if (cgi -> name == n) - { - return cgi -> value; - } - } - return ""; -} - - -size_t HttpdForm::getlength(const std::string& n) -{ - CGI *cgi = nullptr; - size_t l; - - for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) - { - cgi = *it; - if (cgi -> name == n) - break; - cgi = nullptr; - } - l = cgi ? cgi -> value.size() : 0; - if (cgi && !raw) - { - for (size_t i = 0; i < cgi -> value.size(); i++) - { - switch (cgi -> value[i]) - { - case '<': // < - case '>': // > - l += 4; - break; - case '&': // & - l += 5; - break; - } - } - } - return l; -} - - -HttpdForm::cgi_v& HttpdForm::getbase() -{ - return m_cgi; -} - - -const std::string& HttpdForm::GetBoundary() -{ - return m_strBoundary; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/HttpdForm.h b/common/SocketLib/HttpdForm.h deleted file mode 100644 index a8209d98b..000000000 --- a/common/SocketLib/HttpdForm.h +++ /dev/null @@ -1,115 +0,0 @@ -/** \file HttpdForm.h - read stdin, parse cgi input - ** - ** Written: 1999-Feb-10 grymse@alhem.net - **/ - -/* -Copyright (C) 1999-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _FORM_H -#define _FORM_H - -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -class IFile; - -/** Parse/store a http query_string/form-data body. - \ingroup webserver */ -class HttpdForm -{ - /** - * Store the name/value pairs from a GET/POST operation. - * "name" does not have to be unique. - \ingroup webserver - */ - struct CGI - { - CGI(const std::string& n,const std::string& v) : name(n),value(v) {} - CGI(const std::string& n,const std::string& v,const std::string& p) : name(n),value(v),path(p) {} - std::string name; - std::string value; - std::string path; - }; - /** list of key/value pairs. */ - typedef std::list cgi_v; - -public: - /** - * Default constructor (used in POST operations). - * Input is read from stdin. Number of characters to read - * can be found in the environment variable CONTENT_LENGTH. - */ - HttpdForm(IFile *); - /** - * Another constructor (used in GET operations). - * Input is read from the environment variable QUERY_STRING. - * @param query_string The httpd server provided QUERY_STRING - * @param length Query string length. - */ - HttpdForm(const std::string& query_string,size_t length); - ~HttpdForm(); - - void EnableRaw(bool); - - void strcpyval(std::string&,const char *); //,size_t); - - /* get names */ - bool getfirst(std::string& n); //char *,size_t); - bool getnext(std::string& n); //char *,size_t); - - /* get names and values */ - bool getfirst(std::string& n,std::string& v); //char *,size_t,char *,size_t); - bool getnext(std::string& n,std::string& v); //char *,size_t,char *,size_t); - - /* get value */ - int getvalue(const std::string& ,std::string& ); //char *,size_t); - std::string getvalue(const std::string& ); - size_t getlength(const std::string& ); - cgi_v& getbase(); - - const std::string& GetBoundary(); - -private: - HttpdForm(const HttpdForm& ) {} - HttpdForm& operator=(const HttpdForm& ) { return *this; } - cgi_v m_cgi; - cgi_v::iterator m_current; - std::string m_strBoundary; - bool raw; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _FORM_H diff --git a/common/SocketLib/HttpdSocket.cpp b/common/SocketLib/HttpdSocket.cpp deleted file mode 100644 index 21c2938d4..000000000 --- a/common/SocketLib/HttpdSocket.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/** \file HttpdSocket.cpp -*/ -/* -Copyright (C) 2001-2004,2005 Anders Hedstrom (grymse@alhem.net) - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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. -*/ -#ifdef _WIN32 -#pragma warning(disable:4786) -#endif -#include "../global_define.h" -#include "Utility.h" -#include "HttpdCookies.h" -#include "HttpdForm.h" -#include "MemFile.h" -#include "HttpdSocket.h" -#include "../types.h" -#include -#include -#include -#include - -#define DEB(x) -/* -#define DEB(x) { \ - FILE *fil = fopen("httpdlog","at"); \ - if (!fil) \ - fil = fopen("httpdlog","wt"); \ - if (fil) { x; fclose(fil); } \ -} -*/ - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - - -// statics -int HttpdSocket::m_request_count = 0; -std::string HttpdSocket::m_start = ""; - - -HttpdSocket::HttpdSocket(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -: HTTPSocket(ID,in_socket,irIP,irPort) -,m_content_length(0) -,m_file(nullptr) -,m_received(0) -,m_request_id(++m_request_count) -,m_cookies(nullptr) -,m_form(nullptr) -{ - m_http_date = datetime2httpdate(GetDate()); - if (!m_start.size()) - m_start = m_http_date; -} - - -HttpdSocket::~HttpdSocket() -{ - if (m_file) - { - delete m_file; - } - if (m_cookies) - delete m_cookies; - if (m_form) - delete m_form; -} - - -void HttpdSocket::OnFirst() -{ -// printf("Request: %s %s %s\n",GetMethod().c_str(),GetUrl().c_str(),GetHttpVersion().c_str()); -} - - -void HttpdSocket::OnHeader(const std::string& key,const std::string& value) -{ - if (!strcasecmp(key.c_str(),"content-length")) - { - m_content_length = atoi(value.c_str()); - m_content_length_str = value; - } - else - if (!strcasecmp(key.c_str(),"cookie")) - { - m_http_cookie = value; - } - else - if (!strcasecmp(key.c_str(),"content-type")) - { - m_content_type = value; - } - else - if (!strcasecmp(key.c_str(),"if-modified-since")) - { - m_if_modified_since = value; - } -} - - -void HttpdSocket::OnHeaderComplete() -{ - m_cookies = new HttpdCookies(m_http_cookie); - -#if (defined(SOLARIS8) || defined(SOLARIS)) - { - char slask[1000]; - if (GetMethod() == "GET") - { - sprintf(slask,"QUERY_STRING=%s", GetQueryString().c_str()); - putenv(slask); - } - sprintf(slask,"REQUEST_METHOD=%s", GetMethod().c_str()); - putenv(slask); - sprintf(slask,"HTTP_COOKIE=%s", m_http_cookie.c_str()); - putenv(slask); - sprintf(slask,"CONTENT_TYPE=%s", m_content_type.c_str()); - putenv(slask); - sprintf(slask,"CONTENT_LENGTH=%s", m_content_length_str.c_str()); - putenv(slask); - } -#elif defined _WIN32 - { - char slask[1000]; - if (GetMethod() == "GET") - { - sprintf(slask,"QUERY_STRING=%s", GetQueryString().c_str()); - _putenv(slask); - } - sprintf(slask,"REQUEST_METHOD=%s", GetMethod().c_str()); - _putenv(slask); - sprintf(slask,"HTTP_COOKIE=%s", m_http_cookie.c_str()); - _putenv(slask); - sprintf(slask,"CONTENT_TYPE=%s", m_content_type.c_str()); - _putenv(slask); - sprintf(slask,"CONTENT_LENGTH=%s", m_content_length_str.c_str()); - _putenv(slask); - } -#else - if (GetMethod() == "GET") - { - setenv("QUERY_STRING", GetQueryString().c_str(), 1); - } - setenv("REQUEST_METHOD", GetMethod().c_str(), 1); - setenv("HTTP_COOKIE", m_http_cookie.c_str(), 1); - setenv("CONTENT_TYPE", m_content_type.c_str(), 1); - setenv("CONTENT_LENGTH", m_content_length_str.c_str(), 1); -#endif - - if (GetMethod() == "POST") - { - m_file = new MemFile; - } - else - if (GetMethod() == "GET") - { - m_form = new HttpdForm(GetQueryString(), GetQueryString().size() ); - AddResponseHeader("Date", datetime2httpdate(GetDate()) ); - Exec(); - Reset(); // prepare for next request - } - else - { - AddResponseHeader("Date", GetHttpDate()); - AddResponseHeader("Connection", "close"); - SetStatus("405"); - SetStatusText("Method not allowed"); - SendResponse(); - } -} - - -void HttpdSocket::OnData(const char *p,size_t l) -{ - if (m_file) - { - m_file -> fwrite(p,1,l); - } - m_received += l; - if (m_received >= m_content_length && m_content_length) - { - // all done - if (m_file && !m_form) - { - m_form = new HttpdForm(m_file); - AddResponseHeader("Date", datetime2httpdate(GetDate()) ); - Exec(); - Reset(); // prepare for next request - } - } -} - - -void HttpdSocket::Send64(const std::string& str64, const std::string& type) -{ - if (!strcasecmp(m_start.c_str(), m_if_modified_since.c_str())) - { - SetStatus("304"); - SetStatusText("Not Modified"); - SendResponse(); - } - else - { - size_t len = Base64::decode_length(str64); - unsigned char *buf = new unsigned char[len]; - - SetStatus("200"); - SetStatusText("OK"); - - AddResponseHeader("Content-length", Utility::l2string( (long)len) ); - AddResponseHeader("Content-type", type ); - AddResponseHeader("Last-modified", m_start); - SendResponse(); - - Base64::decode(str64, buf, len); - SendBuf( (char *)buf, len); - delete[] buf; - } -} - - -std::string HttpdSocket::datetime2httpdate(const std::string& dt) -{ - struct tm tp; - time_t t; - const char *days[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; - const char *months[] = { "Jan","Feb","Mar","Apr","May","Jun", - "Jul","Aug","Sep","Oct","Nov","Dec" }; - int i; - char s[40]; - -/* 1997-12-16 09:50:40 */ - - if (dt.size() == 19) - { - tp.tm_year = atoi(dt.substr(0,4).c_str()) - 1900; - i = atoi(dt.substr(5,2).c_str()) - 1; - tp.tm_mon = i >= 0 ? i : 0; - tp.tm_mday = atoi(dt.substr(8,2).c_str()); - tp.tm_hour = atoi(dt.substr(11,2).c_str()); - tp.tm_min = atoi(dt.substr(14,2).c_str()); - tp.tm_sec = atoi(dt.substr(17,2).c_str()); - tp.tm_wday = 0; - tp.tm_yday = 0; - tp.tm_isdst = 0; - t = mktime(&tp); - /*if (t == -1) - { - Handler().LogError(this, "datetime2httpdate", 0, "mktime() failed"); - }*/ - - sprintf(s,"%s, %02d %s %d %02d:%02d:%02d GMT", - days[tp.tm_wday], - tp.tm_mday, - months[tp.tm_mon], - tp.tm_year + 1900, - tp.tm_hour,tp.tm_min,tp.tm_sec); - } - else - { - *s = 0; - } - return s; -} - - -std::string HttpdSocket::GetDate() -{ - time_t t = time(nullptr); - struct tm* tp = localtime(&t); - char slask[40]; - if (tp) - { - sprintf(slask,"%d-%02d-%02d %02d:%02d:%02d", - tp -> tm_year + 1900, - tp -> tm_mon + 1, - tp -> tm_mday, - tp -> tm_hour,tp -> tm_min,tp -> tm_sec); - } - else - { - *slask = 0; - } - return slask; -} - - -void HttpdSocket::Reset() -{ - HTTPSocket::Reset(); - m_content_length = 0; - if (m_file) - { - delete m_file; - m_file = nullptr; - } - m_received = 0; - m_request_id = ++m_request_count; - if (m_cookies) - delete m_cookies; - m_cookies = nullptr; - if (m_form) - delete m_form; - m_form = nullptr; -} - - -const std::string& HttpdSocket::GetHttpDate() -{ - return m_http_date; -} - - -HttpdCookies *HttpdSocket::GetCookies() -{ - return m_cookies; -} - - -HttpdForm *HttpdSocket::GetHttpForm() -{ - return m_form; -} - - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/HttpdSocket.h b/common/SocketLib/HttpdSocket.h deleted file mode 100644 index 33d0f4a1f..000000000 --- a/common/SocketLib/HttpdSocket.h +++ /dev/null @@ -1,99 +0,0 @@ -/** \file HttpdSocket.h -*/ -/* -Copyright (C) 2001-2004,2005 Anders Hedstrom (grymse@alhem.net) - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _HTTPDSOCKET_H -#define _HTTPDSOCKET_H - -#include "HTTPSocket.h" - -class TCPConnection; - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -class HttpdCookies; -class HttpdForm; -class IFile; - -/** \defgroup webserver Webserver framework */ -/** Web server socket framework. - \ingroup webserver */ -class HttpdSocket : public HTTPSocket -{ -public: - HttpdSocket(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort); - ~HttpdSocket(); - - void OnFirst(); - void OnHeader(const std::string& key,const std::string& value); - void OnHeaderComplete(); - void OnData(const char *,size_t); - - /** This method needs to be implemented with logic to produce - a response to an incoming request. */ - virtual void Exec() = 0; - /** Get current date in http rfc format. */ - const std::string& GetHttpDate(); - /** Get pointer to cookie class. */ - HttpdCookies *GetCookies(); - /** Get pointer to query string/form data class. */ - HttpdForm *GetHttpForm(); - -protected: - /** Decode and send a base64-encoded string. - \param str64 Base64-encoded string - \param type Mime type of content (content-type header) */ - void Send64(const std::string& str64, const std::string& type); - std::string datetime2httpdate(const std::string& dt); - std::string GetDate(); - void Reset(); - // headers - std::string m_http_cookie; - std::string m_content_type; - std::string m_content_length_str; - std::string m_if_modified_since; - -private: -static int m_request_count; -static std::string m_start; - size_t m_content_length; - IFile *m_file; - size_t m_received; - int m_request_id; - std::string m_http_date; - HttpdCookies *m_cookies; - HttpdForm *m_form; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _HTTPDSOCKET_H diff --git a/common/SocketLib/IFile.h b/common/SocketLib/IFile.h deleted file mode 100644 index 3eb2c59ba..000000000 --- a/common/SocketLib/IFile.h +++ /dev/null @@ -1,65 +0,0 @@ -/** \file IFile.h - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _IFILE_H -#define _IFILE_H - -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -/** \defgroup file File handling */ -/** Pure virtual file I/O interface. - \ingroup file */ -class IFile -{ -public: - virtual ~IFile() {} - - virtual bool fopen(const std::string&, const std::string&) = 0; - virtual void fclose() = 0; - - virtual size_t fread(char *, size_t, size_t) = 0; - virtual size_t fwrite(const char *, size_t, size_t) = 0; - - virtual char *fgets(char *, int) = 0; - virtual void fprintf(char *format, ...) = 0; - - virtual off_t size() = 0; - virtual bool eof() = 0; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _IFILE_H diff --git a/common/SocketLib/MemFile.cpp b/common/SocketLib/MemFile.cpp deleted file mode 100644 index c621666e5..000000000 --- a/common/SocketLib/MemFile.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/** \file MemFile.cpp - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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. -*/ -#ifdef _WIN32 -#pragma warning(disable:4786) -#endif -#include -#include - -#include "MemFile.h" -#include -#include - -#ifdef _DEBUG -#define DEB(x) x -#else -#define DEB(x) -#endif - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -std::map MemFile::m_files; - - -MemFile::MemFile() -:m_temporary(true) -,m_base(new block_t) -,m_current_read(m_base) -,m_current_write(m_base) -,m_read_ptr(0) -,m_write_ptr(0) -{ -} - - -MemFile::MemFile(const std::string& path) -:m_path(path) -,m_temporary(false) -,m_base(m_files[path]) -,m_current_read(nullptr) -,m_current_write(nullptr) -,m_read_ptr(0) -,m_write_ptr(0) -{ - if (!m_base) - { - m_base = new block_t; - m_files[path] = m_base; - } - m_current_read = m_base; - m_current_write = m_base; -} - - -MemFile::~MemFile() -{ - while (m_base && m_temporary) - { - block_t *p = m_base; - m_base = p -> next; - delete p; - } -} - - -bool MemFile::fopen(const std::string& path, const std::string& mode) -{ - return true; -} - - -void MemFile::fclose() -{ -} - - - -size_t MemFile::fread(char *ptr, size_t size, size_t nmemb) -{ - size_t p = m_read_ptr % BLOCKSIZE; - size_t sz = size * nmemb; - if (p + sz < BLOCKSIZE) - { - memcpy(ptr, m_current_read -> data + p, sz); - m_read_ptr += sz; - } - else - { - size_t sz1 = BLOCKSIZE - p; - size_t sz2 = size - sz1; - memcpy(ptr, m_current_read -> data + p, sz1); - m_read_ptr += sz1; - if (m_current_read -> next) - { - m_current_read = m_current_read -> next; - memcpy(ptr + sz1, m_current_read -> data, sz2); - m_read_ptr += sz2; - } - else - { -DEB(printf("Read beyond available data\n");) - return sz1; - } - } - return sz; -} - - -size_t MemFile::fwrite(const char *ptr, size_t size, size_t nmemb) -{ - size_t p = m_write_ptr % BLOCKSIZE; - size_t sz = size * nmemb; - if (p + sz < BLOCKSIZE) - { - memcpy(m_current_write -> data + p, ptr, sz); - m_write_ptr += sz; - } - else - { - size_t sz1 = BLOCKSIZE - p; - size_t sz2 = size - sz1; - memcpy(m_current_write -> data + p, ptr, sz1); - block_t *next = new block_t; - m_current_write -> next = next; - m_current_write = next; - memcpy(m_current_write -> data, ptr + sz1, sz2); - m_write_ptr += sz; - } - return sz; -} - - - -char *MemFile::fgets(char *s, int size) -{ - int n = 0; - while (n < size - 1 && !eof()) - { - char c; - fread(&c, 1, 1); - if (c == 10) - { - s[n] = 0; - return s; - } - s[n++] = c; - } - s[n] = 0; - return s; -} - - -void MemFile::fprintf(char *format, ...) -{ - va_list ap; - char tmp[BLOCKSIZE]; - va_start(ap, format); -#ifdef _WIN32 - vsprintf(tmp, format, ap); -#else - vsnprintf(tmp, BLOCKSIZE - 1, format, ap); -#endif - va_end(ap); - fwrite(tmp, 1, strlen(tmp)); -} - - -off_t MemFile::size() -{ - return (off_t)m_write_ptr; -} - - -bool MemFile::eof() -{ - return (m_read_ptr < m_write_ptr) ? false : true; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/MemFile.h b/common/SocketLib/MemFile.h deleted file mode 100644 index de777e424..000000000 --- a/common/SocketLib/MemFile.h +++ /dev/null @@ -1,93 +0,0 @@ -/** \file MemFile.h - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _MEMFILE_H -#define _MEMFILE_H - -#include -#include "IFile.h" - -#define BLOCKSIZE 32768 - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -/** Implements a memory file. - \ingroup file */ -class MemFile : public IFile -{ -public: - /** File block structure. - \ingroup file */ - struct block_t { - block_t() : next(nullptr) {} - struct block_t *next; - char data[BLOCKSIZE]; - }; -public: - MemFile(); - MemFile(const std::string& path); - ~MemFile(); - - bool fopen(const std::string& path, const std::string& mode); - void fclose(); - - size_t fread(char *ptr, size_t size, size_t nmemb); - size_t fwrite(const char *ptr, size_t size, size_t nmemb); - - char *fgets(char *s, int size); - void fprintf(char *format, ...); - - off_t size(); - bool eof(); - -private: - MemFile(const MemFile& ) {} // copy constructor - MemFile& operator=(const MemFile& ) { return *this; } // assignment operator - -static std::map m_files; - std::string m_path; - bool m_temporary; - block_t *m_base; - block_t *m_current_read; - block_t *m_current_write; - size_t m_read_ptr; - size_t m_write_ptr; -}; - - - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _MEMFILE_H diff --git a/common/SocketLib/Mime.cpp b/common/SocketLib/Mime.cpp deleted file mode 100644 index 282a34e77..000000000 --- a/common/SocketLib/Mime.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/** - ** File ......... Mime.cpp - ** Published .... 2004-07-13 - ** Author ....... grymse@alhem.net -**/ -/* -Copyright (C) 2004 Anders Hedstrom - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 - -#include "Parse.h" -#include "Mime.h" -#include - - - -Mime::Mime() { -} - -Mime::Mime(const std::string& filename) { - LoadMimeFile(filename); -} - -bool Mime::LoadMimeFile(const std::string& filename) { - FILE *fil; - if ((fil = fopen(filename.c_str(),"rt")) != nullptr) { - char * slask = new char[1000]; - fgets(slask,1000,fil); - while (!feof(fil)) - { - while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10)) - { - slask[strlen(slask) - 1] = 0; - } - Parse pa(slask); - std::string mime_type = pa.getword(); - std::string ext = pa.getword(); - while (ext.size()) - { - m_mime[ext] = mime_type; - ext = pa.getword(); - } - // - fgets(slask,1000,fil); - } - delete[] slask; - fclose(fil); - return(true); - } - return(false); -} - - -Mime::~Mime() -{ -} - -void Mime::Clear() { - m_mime.clear(); -} - -std::string Mime::GetMimeFromFilename(const std::string &filename) const { - std::string::size_type pos = filename.find_last_of('.'); - if(pos == std::string::npos) - return(std::string("text/plain")); - return(GetMimeFromExtension(filename.substr(pos+1))); -} - -std::string Mime::GetMimeFromExtension(const std::string& ext) const { - mime_m::const_iterator res; - res = m_mime.find(ext); - if(res == m_mime.end()) - return(std::string("text/plain")); - - return res->second; -} - - diff --git a/common/SocketLib/Mime.h b/common/SocketLib/Mime.h deleted file mode 100644 index 337f9397a..000000000 --- a/common/SocketLib/Mime.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - ** File ......... Mime.h - ** Published .... 2004-07-13 - ** Author ....... grymse@alhem.net -**/ -/* -Copyright (C) 2004 Anders Hedstrom - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _MIME_H -#define _MIME_H - -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -class Mime { - typedef std::map mime_m; -public: - Mime(); - Mime(const std::string& mime_file); - ~Mime(); - - void Clear(); - bool LoadMimeFile(const std::string& mime_file); - - std::string GetMimeFromFilename(const std::string &filename) const; - std::string GetMimeFromExtension(const std::string &ext) const; - -private: - mime_m m_mime; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _MIME_H diff --git a/common/SocketLib/Parse.cpp b/common/SocketLib/Parse.cpp deleted file mode 100644 index 946c83e68..000000000 --- a/common/SocketLib/Parse.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/** \file Parse.cpp - parse a string - ** - ** Written: 1999-Feb-10 grymse@alhem.net - **/ - -/* -Copyright (C) 1999-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 -#include -#include - -#include "Parse.h" - -#ifdef _DEBUG -#define DEB(x) -#else -#define DEB(x) -#endif - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -/* implementation of class Parse */ - -Parse::Parse() -:pa_the_str("") -,pa_splits("") -,pa_ord("") -,pa_the_ptr(0) -,pa_breakchar(0) -,pa_enable(0) -,pa_disable(0) -,pa_nospace(0) -,pa_quote(false) -{ -} - -Parse::Parse(const std::string&s) -:pa_the_str(s) -,pa_splits("") -,pa_ord("") -,pa_the_ptr(0) -,pa_breakchar(0) -,pa_enable(0) -,pa_disable(0) -,pa_nospace(0) -,pa_quote(false) -{ -} - -Parse::Parse(const std::string&s,const std::string&sp) -:pa_the_str(s) -,pa_splits(sp) -,pa_ord("") -,pa_the_ptr(0) -,pa_breakchar(0) -,pa_enable(0) -,pa_disable(0) -,pa_nospace(0) -,pa_quote(false) -{ -} - -Parse::Parse(const std::string&s,const std::string&sp,short nospace) -:pa_the_str(s) -,pa_splits(sp) -,pa_ord("") -,pa_the_ptr(0) -,pa_breakchar(0) -,pa_enable(0) -,pa_disable(0) -,pa_nospace(1) -,pa_quote(false) -{ -} - - -Parse::~Parse() -{ -} - -#define C ((pa_the_ptr - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -/***************************************************/ -/* interface of class Parse */ - -/** Splits a string whatever way you want. - \ingroup util */ -class Parse -{ -public: - Parse(); - Parse(const std::string&); - Parse(const std::string&,const std::string&); - Parse(const std::string&,const std::string&,short); - ~Parse(); - short issplit(char); - void getsplit(void); - void getsplit(std::string&); - std::string getword(void); - void getword(std::string&); - void getword(std::string&,std::string&,int); - std::string getrest(); - void getrest(std::string&); - long getvalue(void); - void setbreak(char); - int getwordlen(void); - int getrestlen(void); - void enablebreak(char c) { - pa_enable = c; - } - void disablebreak(char c) { - pa_disable = c; - } - void getline(void); - void getline(std::string&); - size_t getptr(void) { return pa_the_ptr; } - void EnableQuote(bool b) { pa_quote = b; } - -private: - std::string pa_the_str; - std::string pa_splits; - std::string pa_ord; - size_t pa_the_ptr; - char pa_breakchar; - char pa_enable; - char pa_disable; - short pa_nospace; - bool pa_quote; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _PARSE_H diff --git a/common/SocketLib/README.eqemu b/common/SocketLib/README.eqemu deleted file mode 100644 index 4d14b5332..000000000 --- a/common/SocketLib/README.eqemu +++ /dev/null @@ -1,5 +0,0 @@ -EQEmu took this code from `C++ Sockets Library` -http://www.alhem.net/Sockets/ -and integrated it into our world server. We did not care for the actual -socket code (didnt work on windows) so we scrapped all of it, and just -used the HTTP framework code. diff --git a/common/SocketLib/README.macosx b/common/SocketLib/README.macosx deleted file mode 100644 index ee23d974a..000000000 --- a/common/SocketLib/README.macosx +++ /dev/null @@ -1,5 +0,0 @@ -Find uuid.h here - http://www.die.net/doc/linux/include/uuid/uuid.h -or here - http://www.thedna.net/uuid.h - diff --git a/common/SocketLib/Utility.cpp b/common/SocketLib/Utility.cpp deleted file mode 100644 index e3c411fbb..000000000 --- a/common/SocketLib/Utility.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/** \file Utility.cpp - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 "Utility.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -std::string Utility::base64(const std::string& str_in) -{ - std::string str; - Base64::encode(str_in, str, false); // , false == do not add cr/lf - return str; -} - - -std::string Utility::base64d(const std::string& str_in) -{ - std::string str; - Base64::decode(str_in, str); - return str; -} - - -std::string Utility::l2string(long l) -{ - std::string str; - char tmp[100]; - sprintf(tmp,"%ld",l); - str = tmp; - return str; -} - - -std::string Utility::bigint2string(uint64_t l) -{ - std::string str; - uint64_t tmp = l; - while (tmp) - { - uint64_t a = tmp % 10; - str = (char)(a + 48) + str; - tmp /= 10; - } - if (!str.size()) - { - str = "0"; - } - return str; -} - - -uint64_t Utility::atoi64(const std::string& str) -{ - uint64_t l = 0; - for (size_t i = 0; i < str.size(); i++) - { - l = l * 10 + str[i] - 48; - } - return l; -} - - -unsigned int Utility::hex2unsigned(const std::string& str) -{ - unsigned int r = 0; - for (size_t i = 0; i < str.size(); i++) - { - r = r * 16 + str[i] - 48 - ((str[i] >= 'A') ? 7 : 0) - ((str[i] >= 'a') ? 32 : 0); - } - return r; -} - - -/* -* Encode string per RFC1738 URL encoding rules -* tnx rstaveley -*/ -std::string Utility::rfc1738_encode(const std::string& src) -{ -static char hex[] = "0123456789ABCDEF"; - std::string dst; - for (size_t i = 0; i < src.size(); i++) - { - if (isalnum(src[i])) - { - dst += src[i]; - } - else - if (src[i] == ' ') - { - dst += '+'; - } - else - { - dst += '%'; - dst += hex[src[i] / 16]; - dst += hex[src[i] % 16]; - } - } - return dst; -} // rfc1738_encode - - -/* -* Decode string per RFC1738 URL encoding rules -* tnx rstaveley -*/ -std::string Utility::rfc1738_decode(const std::string& src) -{ - std::string dst; - for (size_t i = 0; i < src.size(); i++) - { - if (src[i] == '%' && isxdigit(src[i + 1]) && isxdigit(src[i + 2])) - { - char c1 = src[++i]; - char c2 = src[++i]; - c1 = c1 - 48 - ((c1 >= 'A') ? 7 : 0) - ((c1 >= 'a') ? 32 : 0); - c2 = c2 - 48 - ((c2 >= 'A') ? 7 : 0) - ((c2 >= 'a') ? 32 : 0); - dst += (char)(c1 * 16 + c2); - } - else - if (src[i] == '+') - { - dst += ' '; - } - else - { - dst += src[i]; - } - } - return dst; -} // rfc1738_decode - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/Utility.h b/common/SocketLib/Utility.h deleted file mode 100644 index 1100a99e2..000000000 --- a/common/SocketLib/Utility.h +++ /dev/null @@ -1,70 +0,0 @@ -/** \file Utility.h - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _UTILITY_H -#define _UTILITY_H - -#include -#ifdef _WIN32 -typedef unsigned __int64 uint64_t; -#else -#include -#ifdef SOLARIS -# include -#else -# include -#endif -#endif -#include "Base64.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -/** Conversion utilities. - \ingroup util */ -class Utility -{ -public: - static std::string base64(const std::string& str_in); - static std::string base64d(const std::string& str_in); - static std::string l2string(long l); - static std::string bigint2string(uint64_t l); - static uint64_t atoi64(const std::string& str); - static unsigned int hex2unsigned(const std::string& str); - static std::string rfc1738_encode(const std::string& src); - static std::string rfc1738_decode(const std::string& src); -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _UTILITY_H diff --git a/common/SocketLib/gpl.txt b/common/SocketLib/gpl.txt deleted file mode 100644 index 5b6e7c66c..000000000 --- a/common/SocketLib/gpl.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; 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 - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/common/SocketLib/socket_include.cpp b/common/SocketLib/socket_include.cpp deleted file mode 100644 index 353206dcc..000000000 --- a/common/SocketLib/socket_include.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** \file socket_include.cpp - ** \date 2004-11-28 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 - -// only to be included in win32 projects -const char *StrError(int x) -{ -static char tmp[100]; - switch (x) - { - case 10004: return "Interrupted function call."; - case 10013: return "Permission denied."; - case 10014: return "Bad address."; - case 10022: return "Invalid argument."; - case 10024: return "Too many open files."; - case 10035: return "Resource temporarily unavailable."; - case 10036: return "Operation now in progress."; - case 10037: return "Operation already in progress."; - case 10038: return "Socket operation on nonsocket."; - case 10039: return "Destination address required."; - case 10040: return "Message too long."; - case 10041: return "Protocol wrong type for socket."; - case 10042: return "Bad protocol option."; - case 10043: return "Protocol not supported."; - case 10044: return "Socket type not supported."; - case 10045: return "Operation not supported."; - case 10046: return "Protocol family not supported."; - case 10047: return "Address family not supported by protocol family."; - case 10048: return "Address already in use."; - case 10049: return "Cannot assign requested address."; - case 10050: return "Network is down."; - case 10051: return "Network is unreachable."; - case 10052: return "Network dropped connection on reset."; - case 10053: return "Software caused connection abort."; - case 10054: return "Connection reset by peer."; - case 10055: return "No buffer space available."; - case 10056: return "Socket is already connected."; - case 10057: return "Socket is not connected."; - case 10058: return "Cannot send after socket shutdown."; - case 10060: return "Connection timed out."; - case 10061: return "Connection refused."; - case 10064: return "Host is down."; - case 10065: return "No route to host."; - case 10067: return "Too many processes."; - case 10091: return "Network subsystem is unavailable."; - case 10092: return "Winsock.dll version out of range."; - case 10093: return "Successful WSAStartup not yet performed."; - case 10101: return "Graceful shutdown in progress."; - case 10109: return "Class type not found."; - case 11001: return "Host not found."; - case 11002: return "Nonauthoritative host not found."; - case 11003: return "This is a nonrecoverable error."; - case 11004: return "Valid name, no data record of requested type."; - - default: - break; - } - sprintf(tmp, "Winsock error code: %d", x); - return tmp; -} diff --git a/common/SocketLib/socket_include.h b/common/SocketLib/socket_include.h deleted file mode 100644 index c7489ffa3..000000000 --- a/common/SocketLib/socket_include.h +++ /dev/null @@ -1,218 +0,0 @@ -/** \file socket_include.h - ** \date 2005-04-12 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _SOCKET_INCLUDE_H -#define _SOCKET_INCLUDE_H - -#if (defined(__unix__) || defined(unix)) && !defined(USG) -#include -#endif - - -#ifndef _WIN32 -// ---------------------------------------- -// common unix includes / defines -#include -#include -#include -#include -#include -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -#define Errno errno -#define StrError strerror - -// WIN32 adapt -#define closesocket close -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 -typedef int SOCKET; - -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned long) -1) -#endif // INADDR_NONE - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // !_WIN32 - - -// ---------------------------------------- -// Generic -#ifndef SOL_IP -#define SOL_IP IPPROTO_IP -#endif - - -// ---------------------------------------- -// OS specific adaptions - -#ifdef SOLARIS -// ---------------------------------------- -// Solaris -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef unsigned short port_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - -#define s6_addr16 _S6_un._S6_u8 -#define MSG_NOSIGNAL 0 - -#elif defined __FreeBSD__ -// ---------------------------------------- -// FreeBSD -# if __FreeBSD_version >= 400014 -# define s6_addr16 __u6_addr.__u6_addr16 -# if !defined(MSG_NOSIGNAL) -# define MSG_NOSIGNAL 0 -# endif -# include -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef in_addr_t ipaddr_t; -typedef in_port_t port_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - -# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -# define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -# else -# error FreeBSD versions prior to 400014 does not support ipv6 -# endif - -#elif defined MACOSX -// ---------------------------------------- -// Mac OS X -#include -#include -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef unsigned long ipaddr_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - -#define s6_addr16 __u6_addr.__u6_addr16 -#define MSG_NOSIGNAL 0 // oops - thanks Derek -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP - -#elif defined _WIN32 -// ---------------------------------------- -// Win32 -#pragma comment(lib, "wsock32.lib") -#define strcasecmp _stricmp - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef unsigned long ipaddr_t; -typedef unsigned short port_t; -typedef int socklen_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - -#define MSG_NOSIGNAL 0 -#define SHUT_RDWR 2 - -// 1.8.6: define FD_SETSIZE to something bigger than 64 if there are a lot of -// simultaneous connections (must be done before including winsock.h) -//#define FD_SETSIZE 1024 -#include - -#define Errno WSAGetLastError() -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -const char *StrError(int x); - -// class WSAInitializer is a part of the Socket class (on win32) -// as a static instance - so whenever an application uses a Socket, -// winsock is initialized -class WSAInitializer // Winsock Initializer -{ -public: - WSAInitializer() { - if (WSAStartup(0x101,&m_wsadata)) - { - exit(-1); - } - } - ~WSAInitializer() { - WSACleanup(); - } -private: - WSADATA m_wsadata; -}; - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#else -// ---------------------------------------- -// LINUX -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef unsigned long ipaddr_t; -typedef unsigned short port_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - - -#endif - -#ifdef _THREADSAFE_SOCKETS -#include "mutex.h" -#include "Lock.h" -#endif - -#endif // _SOCKET_INCLUDE_H diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp deleted file mode 100644 index 5ae937137..000000000 --- a/common/eq_stream.cpp +++ /dev/null @@ -1,1440 +0,0 @@ -/* - Copyright (C) 2005 Michael S. Finger - - 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 "eq_stream.h" - -#include "common/crc16.h" -#include "common/eq_packet.h" -#include "common/eqemu_logsys.h" -#include "common/global_define.h" -#include "common/op_codes.h" -#include "common/platform.h" -#include "common/strings.h" - -#include -#include -#include -#include - -#ifdef _WINDOWS -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -//for logsys -#define _L "%s:%d: " -#define __L , long2ip(remote_ip).c_str(), ntohs(remote_port) - -uint16 EQStream::MaxWindowSize=2048; - -void EQStream::init(bool resetSession) { - // we only reset these statistics if it is a 'new' connection - if ( resetSession ) - { - streamactive = false; - sessionAttempts = 0; - } - active_users = 0; - Session=0; - Key=0; - MaxLen=0; - NextInSeq=0; - NextOutSeq=0; - NextAckToSend=-1; - LastAckSent=-1; - MaxSends=5; - LastPacket=0; - oversize_buffer=nullptr; - oversize_length=0; - oversize_offset=0; - RateThreshold=RATEBASE/250; - DecayRate=DECAYBASE/250; - BytesWritten=0; - sent_packet_count = 0; - received_packet_count = 0; - SequencedBase = 0; - AverageDelta = 500; - - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - retransmittimer = Timer::GetCurrentTime(); - retransmittimeout = 500 * RETRANSMIT_TIMEOUT_MULT; - } - - OpMgr = nullptr; - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "init Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); - } -} - -EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p) -{ - EQRawApplicationPacket *ap=nullptr; - LogNetcode(_L "Creating new application packet, length [{}]" __L, p->size); - // _raw(NET__APP_CREATE_HEX, 0xFFFF, p); - ap = p->MakeAppPacket(); - return ap; -} - -EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len) -{ - EQRawApplicationPacket *ap=nullptr; - LogNetcode(_L "Creating new application packet, length [{}]" __L, len); - ap = new EQRawApplicationPacket(buf, len); - return ap; -} - -EQProtocolPacket *EQStream::MakeProtocolPacket(const unsigned char *buf, uint32 len) { - uint16 proto_opcode = ntohs(*(const uint16 *)buf); - - //advance over opcode. - buf += 2; - len -= 2; - - return(new EQProtocolPacket(proto_opcode, buf, len)); -} - -void EQStream::ProcessPacket(EQProtocolPacket *p) -{ - uint32 processed=0, subpacket_length=0; - if (p == nullptr) - return; - // Raw Application packet - if (p->opcode > 0xff) { - p->opcode = htons(p->opcode); //byte order is backwards in the protocol packet - EQRawApplicationPacket *ap=MakeApplicationPacket(p); - if (ap) - InboundQueuePush(ap); - return; - } - - if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) { - LogNetcode(_L "Session not initialized, packet ignored" __L); - // _raw(NET__DEBUG, 0xFFFF, p); - return; - } - - switch (p->opcode) { - case OP_Combined: { - processed=0; - while(processed < p->size) { - subpacket_length=*(p->pBuffer+processed); - EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length); - LogNetcode(_L "Extracting combined packet of length [{}]" __L, subpacket_length); - // _raw(NET__NET_CREATE_HEX, 0xFFFF, subp); - subp->copyInfo(p); - ProcessPacket(subp); - delete subp; - processed+=subpacket_length+1; - } - } - break; - - case OP_AppCombined: { - processed=0; - while(processedsize) { - EQRawApplicationPacket *ap=nullptr; - if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))!=0xff) { - LogNetcode(_L "Extracting combined app packet of length [{}], short len" __L, subpacket_length); - ap=MakeApplicationPacket(p->pBuffer+processed+1,subpacket_length); - processed+=subpacket_length+1; - } else { - subpacket_length=ntohs(*(uint16 *)(p->pBuffer+processed+1)); - LogNetcode(_L "Extracting combined app packet of length [{}], short len" __L, subpacket_length); - ap=MakeApplicationPacket(p->pBuffer+processed+3,subpacket_length); - processed+=subpacket_length+3; - } - if (ap) { - ap->copyInfo(p); - InboundQueuePush(ap); - } - } - } - break; - - case OP_Packet: { - if(!p->pBuffer || (p->Size() < 4)) - { - LogNetcode(_L "Received OP_Packet that was of malformed size" __L); - break; - } - uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); - SeqOrder check=CompareSequence(NextInSeq,seq); - if (check == SeqFuture) { - LogNetcode(_L "Future OP_Packet: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); - // _raw(NET__DEBUG, seq, p); - - PacketQueue[seq]=p->Copy(); - LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); - - //SendOutOfOrderAck(seq); - - } else if (check == SeqPast) { - LogNetcode(_L "Duplicate OP_Packet: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); - // _raw(NET__DEBUG, seq, p); - SendOutOfOrderAck(seq); //we already got this packet but it was out of order - } else { - // In case we did queue one before as well. - EQProtocolPacket *qp=RemoveQueue(seq); - if (qp) { - LogNetcode("[NET_TRACE] OP_Packet: Removing older queued packet with sequence [{}]", seq); - delete qp; - } - - SetNextAckToSend(seq); - NextInSeq++; - // Check for an embedded OP_AppCombinded (protocol level 0x19) - if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { - EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+2,p->size-2); - LogNetcode(_L "seq [{}], Extracting combined packet of length [{}]" __L, seq, subp->size); - // _raw(NET__NET_CREATE_HEX, seq, subp); - subp->copyInfo(p); - ProcessPacket(subp); - delete subp; - } else { - EQRawApplicationPacket *ap=MakeApplicationPacket(p->pBuffer+2,p->size-2); - if (ap) { - ap->copyInfo(p); - InboundQueuePush(ap); - } - } - } - } - break; - - case OP_Fragment: { - if(!p->pBuffer || (p->Size() < 4)) - { - LogNetcode(_L "Received OP_Fragment that was of malformed size" __L); - break; - } - uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); - SeqOrder check=CompareSequence(NextInSeq,seq); - if (check == SeqFuture) { - LogNetcode(_L "Future OP_Fragment: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); - // _raw(NET__DEBUG, seq, p); - - PacketQueue[seq]=p->Copy(); - LogNetcode(_L "OP_Fragment Queue size=[{}]" __L, PacketQueue.size()); - - //SendOutOfOrderAck(seq); - - } else if (check == SeqPast) { - LogNetcode(_L "Duplicate OP_Fragment: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); - // _raw(NET__DEBUG, seq, p); - SendOutOfOrderAck(seq); - } else { - // In case we did queue one before as well. - EQProtocolPacket *qp=RemoveQueue(seq); - if (qp) { - LogNetcode("[NET_TRACE] OP_Fragment: Removing older queued packet with sequence [{}]", seq); - delete qp; - } - SetNextAckToSend(seq); - NextInSeq++; - if (oversize_buffer) { - memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2); - oversize_offset+=p->size-2; - LogNetcode(_L "Fragment of oversized of length [{}], seq [{}]: now at [{}]/[{}]" __L, p->size-2, seq, oversize_offset, oversize_length); - if (oversize_offset==oversize_length) { - if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { - EQProtocolPacket *subp=MakeProtocolPacket(oversize_buffer,oversize_offset); - LogNetcode(_L "seq [{}], Extracting combined oversize packet of length [{}]" __L, seq, subp->size); - //// _raw(NET__NET_CREATE_HEX, subp); - subp->copyInfo(p); - ProcessPacket(subp); - delete subp; - } else { - EQRawApplicationPacket *ap=MakeApplicationPacket(oversize_buffer,oversize_offset); - LogNetcode(_L "seq [{}], completed combined oversize packet of length [{}]" __L, seq, ap->size); - if (ap) { - ap->copyInfo(p); - InboundQueuePush(ap); - } - } - delete[] oversize_buffer; - oversize_buffer=nullptr; - oversize_offset=0; - } - } else { - oversize_length=ntohl(*(uint32 *)(p->pBuffer+2)); - oversize_buffer=new unsigned char[oversize_length]; - memcpy(oversize_buffer,p->pBuffer+6,p->size-6); - oversize_offset=p->size-6; - LogNetcode(_L "First fragment of oversized of seq [{}]: now at [{}]/[{}]" __L, seq, oversize_offset, oversize_length); - } - } - } - break; - case OP_KeepAlive: { - NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size)); - LogNetcode(_L "Received and queued reply to keep alive" __L); - } - break; - case OP_Ack: { - if(!p->pBuffer || (p->Size() < 4)) - { - LogNetcode(_L "Received OP_Ack that was of malformed size" __L); - break; - } - uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); - AckPackets(seq); - - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - retransmittimer = Timer::GetCurrentTime(); - } - } - break; - case OP_SessionRequest: { - if(p->Size() < sizeof(SessionRequest)) - { - LogNetcode(_L "Received OP_SessionRequest that was of malformed size" __L); - break; - } - if (GetState()==ESTABLISHED) { - LogNetcode(_L "Received OP_SessionRequest in ESTABLISHED state ([{}]) streamactive ([{}]) attempt ([{}])" __L, GetState(),streamactive,sessionAttempts); - - // client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case - // streamactive means we identified the opcode for the stream, we cannot re-establish this connection - if ( streamactive || ( sessionAttempts > MAX_SESSION_RETRIES ) ) - { - _SendDisconnect(); - SetState(CLOSED); - break; - } - } - sessionAttempts++; - // we set established below, so statistics will not be reset for session attempts/stream active. - init(GetState()!=ESTABLISHED); - OutboundQueueClear(); - SessionRequest *Request=(SessionRequest *)p->pBuffer; - Session=ntohl(Request->Session); - SetMaxLen(ntohl(Request->MaxLength)); - LogNetcode(_L "Received OP_SessionRequest: session [{}], maxlen [{}]" __L, (unsigned long)Session, MaxLen); - SetState(ESTABLISHED); - Key=0x11223344; - SendSessionResponse(); - } - break; - case OP_SessionResponse: { - if(p->Size() < sizeof(SessionResponse)) - { - LogNetcode(_L "Received OP_SessionResponse that was of malformed size" __L); - break; - } - - init(); - OutboundQueueClear(); - SessionResponse *Response=(SessionResponse *)p->pBuffer; - SetMaxLen(ntohl(Response->MaxLength)); - Key=ntohl(Response->Key); - NextInSeq=0; - SetState(ESTABLISHED); - if (!Session) - Session=ntohl(Response->Session); - compressed=(Response->Format&FLAG_COMPRESSED); - encoded=(Response->Format&FLAG_ENCODED); - - LogNetcode(_L "Received OP_SessionResponse: session [{}], maxlen [{}], key [{}], compressed? [{}], encoded? [{}]" __L, (unsigned long)Session, MaxLen, (unsigned long)Key, compressed?"yes":"no", encoded?"yes":"no"); - - // Kinda kludgy, but trie for now - if (StreamType==UnknownStream) { - if (compressed) { - if (remote_port==9000 || (remote_port==0 && p->src_port==9000)) { - SetStreamType(WorldStream); - } else { - SetStreamType(ZoneStream); - } - } else if (encoded) { - SetStreamType(ChatOrMailStream); - } else { - SetStreamType(LoginStream); - } - } - } - break; - case OP_SessionDisconnect: { - //NextInSeq=0; - EQStreamState state = GetState(); - if(state == ESTABLISHED) { - //client initiated disconnect? - LogNetcode(_L "Received unsolicited OP_SessionDisconnect. Treating like a client-initiated disconnect" __L); - _SendDisconnect(); - SetState(CLOSED); - } else if(state == CLOSING) { - //we were waiting for this anyways, ignore pending messages, send the reply and be closed. - LogNetcode(_L "Received OP_SessionDisconnect when we have a pending close, they beat us to it. Were happy though" __L); - _SendDisconnect(); - SetState(CLOSED); - } else { - //we are expecting this (or have already gotten it, but dont care either way) - LogNetcode(_L "Received expected OP_SessionDisconnect. Moving to closed state" __L); - SetState(CLOSED); - } - } - break; - case OP_OutOfOrderAck: { - if(!p->pBuffer || (p->Size() < 4)) - { - LogNetcode(_L "Received OP_OutOfOrderAck that was of malformed size" __L); - break; - } - uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); - MOutboundQueue.lock(); - - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "Pre-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - - //if the packet they got out of order is between our last acked packet and the last sent packet, then its valid. - if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) { - Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L, - seq, SequencedBase, SequencedBase+SequencedQueue.size()); - - uint16 sqsize = SequencedQueue.size(); - uint16 index = seq - SequencedBase; - LogNetcode(_L "OP_OutOfOrderAck marking packet acked in queue (queue index = [{}], queue size = [{}])" __L, index, sqsize); - if (index < sqsize) { - SequencedQueue[index]->acked = true; - // flag packets for a resend - uint16 count = 0; - uint32 timeout = AverageDelta * 2 + 100; - for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) { - if (!(*sitr)->acked && (*sitr)->sent_time > 0 && (((*sitr)->sent_time + timeout) < Timer::GetCurrentTime())) { - (*sitr)->sent_time = 0; - LogNetcode(_L "OP_OutOfOrderAck Flagging packet [{}] for retransmission" __L, SequencedBase + count); - } - } - } - - if(RETRANSMIT_TIMEOUT_MULT) { - retransmittimer = Timer::GetCurrentTime(); - } - } else { - LogNetcode(_L "Received OP_OutOfOrderAck for out-of-window [{}]. Window ([{}]->[{}])" __L, seq, SequencedBase, NextOutSeq); - } - - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "Post-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - - MOutboundQueue.unlock(); - } - break; - case OP_SessionStatRequest: { - if(p->Size() < sizeof(ClientSessionStats)) - { - LogNetcode(_L "Received OP_SessionStatRequest that was of malformed size" __L); - break; - } - ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer; - Log(Logs::Detail, Logs::Netcode, _L "Received Stats: %lu packets received, %lu packets sent, Deltas: local %lu, (%lu <- %lu -> %lu) remote %lu" __L, - (unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta), - (unsigned long)ntohl(ClientStats->low_delta), (unsigned long)ntohl(ClientStats->average_delta), - (unsigned long)ntohl(ClientStats->high_delta), (unsigned long)ntohl(ClientStats->last_remote_delta)); - - AdjustRates(ntohl(ClientStats->average_delta)); - - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - if (RETRANSMIT_TIMEOUT_MULT && ntohl(ClientStats->average_delta)) { - //recalculate retransmittimeout using the larger of the last rtt or average rtt, which is multiplied by the rule value - if ((ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta)) > (ntohl(ClientStats->average_delta) * 2)) { - retransmittimeout = (ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta)) - * RETRANSMIT_TIMEOUT_MULT; - } else { - retransmittimeout = ntohl(ClientStats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT; - } - retransmittimeout += 300; - if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX) - retransmittimeout = RETRANSMIT_TIMEOUT_MAX; - LogNetcode(_L "Retransmit timeout recalculated to [{}]ms" __L, retransmittimeout); - } - } - - ServerSessionStats *ServerStats = (ServerSessionStats *)p->pBuffer; - - //ServerStats->RequestID = ClientStats->RequestID; // no change - ServerStats->ServerTime = htonl(Timer::GetCurrentTime()); - ServerStats->packets_sent_echo = ClientStats->packets_sent; // still in htonll format - ServerStats->packets_received_echo = ClientStats->packets_received; // still in htonll format - ServerStats->packets_sent = htonll(GetPacketsSent()); - ServerStats->packets_received = htonll(GetPacketsReceived()); - - NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse, p->pBuffer, p->size)); - } - break; - case OP_SessionStatResponse: { - LogNetcode(_L "Received OP_SessionStatResponse. Ignoring" __L); - } - break; - case OP_OutOfSession: { - LogNetcode(_L "Received OP_OutOfSession. Ignoring" __L); - } - break; - default: - EQRawApplicationPacket *ap = MakeApplicationPacket(p); - if (ap) - InboundQueuePush(ap); - break; - } -} - -void EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) -{ - if(p == nullptr) - return; - - EQApplicationPacket *newp = p->Copy(); - - if (newp != nullptr) - FastQueuePacket(&newp, ack_req); -} - -void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req) -{ - EQApplicationPacket *pack=*p; - *p = nullptr; //clear caller's pointer.. effectively takes ownership - - if(pack == nullptr) - return; - - if(OpMgr == nullptr || *OpMgr == nullptr) { - LogNetcode(_L "Packet enqueued into a stream with no opcode manager, dropping" __L); - delete pack; - return; - } - - uint16 opcode = 0; - if(pack->GetOpcodeBypass() != 0) { - opcode = pack->GetOpcodeBypass(); - } else { - opcode = (*OpMgr)->EmuToEQ(pack->GetOpcode()); - } - - if (!ack_req) { - NonSequencedPush(new EQProtocolPacket(opcode, pack->pBuffer, pack->size)); - delete pack; - } else { - SendPacket(opcode, pack); - } -} - -void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) -{ - uint32 chunksize, used; - uint32 length; - - if (EQEmuLogSys::Instance()->log_settings[Logs::Server_Client_Packet].is_category_enabled == 1){ - if (p->GetOpcode() != OP_SpecialMesg){ - Log(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size()); - } - } - - if (EQEmuLogSys::Instance()->log_settings[Logs::Server_Client_Packet_With_Dump].is_category_enabled == 1){ - if (p->GetOpcode() != OP_SpecialMesg){ - Log(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str()); - } - } - - // Convert the EQApplicationPacket to 1 or more EQProtocolPackets - if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2) - LogNetcode(_L "Making oversized packet, len [{}]" __L, p->Size()); - - auto tmpbuff = new unsigned char[p->size + 3]; - length=p->serialize(opcode, tmpbuff); - if (length != p->Size()) - LogNetcode(_L "Packet adjustment, len [{}] to [{}]" __L, p->Size(), length); - - auto out = new EQProtocolPacket(OP_Fragment, nullptr, MaxLen - 4); - *(uint32 *)(out->pBuffer+2)=htonl(length); - used=MaxLen-10; - memcpy(out->pBuffer+6,tmpbuff,used); - LogNetcode(_L "First fragment: used [{}]/[{}]. Payload size [{}] in the packet" __L, used, length, p->size); - SequencedPush(out); - - - while (usedpBuffer+2,tmpbuff+used,chunksize); - out->size=chunksize+2; - SequencedPush(out); - used+=chunksize; - LogNetcode(_L "Subsequent fragment: len [{}], used [{}]/[{}]" __L, chunksize, used, length); - } - delete p; - delete[] tmpbuff; - } else { - - auto tmpbuff = new unsigned char[p->Size() + 3]; - length=p->serialize(opcode, tmpbuff+2) + 2; - - auto out = new EQProtocolPacket(OP_Packet, tmpbuff, length); - - delete[] tmpbuff; - SequencedPush(out); - delete p; - } -} - -void EQStream::SequencedPush(EQProtocolPacket *p) -{ - MOutboundQueue.lock(); - if (uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log(Logs::Detail, Logs::Netcode, _L "Pre-Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, - SequencedBase, SequencedQueue.size(), NextOutSeq); - } - - Log(Logs::Detail, Logs::Netcode, _L "Pushing sequenced packet %d of length %d. Base Seq is %d." __L, - NextOutSeq, p->size, SequencedBase); - *(uint16 *)(p->pBuffer) = htons(NextOutSeq); - SequencedQueue.push_back(p); - NextOutSeq++; - - if (uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log(Logs::Detail, Logs::Netcode, _L "Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, - SequencedBase, SequencedQueue.size(), NextOutSeq); - } - - MOutboundQueue.unlock(); -} - -void EQStream::NonSequencedPush(EQProtocolPacket *p) -{ - MOutboundQueue.lock(); - LogNetcode(_L "Pushing non-sequenced packet of length [{}]" __L, p->size); - NonSequencedQueue.push(p); - MOutboundQueue.unlock(); -} - -void EQStream::SendAck(uint16 seq) -{ -uint16 Seq=htons(seq); - LogNetcode(_L "Sending ack with sequence [{}]" __L, seq); - SetLastAckSent(seq); - NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16))); -} - -void EQStream::SendOutOfOrderAck(uint16 seq) -{ - LogNetcode(_L "Sending out of order ack with sequence [{}]" __L, seq); -uint16 Seq=htons(seq); - NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16))); -} - -void EQStream::Write(int eq_fd) -{ - std::queue ReadyToSend; - bool SeqEmpty=false, NonSeqEmpty=false; - std::deque::iterator sitr; - - // Check our rate to make sure we can send more - MRate.lock(); - int32 threshold=RateThreshold; - MRate.unlock(); - if (BytesWritten > threshold) { - return; - } - - // If we got more packets to we need to ack, send an ack on the highest one - MAcks.lock(); - if (CompareSequence(LastAckSent, NextAckToSend) == SeqFuture) - SendAck(NextAckToSend); - MAcks.unlock(); - - // Lock the outbound queues while we process - MOutboundQueue.lock(); - - // Place to hold the base packet t combine into - EQProtocolPacket *p=nullptr; - - // Find the next sequenced packet to send from the "queue" - sitr = SequencedQueue.begin(); - - uint16 count = 0; - // get to start of packets - while (sitr != SequencedQueue.end() && (*sitr)->sent_time > 0) { - ++sitr; - ++count; - } - - // Loop until both are empty or MaxSends is reached - while(!SeqEmpty || !NonSeqEmpty) { - - // See if there are more non-sequenced packets left - if (!NonSequencedQueue.empty()) { - if (!p) { - // If we don't have a packet to try to combine into, use this one as the base - // And remove it form the queue - p = NonSequencedQueue.front(); - LogNetcode(_L "Starting combined packet with non-seq packet of len [{}]" __L, p->size); - NonSequencedQueue.pop(); - } else if (!p->combine(NonSequencedQueue.front())) { - // Trying to combine this packet with the base didn't work (too big maybe) - // So just send the base packet (we'll try this packet again later) - LogNetcode(_L "Combined packet full at len [{}], next non-seq packet is len [{}]" __L, p->size, (NonSequencedQueue.front())->size); - ReadyToSend.push(p); - BytesWritten+=p->size; - p=nullptr; - - if (BytesWritten > threshold) { - // Sent enough this round, lets stop to be fair - LogNetcode(_L "Exceeded write threshold in nonseq ([{}] > [{}])" __L, BytesWritten, threshold); - break; - } - } else { - // Combine worked, so just remove this packet and it's spot in the queue - LogNetcode(_L "Combined non-seq packet of len [{}], yeilding [{}] combined" __L, (NonSequencedQueue.front())->size, p->size); - delete NonSequencedQueue.front(); - NonSequencedQueue.pop(); - } - } else { - // No more non-sequenced packets - NonSeqEmpty=true; - } - - if (sitr != SequencedQueue.end()) { - uint16 seq_send = SequencedBase + count; //just for logging... - - if(SequencedQueue.empty()) { - LogNetcode(_L "Tried to write a packet with an empty queue ([{}] is past next out [{}])" __L, seq_send, NextOutSeq); - SeqEmpty=true; - continue; - } - - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - if ((*sitr)->acked || (*sitr)->sent_time != 0) { - ++sitr; - ++count; - if (p) { - LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); - ReadyToSend.push(p); - BytesWritten += p->size; - p = nullptr; - } - LogNetcode(_L "Not retransmitting seq packet [{}] because already marked as acked" __L, seq_send); - } else if (!p) { - // If we don't have a packet to try to combine into, use this one as the base - // Copy it first as it will still live until it is acked - p=(*sitr)->Copy(); - LogNetcode(_L "Starting combined packet with seq packet [{}] of len [{}]" __L, seq_send, p->size); - (*sitr)->sent_time = Timer::GetCurrentTime(); - ++sitr; - ++count; - } else if (!p->combine(*sitr)) { - // Trying to combine this packet with the base didn't work (too big maybe) - // So just send the base packet (we'll try this packet again later) - LogNetcode(_L "Combined packet full at len [{}], next seq packet [{}] is len [{}]" __L, p->size, seq_send + 1, (*sitr)->size); - ReadyToSend.push(p); - BytesWritten+=p->size; - p=nullptr; - if ((*sitr)->opcode != OP_Fragment && BytesWritten > threshold) { - // Sent enough this round, lets stop to be fair - LogNetcode(_L "Exceeded write threshold in seq ([{}] > [{}])" __L, BytesWritten, threshold); - break; - } - } else { - // Combine worked - LogNetcode(_L "Combined seq packet [{}] of len [{}], yeilding [{}] combined" __L, seq_send, (*sitr)->size, p->size); - (*sitr)->sent_time = Timer::GetCurrentTime(); - ++sitr; - ++count; - } - } else { - if ((*sitr)->sent_time != 0) { - ++sitr; - ++count; - if (p) { - LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); - ReadyToSend.push(p); - BytesWritten += p->size; - p = nullptr; - } - } else if (!p) { - // If we don't have a packet to try to combine into, use this one as the base - // Copy it first as it will still live until it is acked - p=(*sitr)->Copy(); - (*sitr)->sent_time = Timer::GetCurrentTime(); - LogNetcode(_L "Starting combined packet with seq packet [{}] of len [{}]" __L, seq_send, p->size); - ++sitr; - ++count; - } else if (!p->combine(*sitr)) { - // Trying to combine this packet with the base didn't work (too big maybe) - // So just send the base packet (we'll try this packet again later) - LogNetcode(_L "Combined packet full at len [{}], next seq packet [{}] is len [{}]" __L, p->size, seq_send, (*sitr)->size); - ReadyToSend.push(p); - BytesWritten+=p->size; - p=nullptr; - - if (BytesWritten > threshold) { - // Sent enough this round, lets stop to be fair - LogNetcode(_L "Exceeded write threshold in seq ([{}] > [{}])" __L, BytesWritten, threshold); - break; - } - } else { - // Combine worked - LogNetcode(_L "Combined seq packet [{}] of len [{}], yielding [{}] combined" __L, seq_send, (*sitr)->size, p->size); - (*sitr)->sent_time = Timer::GetCurrentTime(); - ++sitr; - ++count; - } - } - - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "Post send Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - } else { - // No more sequenced packets - SeqEmpty=true; - } - } - // Unlock the queue - MOutboundQueue.unlock(); - - // We have a packet still, must have run out of both seq and non-seq, so send it - if (p) { - LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); - ReadyToSend.push(p); - BytesWritten+=p->size; - } - - // Send all the packets we "made" - while(!ReadyToSend.empty()) { - p = ReadyToSend.front(); - WritePacket(eq_fd,p); - delete p; - ReadyToSend.pop(); - } - - //see if we need to send our disconnect and finish our close - if(SeqEmpty && NonSeqEmpty) { - //no more data to send - if(CheckState(CLOSING)) { - LogNetcode(_L "All outgoing data flushed, closing stream" __L ); - //we are waiting for the queues to empty, now we can do our disconnect. - //this packet will not actually go out until the next call to Write(). - _SendDisconnect(); - SetState(DISCONNECTING); - } - } -} - -void EQStream::WritePacket(int eq_fd, EQProtocolPacket *p) -{ -uint32 length; -sockaddr_in address; - address.sin_family = AF_INET; - address.sin_addr.s_addr=remote_ip; - address.sin_port=remote_port; -#ifdef NOWAY - uint32 ip=address.sin_addr.s_addr; - std::cout << "Sending to: " - << (int)*(unsigned char *)&ip - << "." << (int)*((unsigned char *)&ip+1) - << "." << (int)*((unsigned char *)&ip+2) - << "." << (int)*((unsigned char *)&ip+3) - << "," << (int)ntohs(address.sin_port) << "(" << p->size << ")" << std::endl; - - p->DumpRaw(); - std::cout << "-------------" << std::endl; -#endif - length=p->serialize(buffer); - if (p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) { - if (compressed) { - BytesWritten -= p->size; - uint32 newlen=EQProtocolPacket::Compress(buffer,length, _tempBuffer, 2048); - memcpy(buffer,_tempBuffer,newlen); - length=newlen; - BytesWritten += newlen; - } - if (encoded) { - EQProtocolPacket::ChatEncode(buffer,length,Key); - } - - *(uint16 *)(buffer+length)=htons(CRC16(buffer,length,Key)); - length+=2; - } - //dump_message_column(buffer,length,"Writer: "); - sendto(eq_fd,(char *)buffer,length,0,(sockaddr *)&address,sizeof(address)); - AddBytesSent(length); -} - -void EQStream::SendSessionResponse() -{ - auto out = new EQProtocolPacket(OP_SessionResponse, nullptr, sizeof(SessionResponse)); - SessionResponse *Response=(SessionResponse *)out->pBuffer; - Response->Session=htonl(Session); - Response->MaxLength=htonl(MaxLen); - Response->UnknownA=2; - Response->Format=0; - if (compressed) - Response->Format|=FLAG_COMPRESSED; - if (encoded) - Response->Format|=FLAG_ENCODED; - Response->Key=htonl(Key); - - out->size=sizeof(SessionResponse); - - Log(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionResponse: session %lu, maxlen=%d, key=0x%x, compressed? %s, encoded? %s" __L, - (unsigned long)Session, MaxLen, Key, compressed?"yes":"no", encoded?"yes":"no"); - - NonSequencedPush(out); -} - -void EQStream::SendSessionRequest() -{ - auto out = new EQProtocolPacket(OP_SessionRequest, nullptr, sizeof(SessionRequest)); - SessionRequest *Request=(SessionRequest *)out->pBuffer; - memset(Request,0,sizeof(SessionRequest)); - Request->Session=htonl(time(nullptr)); - Request->MaxLength=htonl(512); - - LogNetcode(_L "Sending OP_SessionRequest: session [{}], maxlen=[{}]" __L, (unsigned long)ntohl(Request->Session), ntohl(Request->MaxLength)); - - NonSequencedPush(out); -} - -void EQStream::_SendDisconnect() -{ - if(GetState() == CLOSED) - return; - - auto out = new EQProtocolPacket(OP_SessionDisconnect, nullptr, sizeof(uint32)); - *(uint32 *)out->pBuffer=htonl(Session); - NonSequencedPush(out); - - LogNetcode(_L "Sending OP_SessionDisconnect: session [{}]" __L, (unsigned long)Session); -} - -void EQStream::InboundQueuePush(EQRawApplicationPacket *p) -{ - MInboundQueue.lock(); - InboundQueue.push_back(p); - MInboundQueue.unlock(); -} - -EQApplicationPacket *EQStream::PopPacket() -{ -EQRawApplicationPacket *p=nullptr; - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - auto itr = InboundQueue.begin(); - p=*itr; - InboundQueue.erase(itr); - } - MInboundQueue.unlock(); - - if (p) { - if (OpMgr != nullptr && *OpMgr != nullptr) { - EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); - if (emu_op == OP_Unknown) { - // Log(Logs::General, Logs::Client_Server_Packet_Unhandled, "Unknown :: [%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->opcode, p->Size(), DumpPacketToString(p).c_str()); - } - p->SetOpcode(emu_op); - } - } - - return p; -} - -EQRawApplicationPacket *EQStream::PopRawPacket() -{ -EQRawApplicationPacket *p=nullptr; - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - auto itr = InboundQueue.begin(); - p=*itr; - InboundQueue.erase(itr); - } - MInboundQueue.unlock(); - - //resolve the opcode if we can. - if(p) { - if(OpMgr != nullptr && *OpMgr != nullptr) { - EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); - if(emu_op == OP_Unknown) { - LogNetcode("Unable to convert EQ opcode {:#04x} to an Application opcode", p->opcode); - } - - p->SetOpcode(emu_op); - } - } - - return p; -} - -EQRawApplicationPacket *EQStream::PeekPacket() -{ -EQRawApplicationPacket *p=nullptr; - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - auto itr = InboundQueue.begin(); - p=*itr; - } - MInboundQueue.unlock(); - - return p; -} - -void EQStream::InboundQueueClear() -{ -EQApplicationPacket *p=nullptr; - - LogNetcode(_L "Clearing inbound queue" __L); - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - std::vector::iterator itr; - for(itr=InboundQueue.begin();itr!=InboundQueue.end();++itr) { - p=*itr; - delete p; - } - InboundQueue.clear(); - } - MInboundQueue.unlock(); -} - -bool EQStream::HasOutgoingData() -{ -bool flag; - - //once closed, we have nothing more to say - if(CheckClosed()) - return(false); - - MOutboundQueue.lock(); - flag=(!NonSequencedQueue.empty()); - if (!flag) { - //not only wait until we send it all, but wait until they ack everything. - flag = !SequencedQueue.empty(); - } - MOutboundQueue.unlock(); - - if (!flag) { - MAcks.lock(); - flag= (NextAckToSend>LastAckSent); - MAcks.unlock(); - } - - return flag; -} - -void EQStream::OutboundQueueClear() -{ -EQProtocolPacket *p=nullptr; - - LogNetcode(_L "Clearing outbound queue" __L); - - MOutboundQueue.lock(); - while(!NonSequencedQueue.empty()) { - delete NonSequencedQueue.front(); - NonSequencedQueue.pop(); - } - if(!SequencedQueue.empty()) { - std::deque::iterator itr; - for(itr=SequencedQueue.begin();itr!=SequencedQueue.end();++itr) { - p=*itr; - delete p; - } - SequencedQueue.clear(); - } - MOutboundQueue.unlock(); -} - -void EQStream::PacketQueueClear() -{ -EQProtocolPacket *p=nullptr; - - LogNetcode(_L "Clearing future packet queue" __L); - - if(!PacketQueue.empty()) { - std::map::iterator itr; - for(itr=PacketQueue.begin();itr!=PacketQueue.end();++itr) { - p=itr->second; - delete p; - } - PacketQueue.clear(); - } -} - -void EQStream::Process(const unsigned char *buffer, const uint32 length) -{ - static unsigned char newbuffer[2048]; - uint32 newlength=0; - if (EQProtocolPacket::ValidateCRC(buffer,length,Key)) { - if (compressed) { - newlength=EQProtocolPacket::Decompress(buffer,length,newbuffer,2048); - } else { - memcpy(newbuffer,buffer,length); - newlength=length; - if (encoded) - EQProtocolPacket::ChatDecode(newbuffer,newlength-2,Key); - } - if (buffer[1]!=0x01 && buffer[1]!=0x02 && buffer[1]!=0x1d) - newlength-=2; - EQProtocolPacket *p = MakeProtocolPacket(newbuffer,newlength); - ProcessPacket(p); - delete p; - ProcessQueue(); - } else { - LogNetcode(_L "Incoming packet failed checksum" __L); - } -} - -long EQStream::GetNextAckToSend() -{ - MAcks.lock(); - long l=NextAckToSend; - MAcks.unlock(); - - return l; -} - -long EQStream::GetLastAckSent() -{ - MAcks.lock(); - long l=LastAckSent; - MAcks.unlock(); - - return l; -} - -void EQStream::AckPackets(uint16 seq) -{ -std::deque::iterator itr, tmp; - - MOutboundQueue.lock(); - - SeqOrder ord = CompareSequence(SequencedBase, seq); - if(ord == SeqInOrder) { - //they are not acking anything new... - LogNetcode(_L "Received an ack with no window advancement (seq [{}])" __L, seq); - } else if(ord == SeqPast) { - //they are nacking blocks going back before our buffer, wtf? - LogNetcode(_L "Received an ack with backward window advancement (they gave [{}], our window starts at [{}]). This is bad" __L, seq, SequencedBase); - } else { - LogNetcode(_L "Received an ack up through sequence [{}]. Our base is [{}]" __L, seq, SequencedBase); - - - //this is a good ack, we get to ack some blocks. - seq++; //we stop at the block right after their ack, counting on the wrap of both numbers. - while(SequencedBase != seq) { - if(SequencedQueue.empty()) { - LogNetcode(_L "OUT OF PACKETS acked packet with sequence [{}]. Next send is [{}] before this" __L, (unsigned long)SequencedBase, SequencedQueue.size()); - SequencedBase = NextOutSeq; - break; - } - LogNetcode(_L "Removing acked packet with sequence [{}]" __L, (unsigned long)SequencedBase); - //clean out the acked packet - delete SequencedQueue.front(); - SequencedQueue.pop_front(); - //advance the base sequence number to the seq of the block after the one we just got rid of. - SequencedBase++; - } - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "Post-Ack on [{}] Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - } - - MOutboundQueue.unlock(); -} - -void EQStream::SetNextAckToSend(uint32 seq) -{ - MAcks.lock(); - LogNetcode(_L "Set Next Ack To Send to [{}]" __L, (unsigned long)seq); - NextAckToSend=seq; - MAcks.unlock(); -} - -void EQStream::SetLastAckSent(uint32 seq) -{ - MAcks.lock(); - LogNetcode(_L "Set Last Ack Sent to [{}]" __L, (unsigned long)seq); - LastAckSent=seq; - MAcks.unlock(); -} - -void EQStream::ProcessQueue() -{ - if(PacketQueue.empty()) { - return; - } - - EQProtocolPacket *qp=nullptr; - while((qp=RemoveQueue(NextInSeq))!=nullptr) { - LogNetcode(_L "Processing Queued Packet: Seq=[{}]" __L, NextInSeq); - ProcessPacket(qp); - delete qp; - LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); - } -} - -EQProtocolPacket *EQStream::RemoveQueue(uint16 seq) -{ -std::map::iterator itr; -EQProtocolPacket *qp=nullptr; - if ((itr=PacketQueue.find(seq))!=PacketQueue.end()) { - qp=itr->second; - PacketQueue.erase(itr); - LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); - } - return qp; -} - -void EQStream::SetStreamType(EQStreamType type) -{ - LogNetcode(_L "Changing stream type from [{}] to [{}]" __L, StreamTypeString(StreamType), StreamTypeString(type)); - StreamType=type; - switch (StreamType) { - case LoginStream: - app_opcode_size=1; - compressed=false; - encoded=false; - LogNetcode(_L "Login stream has app opcode size [{}], is not compressed or encoded" __L, app_opcode_size); - break; - case ChatOrMailStream: - case ChatStream: - case MailStream: - app_opcode_size=1; - compressed=false; - encoded=true; - LogNetcode(_L "Chat/Mail stream has app opcode size [{}], is not compressed, and is encoded" __L, app_opcode_size); - break; - case ZoneStream: - case WorldStream: - default: - app_opcode_size=2; - compressed=true; - encoded=false; - LogNetcode(_L "World/Zone stream has app opcode size [{}], is compressed, and is not encoded" __L, app_opcode_size); - break; - } -} - -const char *EQStream::StreamTypeString(EQStreamType t) -{ - switch (t) { - case LoginStream: - return "Login"; - break; - case WorldStream: - return "World"; - break; - case ZoneStream: - return "Zone"; - break; - case ChatOrMailStream: - return "Chat/Mail"; - break; - case ChatStream: - return "Chat"; - break; - case MailStream: - return "Mail"; - break; - case UnknownStream: - return "Unknown"; - break; - } - return "UnknownType"; -} - -//returns SeqFuture if `seq` is later than `expected_seq` -EQStream::SeqOrder EQStream::CompareSequence(uint16 expected_seq , uint16 seq) -{ - if (expected_seq==seq) { - // Curent - return SeqInOrder; - } else if ((seq > expected_seq && (uint32)seq < ((uint32)expected_seq + EQStream::MaxWindowSize)) || seq < (expected_seq - EQStream::MaxWindowSize)) { - // Future - return SeqFuture; - } else { - // Past - return SeqPast; - } -} - -void EQStream::SetState(EQStreamState state) { - MState.lock(); - LogNetcode(_L "Changing state from [{}] to [{}]" __L, State, state); - State=state; - MState.unlock(); -} - - -void EQStream::CheckTimeout(uint32 now, uint32 timeout) { - - bool outgoing_data = HasOutgoingData(); //up here to avoid recursive locking - - EQStreamState orig_state = GetState(); - if (orig_state == CLOSING && !outgoing_data) { - LogNetcode(_L "Out of data in closing state, disconnecting" __L); - _SendDisconnect(); - SetState(DISCONNECTING); - } else if (LastPacket && (now-LastPacket) > timeout) { - switch(orig_state) { - case CLOSING: - //if we time out in the closing state, they are not acking us, just give up - LogNetcode(_L "Timeout expired in closing state. Moving to closed state" __L); - _SendDisconnect(); - SetState(CLOSED); - break; - case DISCONNECTING: - //we timed out waiting for them to send us the disconnect reply, just give up. - LogNetcode(_L "Timeout expired in disconnecting state. Moving to closed state" __L); - SetState(CLOSED); - break; - case CLOSED: - LogNetcode(_L "Timeout expired in closed state??" __L); - break; - case ESTABLISHED: - //we timed out during normal operation. Try to be nice about it. - //we will almost certainly time out again waiting for the disconnect reply, but oh well. - LogNetcode(_L "Timeout expired in established state. Closing connection" __L); - _SendDisconnect(); - SetState(DISCONNECTING); - break; - default: - break; - } - } -} - -void EQStream::Decay() -{ - MRate.lock(); - uint32 rate=DecayRate; - MRate.unlock(); - if (BytesWritten>0) { - BytesWritten-=rate; - if (BytesWritten<0) - BytesWritten=0; - } - // check for any timed out acks - if ((GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) && RETRANSMIT_TIMEOUT_MULT && retransmittimeout) { - int count = 0; - MOutboundQueue.lock(); - for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); ++sitr, count++) { - if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) { - (*sitr)->sent_time = 0; - LogNetcode(_L "Timeout exceeded for seq [{}]. Flagging packet for retransmission" __L, SequencedBase + count); - } - } - MOutboundQueue.unlock(); - } -} - -void EQStream::AdjustRates(uint32 average_delta) -{ - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - if (average_delta && (average_delta <= AVERAGE_DELTA_MAX)) { - MRate.lock(); - AverageDelta = average_delta; - RateThreshold=RATEBASE/average_delta; - DecayRate=DECAYBASE/average_delta; - if (BytesWritten > RateThreshold) - BytesWritten = RateThreshold + DecayRate; - Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, - RateThreshold, DecayRate, average_delta); - MRate.unlock(); - } else { - Log(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, - average_delta, AVERAGE_DELTA_MAX); - AverageDelta = AVERAGE_DELTA_MAX; - } - } else { - if (average_delta) { - MRate.lock(); - AverageDelta = average_delta; - BytesWritten = 0; - RateThreshold=RATEBASE/average_delta; - DecayRate=DECAYBASE/average_delta; - Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, - RateThreshold, DecayRate, average_delta); - MRate.unlock(); - } - } -} - -void EQStream::Close() { - if(HasOutgoingData()) { - //there is pending data, wait for it to go out. - LogNetcode(_L "Stream requested to Close(), but there is pending data, waiting for it" __L); - SetState(CLOSING); - } else { - //otherwise, we are done, we can drop immediately. - _SendDisconnect(); - LogNetcode(_L "Stream closing immediate due to Close()" __L); - SetState(DISCONNECTING); - } -} - - -//this could be expanded to check more than the fitst opcode if -//we needed more complex matching -EQStream::MatchState EQStream::CheckSignature(const Signature *sig) { - EQRawApplicationPacket *p = nullptr; - MatchState res = MatchNotReady; - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - //this is already getting hackish... - p = InboundQueue.front(); - if(sig->ignore_eq_opcode != 0 && p->opcode == sig->ignore_eq_opcode) { - if(InboundQueue.size() > 1) { - p = InboundQueue[1]; - } else { - p = nullptr; - } - } - if(p == nullptr) { - //first opcode is ignored, and nothing else remains... keep waiting - } else if(p->opcode == sig->first_eq_opcode) { - //opcode matches, check length.. - if(p->size == sig->first_length) { - LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x} and length matched [{}]", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); - res = MatchSuccessful; - } else if(sig->first_length == 0) { - LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x} and length ([{}]) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); - res = MatchSuccessful; - } else { - //opcode matched but length did not. - LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x}, but length [{}] did not match expected [{}]", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length); - res = MatchFailed; - } - } else { - //first opcode did not match.. - LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode {:#04x} did not match expected {:#04x}", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode); - res = MatchFailed; - } - } - MInboundQueue.unlock(); - - return(res); -} diff --git a/common/eq_stream.h b/common/eq_stream.h deleted file mode 100644 index 23ec89b7f..000000000 --- a/common/eq_stream.h +++ /dev/null @@ -1,314 +0,0 @@ -#pragma once - -#include "common/eq_packet.h" -#include "common/eq_stream_intf.h" -#include "common/eq_stream_type.h" -#include "common/misc.h" -#include "common/mutex.h" -#include "common/opcodemgr.h" -#include "common/timer.h" - -#include -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -class EQApplicationPacket; -class EQProtocolPacket; - -#define FLAG_COMPRESSED 0x01 -#define FLAG_ENCODED 0x04 - -#ifndef RATEBASE -#define RATEBASE 1048576 -#endif - -#ifndef DECAYBASE -#define DECAYBASE 78642 -#endif - -#ifndef RETRANSMIT_TIMEOUT_MULT -#define RETRANSMIT_TIMEOUT_MULT 3.0 -#endif - -#ifndef RETRANSMIT_TIMEOUT_MAX -#define RETRANSMIT_TIMEOUT_MAX 5000 -#endif - -#ifndef AVERAGE_DELTA_MAX -#define AVERAGE_DELTA_MAX 2500 -#endif - -#ifndef RETRANSMIT_ACKED_PACKETS -#define RETRANSMIT_ACKED_PACKETS true -#endif - -#ifndef MAX_SESSION_RETRIES -#define MAX_SESSION_RETRIES 30 -#endif - -#pragma pack(1) -struct SessionRequest { - uint32 UnknownA; - uint32 Session; - uint32 MaxLength; -}; - -struct SessionResponse { - uint32 Session; - uint32 Key; - uint8 UnknownA; - uint8 Format; - uint8 UnknownB; - uint32 MaxLength; - uint32 UnknownD; -}; - -//Deltas are in ms, representing round trip times -struct ClientSessionStats { -/*000*/ uint16 RequestID; -/*002*/ uint32 last_local_delta; -/*006*/ uint32 average_delta; -/*010*/ uint32 low_delta; -/*014*/ uint32 high_delta; -/*018*/ uint32 last_remote_delta; -/*022*/ uint64 packets_sent; -/*030*/ uint64 packets_received; -/*038*/ -}; - -struct ServerSessionStats { -/*000*/ uint16 RequestID; -/*002*/ uint32 ServerTime; -/*006*/ uint64 packets_sent_echo; -/*014*/ uint64 packets_received_echo; -/*022*/ uint64 packets_sent; -/*030*/ uint64 packets_received; -/*038*/ -}; - -#pragma pack() - -class OpcodeManager; -class EQRawApplicationPacket; - -class EQStream : public EQStreamInterface { - friend class EQStreamPair; //for collector. - protected: - typedef enum { - SeqPast, - SeqInOrder, - SeqFuture - } SeqOrder; - - uint32 remote_ip; - uint16 remote_port; - uint8 buffer[8192]; - unsigned char *oversize_buffer; - uint32 oversize_offset,oversize_length; - uint8 app_opcode_size; - EQStreamType StreamType; - bool compressed,encoded; - uint32 retransmittimer; - uint32 retransmittimeout; - - uint16 sessionAttempts; - bool streamactive; - - //uint32 buffer_len; - - uint32 Session, Key; - uint16 NextInSeq; - uint32 MaxLen; - uint16 MaxSends; - - uint8 active_users; //how many things are actively using this - Mutex MInUse; - - EQStreamState State; - Mutex MState; - - uint32 LastPacket; - Mutex MVarlock; - - // Ack sequence tracking. - long NextAckToSend; - long LastAckSent; - long GetNextAckToSend(); - long GetLastAckSent(); - void AckPackets(uint16 seq); - void SetNextAckToSend(uint32); - void SetLastAckSent(uint32); - - Mutex MAcks; - - // Packets waiting to be sent (all protected by MOutboundQueue) - std::queue NonSequencedQueue; - std::deque SequencedQueue; - uint16 NextOutSeq; - uint16 SequencedBase; //the sequence number of SequencedQueue[0] - Mutex MOutboundQueue; - - //a buffer we use for compression/decompression - unsigned char _tempBuffer[2048]; - - // Packets waiting to be processed - std::vector InboundQueue; - std::map PacketQueue; //not mutex protected, only accessed by caller of Process() - Mutex MInboundQueue; - - static uint16 MaxWindowSize; - - int32 BytesWritten; - - uint64 sent_packet_count; - uint64 received_packet_count; - - Mutex MRate; - int32 RateThreshold; - int32 DecayRate; - uint32 AverageDelta; - - OpcodeManager **OpMgr; - - EQRawApplicationPacket *MakeApplicationPacket(EQProtocolPacket *p); - EQRawApplicationPacket *MakeApplicationPacket(const unsigned char *buf, uint32 len); - EQProtocolPacket *MakeProtocolPacket(const unsigned char *buf, uint32 len); - void SendPacket(uint16 opcode, EQApplicationPacket *p); - - void SetState(EQStreamState state); - - void SendSessionResponse(); - void SendSessionRequest(); - void SendAck(uint16 seq); - void SendOutOfOrderAck(uint16 seq); - void QueuePacket(EQProtocolPacket *p); - void SendPacket(EQProtocolPacket *p); - void NonSequencedPush(EQProtocolPacket *p); - void SequencedPush(EQProtocolPacket *p); - void WritePacket(int fd,EQProtocolPacket *p); - - - uint32 GetKey() { return Key; } - void SetKey(uint32 k) { Key=k; } - void SetSession(uint32 s) { Session=s; } - - void ProcessPacket(EQProtocolPacket *p); - - bool Stale(uint32 now, uint32 timeout=30) { return (LastPacket && (now-LastPacket) > timeout); } - - void InboundQueuePush(EQRawApplicationPacket *p); - EQRawApplicationPacket *PeekPacket(); //for collector. - EQRawApplicationPacket *PopRawPacket(); //for collector. - - void InboundQueueClear(); - void OutboundQueueClear(); - void PacketQueueClear(); - - void ProcessQueue(); - EQProtocolPacket *RemoveQueue(uint16 seq); - - void _SendDisconnect(); - - void init(bool resetSession=true); - public: - EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED; - StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2; - bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0; - streamactive = false; } - EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr; - remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream; - compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0; - create_time = Timer::GetTimeSeconds(); } - virtual ~EQStream() { RemoveData(); SetState(CLOSED); } - void SetMaxLen(uint32 length) { MaxLen=length; } - - //interface used by application (EQStreamInterface) - virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req=true); - virtual void FastQueuePacket(EQApplicationPacket **p, bool ack_req=true); - virtual EQApplicationPacket *PopPacket(); - virtual void Close(); - virtual uint32 GetRemoteIP() const { return remote_ip; } - virtual uint16 GetRemotePort() const { return remote_port; } - virtual void ReleaseFromUse() { MInUse.lock(); if(active_users > 0) active_users--; MInUse.unlock(); } - virtual void RemoveData() { InboundQueueClear(); OutboundQueueClear(); PacketQueueClear(); /*if (CombinedAppPacket) delete CombinedAppPacket;*/ } - virtual bool CheckState(EQStreamState state) { return GetState() == state; } - virtual std::string Describe() const { return("Direct EQStream"); } - - virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; } - - virtual OpcodeManager* GetOpcodeManager() const - { - return (*OpMgr); - }; - - void CheckTimeout(uint32 now, uint32 timeout=30); - bool HasOutgoingData(); - void Process(const unsigned char *data, const uint32 length); - void SetLastPacketTime(uint32 t) {LastPacket=t;} - void Write(int eq_fd); - - // whether or not the stream has been assigned (we passed our stream match) - virtual void SetActive(bool val) { streamactive = val; } - - // - inline bool IsInUse() { bool flag; MInUse.lock(); flag=(active_users>0); MInUse.unlock(); return flag; } - inline void PutInUse() { MInUse.lock(); active_users++; MInUse.unlock(); } - - virtual EQStreamState GetState() { EQStreamState s; MState.lock(); s=State; MState.unlock(); return s; } - - static SeqOrder CompareSequence(uint16 expected_seq , uint16 seq); - - bool CheckActive() { return GetState()==ESTABLISHED; } - bool CheckClosed() { return GetState()==CLOSED; } - void SetOpcodeSize(uint8 s) { app_opcode_size = s; } - void SetStreamType(EQStreamType t); - inline const EQStreamType GetStreamType() const { return StreamType; } - static const char *StreamTypeString(EQStreamType t); - - void Decay(); - void AdjustRates(uint32 average_delta); - - uint32 bytes_sent; - uint32 bytes_recv; - uint32 create_time; - - void AddBytesSent(uint32 bytes) - { - bytes_sent += bytes; - ++sent_packet_count; - } - - void AddBytesRecv(uint32 bytes) - { - bytes_recv += bytes; - ++received_packet_count; - } - - virtual const uint32 GetBytesSent() const { return bytes_sent; } - virtual const uint32 GetBytesRecieved() const { return bytes_recv; } - virtual const uint32 GetBytesSentPerSecond() const - { - if((Timer::GetTimeSeconds() - create_time) == 0) - return 0; - return bytes_sent / (Timer::GetTimeSeconds() - create_time); - } - - virtual const uint32 GetBytesRecvPerSecond() const - { - if((Timer::GetTimeSeconds() - create_time) == 0) - return 0; - return bytes_recv / (Timer::GetTimeSeconds() - create_time); - } - - const uint64 GetPacketsSent() { return sent_packet_count; } - const uint64 GetPacketsReceived() { return received_packet_count; } - - //used for dynamic stream identification - virtual MatchState CheckSignature(const Signature *sig); - -}; diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp deleted file mode 100644 index 470ac5b73..000000000 --- a/common/eq_stream_factory.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "eq_stream_factory.h" - -#include "common/global_define.h" -#ifdef _WINDOWS -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#endif - -#include -#include - -#include "op_codes.h" - -ThreadReturnType EQStreamFactoryReaderLoop(void *eqfs) -{ - EQStreamFactory *fs=(EQStreamFactory *)eqfs; - - fs->ReaderLoop(); - - THREAD_RETURN(nullptr); -} - -ThreadReturnType EQStreamFactoryWriterLoop(void *eqfs) -{ - EQStreamFactory *fs=(EQStreamFactory *)eqfs; - - fs->WriterLoop(); - - THREAD_RETURN(nullptr); -} - -EQStreamFactory::EQStreamFactory(EQStreamType type, int port, uint32 timeout) - : Timeoutable(5000), stream_timeout(timeout) -{ - StreamType=type; - Port=port; - sock=-1; -} - -void EQStreamFactory::Close() -{ - Stop(); - -#ifdef _WINDOWS - closesocket(sock); -#else - close(sock); -#endif - sock=-1; -} - -bool EQStreamFactory::Open() -{ -struct sockaddr_in address; -#ifndef WIN32 - pthread_t t1,t2; -#endif - /* 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(Port); - address.sin_addr.s_addr = htonl(INADDR_ANY); - - /* Setting up UDP port for new clients */ - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - return false; - } - - if (bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) { - close(sock); - sock=-1; - return false; - } - #ifdef _WINDOWS - unsigned long nonblock = 1; - ioctlsocket(sock, FIONBIO, &nonblock); - #else - fcntl(sock, F_SETFL, O_NONBLOCK); - #endif - //moved these because on windows the output was delayed and causing the console window to look bad - #ifdef _WINDOWS - _beginthread(EQStreamFactoryReaderLoop,0, this); - _beginthread(EQStreamFactoryWriterLoop,0, this); - #else - pthread_create(&t1,nullptr,EQStreamFactoryReaderLoop,this); - pthread_create(&t2,nullptr,EQStreamFactoryWriterLoop,this); - #endif - return true; -} - -std::shared_ptr EQStreamFactory::Pop() -{ - std::shared_ptr s = nullptr; - MNewStreams.lock(); - if (!NewStreams.empty()) { - s = NewStreams.front(); - NewStreams.pop(); - s->PutInUse(); - } - MNewStreams.unlock(); - - return s; -} - -void EQStreamFactory::Push(std::shared_ptr s) -{ - MNewStreams.lock(); - NewStreams.push(s); - MNewStreams.unlock(); -} - -void EQStreamFactory::ReaderLoop() -{ - fd_set readset; - std::map, std::shared_ptr>::iterator stream_itr; - int num; - int length; - unsigned char buffer[2048]; - sockaddr_in from; - int socklen = sizeof(sockaddr_in); - timeval sleep_time; - ReaderRunning = true; - - while(sock!=-1) { - MReaderRunning.lock(); - if (!ReaderRunning) - break; - MReaderRunning.unlock(); - - FD_ZERO(&readset); - FD_SET(sock,&readset); - - sleep_time.tv_sec=30; - sleep_time.tv_usec=0; - if ((num=select(sock+1,&readset,nullptr,nullptr,&sleep_time))<0) { - // What do we wanna do? - continue; - } else if (num==0) - continue; - - if(sock == -1) - break; //somebody closed us while we were sleeping. - - if (FD_ISSET(sock,&readset)) { -#ifdef _WINDOWS - if ((length=recvfrom(sock,(char*)buffer,sizeof(buffer),0,(struct sockaddr*)&from,(int *)&socklen)) < 2) -#else - if ((length=recvfrom(sock,buffer,2048,0,(struct sockaddr *)&from,(socklen_t *)&socklen)) < 2) -#endif - { - // What do we wanna do? - } else { - MStreams.lock(); - stream_itr = Streams.find(std::make_pair(from.sin_addr.s_addr, from.sin_port)); - if (stream_itr == Streams.end()) { - if (buffer[1]==OP_SessionRequest) { - std::shared_ptr s = std::make_shared(from); - s->SetStreamType(StreamType); - Streams[std::make_pair(from.sin_addr.s_addr, from.sin_port)]=s; - WriterWork.Signal(); - Push(s); - s->AddBytesRecv(length); - s->Process(buffer,length); - s->SetLastPacketTime(Timer::GetCurrentTime()); - } - MStreams.unlock(); - } else { - std::shared_ptr curstream = stream_itr->second; - //dont bother processing incoming packets for closed connections - if(curstream->CheckClosed()) - curstream = nullptr; - else - curstream->PutInUse(); - //the in use flag prevents the stream from being deleted while we are using it. - - if(curstream) { - curstream->AddBytesRecv(length); - curstream->Process(buffer,length); - curstream->SetLastPacketTime(Timer::GetCurrentTime()); - curstream->ReleaseFromUse(); - } - MStreams.unlock(); - } - } - } - } -} - -void EQStreamFactory::CheckTimeout() -{ - //lock streams the entire time were checking timeouts, it should be fast. - MStreams.lock(); - - unsigned long now=Timer::GetCurrentTime(); - std::map, std::shared_ptr>::iterator stream_itr; - - for(stream_itr = Streams.begin(); stream_itr != Streams.end();) { - std::shared_ptr s = stream_itr->second; - - s->CheckTimeout(now, stream_timeout); - - EQStreamState state = s->GetState(); - - //not part of the else so we check it right away on state change - if (state==CLOSED) { - if (s->IsInUse()) { - //give it a little time for everybody to finish with it - } else { - //everybody is done, we can delete it now - auto temp = stream_itr; - ++stream_itr; - temp->second = nullptr; - Streams.erase(temp); - continue; - } - } - - ++stream_itr; - } - MStreams.unlock(); -} - -void EQStreamFactory::WriterLoop() -{ - bool havework = true; - std::vector> wants_write; - std::vector>::iterator cur, end; - bool decay = false; - uint32 stream_count; - Timer DecayTimer(20); - WriterRunning = true; - DecayTimer.Enable(); - - while (sock != -1) { - MWriterRunning.lock(); - if (!WriterRunning) - break; - MWriterRunning.unlock(); - - havework = false; - wants_write.clear(); - - decay = DecayTimer.Check(); - - // copy streams into a seperate list so we dont have to keep - // MStreams locked while we are writting - MStreams.lock(); - for (auto stream_itr = Streams.begin(); stream_itr != Streams.end(); ++stream_itr) { - // If it's time to decay the bytes sent, then let's do it before we try to write - if (decay) - stream_itr->second->Decay(); - - // bullshit checking, to see if this is really happening, GDB seems to think so... - if (stream_itr->second == nullptr) { - fprintf(stderr, - "ERROR: nullptr Stream encountered in EQStreamFactory::WriterLoop for: %i:%i", - stream_itr->first.first, stream_itr->first.second); - continue; - } - - if (stream_itr->second->HasOutgoingData()) { - havework = true; - stream_itr->second->PutInUse(); - wants_write.push_back(stream_itr->second); - } - } - MStreams.unlock(); - - // do the actual writes - cur = wants_write.begin(); - end = wants_write.end(); - for (; cur != end; ++cur) { - (*cur)->Write(sock); - (*cur)->ReleaseFromUse(); - } - - Sleep(10); - - MStreams.lock(); - stream_count = Streams.size(); - MStreams.unlock(); - if (!stream_count) { - WriterWork.Wait(); - } - } -} - diff --git a/common/eq_stream_factory.h b/common/eq_stream_factory.h deleted file mode 100644 index 2aa2b56e4..000000000 --- a/common/eq_stream_factory.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "common/condition.h" -#include "common/eq_stream.h" -#include "common/timeoutmgr.h" - -#include -#include -#include - -class EQStream; -class Timer; - -class EQStreamFactory : private Timeoutable { - private: - int sock; - int Port; - - bool ReaderRunning; - Mutex MReaderRunning; - bool WriterRunning; - Mutex MWriterRunning; - - Condition WriterWork; - - EQStreamType StreamType; - - std::queue> NewStreams; - Mutex MNewStreams; - - std::map, std::shared_ptr> Streams; - Mutex MStreams; - - virtual void CheckTimeout(); - - Timer *DecayTimer; - - uint32 stream_timeout; - - public: - EQStreamFactory(EQStreamType type, uint32 timeout = 135000) : Timeoutable(5000), stream_timeout(timeout) { ReaderRunning=false; WriterRunning=false; StreamType=type; sock=-1; } - EQStreamFactory(EQStreamType type, int port, uint32 timeout = 135000); - - std::shared_ptr Pop(); - void Push(std::shared_ptr s); - - bool Open(); - bool Open(unsigned long port) { Port=port; return Open(); } - bool IsOpen() { return sock!=-1; } - void Close(); - void ReaderLoop(); - void WriterLoop(); - void Stop() { StopReader(); StopWriter(); } - void StopReader() { MReaderRunning.lock(); ReaderRunning=false; MReaderRunning.unlock(); } - void StopWriter() { MWriterRunning.lock(); WriterRunning=false; MWriterRunning.unlock(); WriterWork.Signal(); } - void SignalWriter() { WriterWork.Signal(); } -}; diff --git a/common/eq_stream_type.h b/common/eq_stream_type.h deleted file mode 100644 index 267dcf2b3..000000000 --- a/common/eq_stream_type.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -typedef enum { - UnknownStream=0, - LoginStream, - WorldStream, - ZoneStream, - ChatOrMailStream, - ChatStream, - MailStream -} EQStreamType; - diff --git a/common/guilds.cpp b/common/guilds.cpp deleted file mode 100644 index 09e92f39b..000000000 --- a/common/guilds.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 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 "guilds.h" - -#include "common/database.h" -#include "common/eq_packet_structs.h" -#include "common/global_define.h" -#include "common/misc_functions.h" - -#ifndef WIN32 -#include //for htonl -#endif \ No newline at end of file diff --git a/common/tcp_connection.cpp b/common/tcp_connection.cpp deleted file mode 100644 index 3a4439911..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(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(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_server.cpp b/common/tcp_server.cpp deleted file mode 100644 index 0009475fd..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 - LogDebug( "Starting TCPServerLoop with thread ID [{}]", pthread_self()); -#endif - - tcps->MLoopRunning.lock(); - while (tcps->RunLoop()) { - Sleep(SERVER_LOOP_GRANULARITY); - tcps->Process(); - } - tcps->MLoopRunning.unlock(); - -#ifndef WIN32 - LogDebug( "Ending TCPServerLoop with thread ID [{}]", 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/world/eqw.cpp b/world/eqw.cpp deleted file mode 100644 index 8b0e17b43..000000000 --- a/world/eqw.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 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 -*/ - -#ifdef EMBPERL - -#include "../common/global_define.h" -#include "eqw.h" -#include "eqw_parser.h" -#include "world_config.h" -#include "../common/races.h" -#include "../common/classes.h" -#include "../common/misc.h" -#include "../common/strings.h" -#include "zoneserver.h" -#include "zonelist.h" -#include "clientlist.h" -#include "cliententry.h" -#include "login_server.h" -#include "login_server_list.h" -#include "worlddb.h" -#include "client.h" -#include "launcher_list.h" -#include "launcher_link.h" -#include "wguild_mgr.h" -#include "../common/emu_constants.h" - -#ifdef seed -#undef seed -#endif - -#include - -extern uint32 numzones; -extern LauncherList launcher_list; -extern volatile bool RunLoops; - -EQW EQW::s_EQW; - -//IO Capture routine -XS(XS_EQWIO_PRINT); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQWIO_PRINT) -{ - dXSARGS; - if (items < 2) - return; - - int r; - for(r = 1; r < items; r++) { - char *str = SvPV_nolen(ST(r)); - EQW::Singleton()->AppendOutput(str); - } - - XSRETURN_EMPTY; -} - -EQW::EQW() { -} - -void EQW::AppendOutput(const char *str) { - m_outputBuffer += str; -// Log.LogDebugType(Logs::Detail, Logs::World_Server, "Append %d chars, yeilding result of length %d", strlen(str), m_outputBuffer.length()); -} - -const std::string &EQW::GetOutput() const { -// Log.LogDebugType(Logs::Detail, Logs::World_Server, "Getting, length %d", m_outputBuffer.length()); - return(m_outputBuffer); -} - -void EQW::LockWorld() { - WorldConfig::LockWorld(); - if (LoginServerList::Instance()->Connected()) { - LoginServerList::Instance()->SendStatus(); - } -} - -void EQW::UnlockWorld() { - WorldConfig::UnlockWorld(); - if (LoginServerList::Instance()->Connected()) { - LoginServerList::Instance()->SendStatus(); - } -} - -Const_char *EQW::GetConfig(Const_char *var_name) { - m_returnBuffer = WorldConfig::get()->GetByName(var_name); - return(m_returnBuffer.c_str()); -} - -bool EQW::LSConnected() { - return(LoginServerList::Instance()->Connected()); -} - -int EQW::CountZones() { - return(ZSList::Instance()->GetZoneCount()); -} - -//returns an array of zone_refs (opaque) -std::vector EQW::ListBootedZones() { - std::vector res; - - std::vector zones; - ZSList::Instance()->GetZoneIDList(zones); - - std::vector::iterator cur, end; - cur = zones.begin(); - end = zones.end(); - for(; cur != end; ++cur) { - res.push_back(itoa(*cur)); - } - - return(res); -} - -std::map EQW::GetZoneDetails(Const_char *zone_ref) { - std::map res; - - ZoneServer *zs = ZSList::Instance()->FindByID(Strings::ToInt(zone_ref)); - if(zs == nullptr) { - res["error"] = "Invalid zone."; - return(res); - } - - res["type"] = zs->IsStaticZone()?"static":"dynamic"; - res["zone_id"] = itoa(zs->GetZoneID()); - res["launch_name"] = zs->GetLaunchName(); - res["launched_name"] = zs->GetLaunchedName(); - res["short_name"] = zs->GetZoneName(); - res["long_name"] = zs->GetZoneLongName(); - res["port"] = itoa(zs->GetCPort()); - res["player_count"] = itoa(zs->NumPlayers()); - - //this isnt gunna work for dynamic zones... - res["launcher"] = ""; - if(zs->GetZoneID() != 0) { - LauncherLink *ll = launcher_list.FindByZone(zs->GetLaunchName()); - if(ll != nullptr) - res["launcher"] = ll->GetName(); - } - - return(res); -} - -int EQW::CountPlayers() { - return(ClientList::Instance()->GetClientCount()); -} - -//returns an array of character names in the zone (empty=all zones) -std::vector EQW::ListPlayers(Const_char *zone_name) { - std::vector res; - - std::vector list; - ClientList::Instance()->GetClients(zone_name, list); - - std::vector::iterator cur, end; - cur = list.begin(); - end = list.end(); - for(; cur != end; ++cur) { - res.push_back((*cur)->name()); - } - return(res); -} - -std::map EQW::GetPlayerDetails(Const_char *char_name) { - std::map res; - - ClientListEntry *cle = ClientList::Instance()->FindCharacter(char_name); - if(cle == nullptr) { - res["error"] = "1"; - return(res); - } - - res["character"] = cle->name(); - res["account"] = cle->AccountName(); - res["account_id"] = itoa(cle->AccountID()); - res["location_short"] = cle->zone()?ZoneName(cle->zone()):"No Zone"; - res["location_long"] = res["location_short"]; - res["location_id"] = itoa(cle->zone()); - res["ip"] = long2ip(cle->GetIP()); - res["level"] = itoa(cle->level()); - res["race"] = GetRaceIDName(cle->race()); - res["race_id"] = itoa(cle->race()); - res["class"] = GetClassIDName(cle->class_()); - res["class_id"] = itoa(cle->class_()); - res["guild_id"] = itoa(cle->GuildID()); - res["guild"] = guild_mgr.GetGuildName(cle->GuildID()); - res["status"] = itoa(cle->Admin()); -// res["patch"] = cle->DescribePatch(); - - return(res); -} - -int EQW::CountLaunchers(bool active_only) { - if(active_only) - return(launcher_list.GetLauncherCount()); - - std::vector it(EQW::ListLaunchers()); - return(it.size()); -} -/* -vector EQW::ListActiveLaunchers() { - vector launchers; - launcher_list.GetLauncherNameList(launchers); - return(launchers); -}*/ - -std::vector EQW::ListLaunchers() { -// vector list; -// database.GetLauncherList(list); - std::vector launchers; - launcher_list.GetLauncherNameList(launchers); - return(launchers); - -/* if(list.empty()) { - return(launchers); - } else if(launchers.empty()) { - return(list); - } - - //union the two lists. - vector::iterator curo, endo, curi, endi; - curo = list.begin(); - endo = list.end(); - for(; curo != endo; curo++) { - bool found = false; - curi = launchers.begin(); - endi = launchers.end(); - for(; curi != endi; curi++) { - if(*curo == *curi) { - found = true; - break; - } - } - if(found) - break; - launchers.push_back(*curo); - } - return(launchers);*/ -} - -EQLConfig * EQW::GetLauncher(Const_char *launcher_name) { - return(launcher_list.GetConfig(launcher_name)); -} - -void EQW::CreateLauncher(Const_char *launcher_name, int dynamic_count) { - launcher_list.CreateLauncher(launcher_name, dynamic_count); -} - -uint32 EQW::CreateGuild(const char* name, uint32 leader_char_id) { - uint32 id = guild_mgr.CreateGuild(name, leader_char_id); - if(id != GUILD_NONE) - ClientList::Instance()->UpdateClientGuild(leader_char_id, id); - return(id); -} - -bool EQW::DeleteGuild(uint32 guild_id) { - return(guild_mgr.DeleteGuild(guild_id)); -} - -bool EQW::RenameGuild(uint32 guild_id, const char* name) { - return(guild_mgr.RenameGuild(guild_id, name)); -} - -bool EQW::SetGuildMOTD(uint32 guild_id, const char* motd, const char *setter) { - return(guild_mgr.SetGuildMOTD(guild_id, motd, setter)); -} - -bool EQW::SetGuildLeader(uint32 guild_id, uint32 leader_char_id) { - return(guild_mgr.SetGuildLeader(guild_id, leader_char_id)); -} - -bool EQW::SetGuild(uint32 charid, uint32 guild_id, uint8 rank) { - ClientList::Instance()->UpdateClientGuild(charid, guild_id); - return(guild_mgr.SetGuild(charid, guild_id, rank)); -} - -bool EQW::SetGuildRank(uint32 charid, uint8 rank) { - return(guild_mgr.SetGuildRank(charid, rank)); -} - -bool EQW::SetBankerFlag(uint32 charid, bool is_banker) { - return(guild_mgr.SetBankerFlag(charid, is_banker)); -} - -bool EQW::SetTributeFlag(uint32 charid, bool enabled) { - return(guild_mgr.SetTributeFlag(charid, enabled)); -} - -bool EQW::SetPublicNote(uint32 charid, const char *note) { - return(guild_mgr.SetPublicNote(charid, note)); -} - -int EQW::CountBugs() { - std::string query = "SELECT count(*) FROM bugs where status = 0"; - auto results = database.QueryDatabase(query); - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return Strings::ToInt(row[0]); -} - -std::vector EQW::ListBugs(uint32 offset) { - std::vector res; - std::string query = StringFormat("SELECT id FROM bugs WHERE status = 0 limit %d, 30", offset); - auto results = database.QueryDatabase(query); - - if (!results.Success()) - return res; - - for (auto row = results.begin();row != results.end(); ++row) - res.push_back(row[0]); - - return res; -} - -std::map EQW::GetBugDetails(Const_char *id) { - std::map res; - std::string query = StringFormat("SELECT name, zone, x, y, z, target, bug FROM bugs WHERE id = %s", id); - auto results = database.QueryDatabase(query); - - if (!results.Success()) - return res; - - for(auto row = results.begin(); row != results.end(); ++row) { - res["name"] = row[0]; - res["zone"] = row[1]; - res["x"] = row[2]; - res["y"] = row[3]; - res["z"] = row[4]; - res["target"] = row[5]; - res["bug"] = row[6]; - res["id"] = id; - } - return res; -} - -void EQW::ResolveBug(const char *id) { - std::vector res; - std::string query = StringFormat("UPDATE bugs SET status=1 WHERE id=%s", id); - database.QueryDatabase(query); -} - -void EQW::SendMessage(uint32 type, const char *msg) { - ZSList::Instance()->SendEmoteMessage( - 0, - 0, - AccountStatus::Player, - type, - msg - ); -} - -void EQW::WorldShutDown(uint32 time, uint32 interval) { - ZSList::Instance()->WorldShutDown(time, interval); -} - -#endif //EMBPERL - diff --git a/world/eqw.h b/world/eqw.h deleted file mode 100644 index 99b917183..000000000 --- a/world/eqw.h +++ /dev/null @@ -1,93 +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 EQW_H_ -#define EQW_H_ - -#include -#include -#include -#include "../common/types.h" - -class EQLConfig; - -//this is the main object exported to perl. -class EQW { - EQW(); -public: - static EQW *Singleton() { return(&s_EQW); } - - void AppendOutput(const char *str); - const std::string &GetOutput() const; - void ClearOutput() { m_outputBuffer = ""; } - -//BEGIN PERL EXPORT - //NOTE: you must have a space after the * of a return value - Const_char * GetConfig(Const_char *var_name); - void LockWorld(); - void UnlockWorld(); - - bool LSConnected(); - - int CountZones(); - std::vector ListBootedZones(); //returns an array of zone_refs (opaque) - std::map GetZoneDetails(Const_char *zone_ref); //returns a hash ref of details - - int CountPlayers(); - std::vector ListPlayers(Const_char *zone_name = ""); //returns an array of player refs (opaque) - std::map GetPlayerDetails(Const_char *player_ref); //returns a hash ref of details - - int CountLaunchers(bool active_only); -// vector ListActiveLaunchers(); //returns an array of launcher names - std::vector ListLaunchers(); //returns an array of launcher names - EQLConfig * GetLauncher(Const_char *launcher_name); //returns the EQLConfig object for the specified launcher. - void CreateLauncher(Const_char *launcher_name, int dynamic_count); -// EQLConfig * FindLauncher(Const_char *zone_ref); - - //Guild routines, mostly wrappers around guild_mgr - uint32 CreateGuild(const char* name, uint32 leader_char_id); - bool DeleteGuild(uint32 guild_id); - bool RenameGuild(uint32 guild_id, const char* name); - bool SetGuildMOTD(uint32 guild_id, const char* motd, const char *setter); - bool SetGuildLeader(uint32 guild_id, uint32 leader_char_id); - bool SetGuild(uint32 charid, uint32 guild_id, uint8 rank); - bool SetGuildRank(uint32 charid, uint8 rank); - bool SetBankerFlag(uint32 charid, bool is_banker); - bool SetTributeFlag(uint32 charid, bool enabled); - bool SetPublicNote(uint32 charid, const char *note); - - //bugs - int CountBugs(); - std::vector ListBugs(uint32 offset); //returns an array of zone_refs (opaque) - std::map GetBugDetails(const char *id); - void ResolveBug(const char *id); - - void SendMessage(uint32 type, const char *msg); - void WorldShutDown(uint32 time, uint32 interval); -//END PERL EXPORT - -protected: - std::string m_outputBuffer; - std::string m_returnBuffer; - - bool m_worldLocked; - -private: - static EQW s_EQW; -}; - -#endif /*EQW_H_*/ diff --git a/world/eqw_http_handler.cpp b/world/eqw_http_handler.cpp deleted file mode 100644 index 5ae1b8b60..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) { - LogInfo("Login autentication failed for [{}] with [{}]", m_username.c_str(), m_password.c_str()); - return(false); - } - if(status < httpLoginStatus) { - LogInfo("Login of [{}] 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() { - LogInfo("Requesting that HTTP Service stop"); - m_running = false; - Close(); -} - -bool EQWHTTPServer::Start(uint16 port, const char *mime_file) { - if(m_running) { - LogInfo("HTTP Service is already running on port [{}]", m_port); - return(false); - } - - //load up our nice mime types - if(!EQWHTTPHandler::LoadMimeTypes(mime_file)) { - LogInfo("Failed to load mime types from [{}]", mime_file); - return(false); - } else { - LogInfo("Loaded mime types from [{}]", mime_file); - } - - //fire up the server thread - char errbuf[TCPServer_ErrorBufferSize]; - if(!Open(port, errbuf)) { - LogInfo("Unable to bind to port [{}] for HTTP service: [{}]", 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_parser.cpp b/world/eqw_parser.cpp deleted file mode 100644 index 46cc4465c..000000000 --- a/world/eqw_parser.cpp +++ /dev/null @@ -1,348 +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) { - LogInfo("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 - LogInfo("Loading worldui perl plugins"); - std::string err; - if(!eval_file("world", "worldui.pl", err)) { - LogInfo("Warning - world.pl: [{}]", 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/http_request.cpp b/world/http_request.cpp deleted file mode 100644 index 16be3c8dd..000000000 --- a/world/http_request.cpp +++ /dev/null @@ -1,80 +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 "http_request.h" -#include "eqw_http_handler.h" -#include "../common/eqdb.h" -#include "../common/SocketLib/HttpdForm.h" -#include - -HTTPRequest::HTTPRequest(EQWHTTPHandler *h, HttpdForm *form) -: m_handler(h) -{ - std::string name, value; - if(form->getfirst(name, value)) { - m_values[name] = value; - while(form->getnext(name, value)) - m_values[name] = value; - } -} - -const char *HTTPRequest::getEscaped(const char *name, const char *default_value) const { - return(EQDB::Singleton()->escape_string(get(name, default_value))); -} - -const char *HTTPRequest::get(const char *name, const char *default_value) const { - std::map::const_iterator res; - res = m_values.find(name); - if(res == m_values.end()) - return(default_value); - return(res->second.c_str()); -} - -std::map HTTPRequest::get_all() const { - return m_values; -} - -int HTTPRequest::getInt(const char *name, int default_value) const { - std::map::const_iterator res; - res = m_values.find(name); - if(res == m_values.end()) - return(default_value); - return(Strings::ToInt(res->second.c_str())); -} - -float HTTPRequest::getFloat(const char *name, float default_value) const { - std::map::const_iterator res; - res = m_values.find(name); - if(res == m_values.end()) - return(default_value); - return(Strings::ToFloat(res->second.c_str())); -} - -void HTTPRequest::header(Const_char *name, Const_char *value) { - m_handler->AddResponseHeader(name, value); -} - -void HTTPRequest::SetResponseCode(Const_char *code) { - m_handler->SetResponseCode(code); -} - -void HTTPRequest::redirect(Const_char *URL) { - header("Location", URL); - SetResponseCode("302"); -} - diff --git a/world/http_request.h b/world/http_request.h deleted file mode 100644 index 907d75ebd..000000000 --- a/world/http_request.h +++ /dev/null @@ -1,58 +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 HTTPREQUEST_H_ -#define HTTPREQUEST_H_ - -#include "../common/types.h" -#include -#include - -//this object acts as a friendlier interface to the HttpdForm object (perl exportable) -//which does more effecient lookups - - -class HttpdForm; -class EQWHTTPHandler; - -class HTTPRequest { -public: - HTTPRequest(EQWHTTPHandler *h, HttpdForm *form); - -//BEGIN PERL EXPORT - - Const_char * get(Const_char *name, Const_char *default_value = "") const; - int getInt(Const_char *name, int default_value = 0) const; - float getFloat(Const_char *name, float default_value = 0.0) const; - - //returns a database-safe string - Const_char * getEscaped(Const_char *name, Const_char *default_value = "") const; - - std::map get_all() const; - - void redirect(Const_char *URL); - void SetResponseCode(Const_char *code); - void header(Const_char *name, Const_char *value); -//END PERL EXPORT - -protected: - EQWHTTPHandler *const m_handler; - std::map m_values; -}; - -#endif /*HTTPREQUEST_H_*/ -