From b5f93adaa5459a7606e84854fecca07a8d85e8fd Mon Sep 17 00:00:00 2001 From: gesior Date: Sat, 10 Jan 2026 00:07:22 +0100 Subject: [PATCH 1/3] [WIP] OTCv8 proxy --- source/ban.cpp | 3 ++ source/config.lua.dist | 6 +++ source/configmanager.cpp | 2 + source/configmanager.h | 4 +- source/connection.cpp | 112 +++++++++++++++++++++++++++++++++++++-- source/connection.h | 14 +++++ 6 files changed, 136 insertions(+), 5 deletions(-) diff --git a/source/ban.cpp b/source/ban.cpp index 25ad4c6de..ca8c4148c 100644 --- a/source/ban.cpp +++ b/source/ban.cpp @@ -36,6 +36,9 @@ bool BanManager::clearTemporaryBans() const bool BanManager::acceptConnection(uint32_t clientip) { + if(g_config.getBoolean(ConfigManager::ALLOW_OTC_PROXY) || g_config.getBoolean(ConfigManager::ALLOW_HAPROXY)) + return true; + if(clientip == 0) return false; banLock.lock(); diff --git a/source/config.lua.dist b/source/config.lua.dist index fd71a3103..fc6c3bd42 100644 --- a/source/config.lua.dist +++ b/source/config.lua.dist @@ -295,6 +295,12 @@ logintimeout = 60 * 1000 -- What is the maximum number of packages the client can send per second? max_packets_per_second = 25 +-- OTCv8 proxy support +allow_otc_proxy = false + +-- HAProxy support +allow_haproxy = false + -- how deep queryDestination should look for free slots (default -1, infinite) player_querydestination_deepness = -1 diff --git a/source/configmanager.cpp b/source/configmanager.cpp index f1fe66631..87ffcae3a 100644 --- a/source/configmanager.cpp +++ b/source/configmanager.cpp @@ -214,6 +214,8 @@ bool ConfigManager::loadFile(const std::string& _filename) // Cast System m_confInteger[ENABLE_CAST] = getGlobalBoolean(L, "enableCast", false); m_confInteger[MAX_CAST_VIEWERS] = getGlobalNumber(L, "max_cast_viewers", 20); + m_confInteger[ALLOW_OTC_PROXY] = getGlobalBoolean(L, "allow_otc_proxy", false); + m_confInteger[ALLOW_HAPROXY] = getGlobalBoolean(L, "allow_haproxy", false); m_isLoaded = true; return true; diff --git a/source/configmanager.h b/source/configmanager.h index 7566cb28c..927934a6f 100644 --- a/source/configmanager.h +++ b/source/configmanager.h @@ -167,7 +167,9 @@ class ConfigManager { GUILD_WAR_FEE, GUILD_WARS_END_ONLY_ON_STARTUP, ENABLE_CAST, - MAX_CAST_VIEWERS, + MAX_CAST_VIEWERS, + ALLOW_OTC_PROXY, + ALLOW_HAPROXY, LAST_INTEGER_CONFIG /* this must be the last one */ }; diff --git a/source/connection.cpp b/source/connection.cpp index 71394a9a7..2f266fddc 100644 --- a/source/connection.cpp +++ b/source/connection.cpp @@ -269,14 +269,116 @@ void Connection::acceptConnection() } } +void Connection::parseOtcProxyPacket(const boost::system::error_code& error) +{ + boost::recursive_mutex::scoped_lock lockClass(m_connectionLock); + m_readTimer.cancel(); + --m_pendingRead; + + if (error) { + closeConnection(); + return; + } + + const uint8_t* msgBuffer = (const uint8_t*)m_msg.getBuffer(); + m_realIP = *reinterpret_cast(msgBuffer); + m_otcProxy = true; + acceptConnection(); +} + +void Connection::parseHaProxyPacket(const boost::system::error_code& error) +{ + boost::recursive_mutex::scoped_lock lockClass(m_connectionLock); + m_readTimer.cancel(); + --m_pendingRead; + + if (error) { + closeConnection(); + return; + } + + const uint8_t* msgBuffer = (const uint8_t*)m_msg.getBuffer(); + m_realIP = *reinterpret_cast(&msgBuffer[14]); + m_haProxy = true; + acceptConnection(); +} + +bool Connection::tryParseProxyPacket() +{ + // only first packet may contain IP from OTCv8 proxy / haproxy + if (m_receivedFirstHeader) { + return false; + } + + m_receivedFirstHeader = true; + + uint16_t size = m_msg.decodeHeader(); + // OTCv8 proxy, 6 bytes packet + // starts from 2 bytes 0xFFFEu, then 4 bytes with IP uint32_t + if (g_config.getNumber(ConfigManager::ALLOW_OTC_PROXY) && size == 0xFFFEu) { + try { + ++m_pendingRead; + m_readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); + m_readTimer.async_wait(boost::bind(&Connection::handleReadTimeout, boost::weak_ptr(shared_from_this()), boost::asio::placeholders::error)); + + boost::asio::async_read(getHandle(), boost::asio::buffer(m_msg.getBuffer(), 4), + boost::bind(&Connection::parseOtcProxyPacket, shared_from_this(), boost::asio::placeholders::error)); + } catch (boost::system::system_error& e) { + if (m_logError) { + LOG_MESSAGE("NETWORK", LOGTYPE_ERROR, 1, e.what()); + m_logError = false; + closeConnection(); + } + } + return true; + } + + // HAProxy send-proxy-v2, 28 bytes packet + // starts from 2 bytes 0x0A0Du, then 26 bytes, IP uint32_t starts from 17th byte (of 28 bytes) + if (g_config.getNumber(ConfigManager::ALLOW_HAPROXY) && size == 0x0A0Du) { + try { + ++m_pendingRead; + m_readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); + m_readTimer.async_wait(boost::bind(&Connection::handleReadTimeout, boost::weak_ptr(shared_from_this()), boost::asio::placeholders::error)); + + boost::asio::async_read(getHandle(), boost::asio::buffer(m_msg.getBuffer(), 26), + boost::bind(&Connection::parseHaProxyPacket, shared_from_this(), boost::asio::placeholders::error)); + } catch (boost::system::system_error& e) { + if (m_logError) { + LOG_MESSAGE("NETWORK", LOGTYPE_ERROR, 1, e.what()); + m_logError = false; + closeConnection(); + } + } + return true; + } + + return false; +} + void Connection::parseHeader(const boost::system::error_code& error) { m_connectionLock.lock(); m_readTimer.cancel(); + --m_pendingRead; - int32_t size = m_msg.decodeHeader(); - if(error || size <= 0 || size >= NETWORKMESSAGE_MAXSIZE - 16){ + if (error) { handleReadError(error); + closeConnection(); + m_connectionLock.unlock(); + return; + } + + if (tryParseProxyPacket()) { + m_connectionLock.unlock(); + return; + } + + int32_t size = m_msg.decodeHeader(); + if (size <= 0 || size >= NETWORKMESSAGE_MAXSIZE - 16) { + closeConnection(); + m_connectionLock.unlock(); + return; } if(m_connectionState != CONNECTION_STATE_OPEN || m_readError){ @@ -300,8 +402,6 @@ void Connection::parseHeader(const boost::system::error_code& error) } } - --m_pendingRead; - try{ ++m_pendingRead; m_readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); @@ -447,6 +547,10 @@ void Connection::internalSend(OutputMessage_ptr msg) uint32_t Connection::getIP() const { + if (isOtcProxy() || isHaProxy()) { + return m_realIP; + } + //Ip is expressed in network byte order boost::system::error_code error; const boost::asio::ip::tcp::endpoint endpoint = m_socket->remote_endpoint(error); diff --git a/source/connection.h b/source/connection.h index b1b34b364..eecda507d 100644 --- a/source/connection.h +++ b/source/connection.h @@ -110,6 +110,10 @@ class Connection : public boost::enable_shared_from_this, boost::non m_writeError = false; m_readError = false; m_packetsSent = 0; + m_realIP = 0; + m_otcProxy = false; + m_haProxy = false; + m_receivedFirstHeader = false; m_timeConnected = time(NULL); #ifdef __ENABLE_SERVER_DIAGNOSTIC__ @@ -136,11 +140,16 @@ class Connection : public boost::enable_shared_from_this, boost::non bool send(OutputMessage_ptr msg); uint32_t getIP() const; + bool isOtcProxy() const { return m_otcProxy; }; + bool isHaProxy() const { return m_haProxy; }; int32_t addRef() {return ++m_refCount;} int32_t unRef() {return --m_refCount;} private: + void parseOtcProxyPacket(const boost::system::error_code& error); + void parseHaProxyPacket(const boost::system::error_code& error); + bool tryParseProxyPacket(); void parseHeader(const boost::system::error_code& error); void parsePacket(const boost::system::error_code& error); @@ -174,6 +183,11 @@ class Connection : public boost::enable_shared_from_this, boost::non time_t m_timeConnected; uint32_t m_packetsSent; + uint32_t m_realIP = 0; + bool m_otcProxy = false; + bool m_haProxy = false; + bool m_receivedFirstHeader = false; + int32_t m_pendingWrite; int32_t m_pendingRead; ConnectionState_t m_connectionState; From 58331e59c9f1f02492d225587bd4e66b0761f00b Mon Sep 17 00:00:00 2001 From: gesior Date: Sat, 10 Jan 2026 00:26:13 +0100 Subject: [PATCH 2/3] [WIP] OTCv8 proxy --- source/configmanager.cpp | 1 + source/configmanager.h | 1 + source/protocollogin.cpp | 22 +++++++++++++++++----- source/status.cpp | 15 +++++++++++++-- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/source/configmanager.cpp b/source/configmanager.cpp index 87ffcae3a..db91ca86e 100644 --- a/source/configmanager.cpp +++ b/source/configmanager.cpp @@ -181,6 +181,7 @@ bool ConfigManager::loadFile(const std::string& _filename) m_confInteger[CAN_ROPE_CREATURES] = getGlobalBoolean(L, "can_rope_creatures", true); m_confString[DEATH_MSG] = getGlobalString(L, "death_msg", "You are dead."); m_confInteger[CAN_ATTACK_INVISIBLE] = getGlobalBoolean(L, "can_attack_invisible", false); + m_confString[STATUS_IP] = getGlobalString(L, "status_ip", ""); m_confInteger[MIN_PVP_LEVEL] = getGlobalNumber(L, "min_pvp_level", 0); #ifdef __MIN_PVP_LEVEL_APPLIES_TO_SUMMONS__ m_confInteger[MIN_PVP_LEVEL_APPLIES_TO_SUMMONS] = getGlobalBoolean(L, "min_pvp_level_applies_to_summons", true); diff --git a/source/configmanager.h b/source/configmanager.h index 927934a6f..a2a530c92 100644 --- a/source/configmanager.h +++ b/source/configmanager.h @@ -64,6 +64,7 @@ class ConfigManager { SQL_TYPE, MAP_STORAGE_TYPE, DEATH_MSG, + STATUS_IP, LAST_STRING_CONFIG /* this must be the last one */ }; diff --git a/source/protocollogin.cpp b/source/protocollogin.cpp index 9fb494035..ed84ee830 100644 --- a/source/protocollogin.cpp +++ b/source/protocollogin.cpp @@ -117,11 +117,23 @@ bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg) return false; } - uint32_t serverip = serverIPs[0].first; - for(uint32_t i = 0; i < serverIPs.size(); ++i){ - if((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second)){ - serverip = serverIPs[i].first; - break; + uint32_t serverip = 0; + if (getConnection()->isOtcProxy()) { + serverip = inet_addr("127.0.0.1"); + } else if (getConnection()->isHaProxy()) { + const std::string& statusIp = g_config.getString(ConfigManager::STATUS_IP); + if (!statusIp.empty()) { + serverip = inet_addr(statusIp.c_str()); + } else { + serverip = inet_addr(g_config.getString(ConfigManager::IP).c_str()); + } + } else { + serverip = serverIPs[0].first; + for (uint32_t i = 0; i < serverIPs.size(); ++i) { + if ((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second)) { + serverip = serverIPs[i].first; + break; + } } } diff --git a/source/status.cpp b/source/status.cpp index 7e7d0028a..54ecf74f8 100644 --- a/source/status.cpp +++ b/source/status.cpp @@ -161,7 +161,12 @@ std::string Status::getStatusString() const // generic info p = xmlNewNode(NULL, (const xmlChar*)"serverinfo"); addXMLProperty(p, "uptime", getUptime()); - addXMLProperty(p, "ip", g_config.getString(ConfigManager::IP)); + const std::string& statusIp = g_config.getString(ConfigManager::STATUS_IP); + if (!statusIp.empty()) { + addXMLProperty(p, "ip", statusIp); + } else { + addXMLProperty(p, "ip", g_config.getString(ConfigManager::IP)); + } addXMLProperty(p, "servername", g_config.getString(ConfigManager::SERVER_NAME)); addXMLProperty(p, "port", g_config.getNumber(ConfigManager::LOGIN_PORT)); addXMLProperty(p, "location", g_config.getString(ConfigManager::LOCATION)); @@ -247,7 +252,13 @@ void Status::getInfo(uint32_t requestedInfo, OutputMessage_ptr output, NetworkMe if(requestedInfo & REQUEST_BASIC_SERVER_INFO){ output->AddByte(0x10); // server info output->AddString(g_config.getString(ConfigManager::SERVER_NAME).c_str()); - output->AddString(g_config.getString(ConfigManager::IP).c_str()); + + const std::string& statusIp = g_config.getString(ConfigManager::STATUS_IP); + if (!statusIp.empty()) { + output->AddString(statusIp.c_str()); + } else { + output->AddString(g_config.getString(ConfigManager::IP).c_str()); + } ss << g_config.getNumber(ConfigManager::LOGIN_PORT); output->AddString(ss.str().c_str()); ss.str(""); From 0ec5a684faf959b3c2da5e03e70d3a6ea092b9bb Mon Sep 17 00:00:00 2001 From: gesior Date: Sat, 10 Jan 2026 00:36:53 +0100 Subject: [PATCH 3/3] Fix all compilation errors --- .gitignore | 1 + Dockerfile | 21 +++++++++------------ source/condition.cpp | 9 +++++---- source/condition.h | 2 +- source/connection.cpp | 12 ++++++------ source/connection.h | 6 +++--- source/definitions.h | 1 + source/game.cpp | 2 ++ source/map.h | 2 +- source/monster.cpp | 8 ++++---- source/player.cpp | 2 +- source/position.cpp | 2 ++ source/scheduler.h | 2 +- source/server.h | 1 + 14 files changed, 38 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 2e3c51e97..7d06e12b4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ source/stamp-h1 source/config.h.in~ # OS +/.idea ._* .DS_Store Thumbs.db diff --git a/Dockerfile b/Dockerfile index 72a9c79b1..bfddff7f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,11 @@ -FROM alpine:latest +FROM alpine:3.19.0 -COPY . /otserv/. +RUN apk add --no-cache \ + autoconf build-base pkgconfig boost-dev gmp-dev libxml2-dev \ + automake lua lua-dev mariadb-dev crypto++ ccache -RUN echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories && \ - apk update && \ - apk upgrade && \ - apk add --no-cache autoconf build-base pkgconfig boost-dev gmp-dev libxml2-dev && \ - apk add --no-cache automake lua lua-dev mariadb-dev crypto++ ccache - cd /otserv/source && \ - chmod +x autogen.sh && \ - ./autogen.sh && \ - ./configure --enable-mysql --enable-server-diag && \ - make +COPY source /othire/ +WORKDIR /othire/ +RUN sh autogen.sh +RUN ./configure --enable-mysql +RUN make -j$(nproc) diff --git a/source/condition.cpp b/source/condition.cpp index 2ed40a269..d9ee6a2c8 100644 --- a/source/condition.cpp +++ b/source/condition.cpp @@ -1410,9 +1410,10 @@ void ConditionDamage::endCondition(Creature* creature, ConditionEnd_t reason) // } -bool ConditionDamage::updateCondition(const ConditionDamage* addCondition) +bool ConditionDamage::updateCondition(const Condition* addCondition) { - if(addCondition->doForceUpdate()){ + const ConditionDamage* conditionDamage = static_cast(addCondition); + if(conditionDamage->doForceUpdate()){ return true; } @@ -1425,13 +1426,13 @@ bool ConditionDamage::updateCondition(const ConditionDamage* addCondition) } int32_t oldTotDamage = getTotalDamage(); - int32_t newTotDamage = addCondition->getTotalDamage(); + int32_t newTotDamage = conditionDamage->getTotalDamage(); if(newTotDamage < oldTotDamage){ return false; } - if(addCondition->periodDamage < periodDamage){ + if(conditionDamage->periodDamage < periodDamage){ return false; } diff --git a/source/condition.h b/source/condition.h index 35bf5ffe8..dd94886ee 100644 --- a/source/condition.h +++ b/source/condition.h @@ -332,7 +332,7 @@ class ConditionDamage: public Condition bool getNextDamage(int32_t& damage); bool doDamage(Creature* creature, int32_t damage); - bool updateCondition(const ConditionDamage* addCondition); + bool updateCondition(const Condition* addCondition); }; class ConditionSpeed: public Condition diff --git a/source/connection.cpp b/source/connection.cpp index 2f266fddc..fe461ca84 100644 --- a/source/connection.cpp +++ b/source/connection.cpp @@ -252,7 +252,7 @@ void Connection::acceptConnection() { try{ ++m_pendingRead; - m_readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); + m_readTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_READ_TIMEOUT)); m_readTimer.async_wait( boost::bind(&Connection::handleReadTimeout, boost::weak_ptr(shared_from_this()), boost::asio::placeholders::error)); // Read size of the first packet @@ -318,7 +318,7 @@ bool Connection::tryParseProxyPacket() if (g_config.getNumber(ConfigManager::ALLOW_OTC_PROXY) && size == 0xFFFEu) { try { ++m_pendingRead; - m_readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); + m_readTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_READ_TIMEOUT)); m_readTimer.async_wait(boost::bind(&Connection::handleReadTimeout, boost::weak_ptr(shared_from_this()), boost::asio::placeholders::error)); boost::asio::async_read(getHandle(), boost::asio::buffer(m_msg.getBuffer(), 4), @@ -338,7 +338,7 @@ bool Connection::tryParseProxyPacket() if (g_config.getNumber(ConfigManager::ALLOW_HAPROXY) && size == 0x0A0Du) { try { ++m_pendingRead; - m_readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); + m_readTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_READ_TIMEOUT)); m_readTimer.async_wait(boost::bind(&Connection::handleReadTimeout, boost::weak_ptr(shared_from_this()), boost::asio::placeholders::error)); boost::asio::async_read(getHandle(), boost::asio::buffer(m_msg.getBuffer(), 26), @@ -404,7 +404,7 @@ void Connection::parseHeader(const boost::system::error_code& error) try{ ++m_pendingRead; - m_readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); + m_readTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_READ_TIMEOUT)); m_readTimer.async_wait( boost::bind(&Connection::handleReadTimeout, boost::weak_ptr(shared_from_this()), boost::asio::placeholders::error)); @@ -466,7 +466,7 @@ void Connection::parsePacket(const boost::system::error_code& error) try{ ++m_pendingRead; - m_readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); + m_readTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_READ_TIMEOUT)); m_readTimer.async_wait( boost::bind(&Connection::handleReadTimeout, boost::weak_ptr(shared_from_this()), boost::asio::placeholders::error)); @@ -529,7 +529,7 @@ void Connection::internalSend(OutputMessage_ptr msg) try{ ++m_pendingWrite; - m_writeTimer.expires_from_now(boost::posix_time::seconds(Connection::write_timeout)); + m_writeTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_WRITE_TIMEOUT)); m_writeTimer.async_wait( boost::bind(&Connection::handleWriteTimeout, boost::weak_ptr(shared_from_this()), boost::asio::placeholders::error)); diff --git a/source/connection.h b/source/connection.h index eecda507d..b278e4e83 100644 --- a/source/connection.h +++ b/source/connection.h @@ -29,6 +29,9 @@ #include #include "networkmessage.h" +static constexpr int32_t CONNECTION_WRITE_TIMEOUT = 30; +static constexpr int32_t CONNECTION_READ_TIMEOUT = 30; + class Protocol; class OutputMessage; typedef boost::shared_ptr OutputMessage_ptr; @@ -81,9 +84,6 @@ class Connection : public boost::enable_shared_from_this, boost::non static uint32_t connectionCount; #endif - enum { write_timeout = 30 }; - enum { read_timeout = 30 }; - enum ConnectionState_t { CONNECTION_STATE_OPEN = 0, CONNECTION_STATE_REQUEST_CLOSE = 1, diff --git a/source/definitions.h b/source/definitions.h index f8d550af3..518ef095c 100644 --- a/source/definitions.h +++ b/source/definitions.h @@ -74,6 +74,7 @@ enum passwordType_t{ // Boost won't complain about non-working function #define BOOST_ASIO_ENABLE_CANCELIO 1 +#define BOOST_BIND_GLOBAL_PLACEHOLDERS #ifndef __FUNCTION__ #define __FUNCTION__ __func__ diff --git a/source/game.cpp b/source/game.cpp index 0b937fe2b..9e8be3410 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -988,6 +988,8 @@ ReturnValue Game::internalMoveCreature(Creature* creature, Direction direction, destPos.y += 1; canChangeFloor = false; break; + case DIRECTION_NONE: + break; } if(creature->getPlayer() && canChangeFloor){ diff --git a/source/map.h b/source/map.h index f4a9d96af..3ce0af327 100644 --- a/source/map.h +++ b/source/map.h @@ -84,7 +84,7 @@ class AStarNodes{ uint32_t curNode; }; -template class lessPointer : public std::binary_function +template class lessPointer { public: bool operator()(T*& t1, T*& t2) { diff --git a/source/monster.cpp b/source/monster.cpp index b8a99fae9..c9ca334ed 100644 --- a/source/monster.cpp +++ b/source/monster.cpp @@ -685,10 +685,10 @@ BlockType_t Monster::blockHit(Creature* attacker, CombatType_t combatType, int32 if(elementMod != 0) damage = (int32_t)std::ceil(damage * ((float)(100 - elementMod) / 100)); - if(damage <= 0){ - damage = 0; - blockType = BLOCK_DEFENSE; - } + if(damage <= 0){ + damage = 0; + blockType = BLOCK_DEFENSE; + } } return blockType; diff --git a/source/player.cpp b/source/player.cpp index e9697734d..47086516e 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -4254,7 +4254,7 @@ Skulls_t Player::getSkullClient(const Player* player) const return SKULL_NONE; } - if(getSkull() != SKULL_NONE && player->hasAttacked(this) || isGuildEnemy(player)){ + if((getSkull() != SKULL_NONE && player->hasAttacked(this)) || isGuildEnemy(player)){ return SKULL_YELLOW; } diff --git a/source/position.cpp b/source/position.cpp index fb067fa55..672c5a656 100644 --- a/source/position.cpp +++ b/source/position.cpp @@ -59,6 +59,8 @@ std::ostream& operator<<(std::ostream& os, const Direction& dir) { case NORTHEAST: os << "North-East"; break; + case DIRECTION_NONE: + break; } return os; diff --git a/source/scheduler.h b/source/scheduler.h index 54c442fbb..fffef8abd 100644 --- a/source/scheduler.h +++ b/source/scheduler.h @@ -66,7 +66,7 @@ inline SchedulerTask* createSchedulerTask(uint32_t delay, const boost::function< return new SchedulerTask(delay, f); } -class lessSchedTask : public std::binary_function +class lessSchedTask { public: bool operator()(SchedulerTask*& t1, SchedulerTask*& t2) diff --git a/source/server.h b/source/server.h index 5c3ba955b..79638d03f 100644 --- a/source/server.h +++ b/source/server.h @@ -28,6 +28,7 @@ #include #include #include +#include class Connection; typedef boost::shared_ptr Connection_ptr;