OSDN Git Service

プロトコルバージョンを3に変更
[mmo/main.git] / server / Server.cpp
index c2e29c2..59e6912 100644 (file)
@@ -1,4 +1,4 @@
-//\r
+//\r
 // Server.cpp\r
 //\r
 \r
@@ -7,18 +7,20 @@
 #include <algorithm>\r
 #include <boost/make_shared.hpp>\r
 #include <boost/foreach.hpp>\r
+#include <boost/archive/text_oarchive.hpp>\r
+#include <boost/property_tree/ptree_serialization.hpp>\r
 #include "../common/Logger.hpp"\r
 #include "../common/network/Command.hpp"\r
 #include "../common/network/Utils.hpp"\r
 \r
 namespace network {\r
 \r
-    Server::Server(const Config& config) :\r
-                       config_(config),\r
-            endpoint_(tcp::v4(), config.port()),\r
+    Server::Server() :\r
+            endpoint_(tcp::v4(), config_.port()),\r
             acceptor_(io_service_, endpoint_),\r
-            socket_udp_(io_service_, udp::endpoint(udp::v4(), config.port())),\r
-            udp_packet_count_(0)\r
+            socket_udp_(io_service_, udp::endpoint(udp::v4(), config_.port())),\r
+            udp_packet_count_(0),\r
+                       recent_chat_log_(10)\r
     {\r
     }\r
 \r
@@ -28,14 +30,15 @@ namespace network {
                 [&](network::Command c){\r
 \r
             // ログアウト\r
-            if (c.header() == network::header::FatalConnectionError) {\r
+            if (c.header() == network::header::FatalConnectionError || \r
+                               c.header() == network::header::UserFatalConnectionError) {\r
                 if (callback) {\r
                                        (*callback)(c);\r
                                }\r
             } else if (auto session = c.session().lock()) {\r
                                auto read_average = session->GetReadByteAverage();\r
                                if (read_average > config_.receive_limit_2()) {\r
-                                       Logger::Info(_T("Banished session: %d"), session->id());\r
+                                       Logger::Info(_T("Banished a session: %d %dbyte/s"), session->id(), read_average);\r
                                        session->Close();\r
                                } else if(read_average > config_.receive_limit_1()) {\r
                                        Logger::Info(_T("Receive limit exceeded: %d: %d byte/s"), session->id(), read_average);\r
@@ -48,6 +51,12 @@ namespace network {
 \r
         });\r
 \r
+               BOOST_FOREACH(const auto& host, config().lobby_servers()) {\r
+                       udp::resolver resolver(io_service_);\r
+                       udp::resolver::query query(udp::v4(), host.c_str(), "39380");\r
+                       lobby_hosts_.push_back(resolver.resolve(query));\r
+               }\r
+\r
         {\r
         auto new_session = boost::make_shared<ServerSession>(io_service_);\r
         acceptor_.async_accept(new_session->tcp_socket(),\r
@@ -80,7 +89,9 @@ namespace network {
        int Server::GetUserCount() const\r
        {\r
                auto count = std::count_if(sessions_.begin(), sessions_.end(),\r
-                       [](const SessionWeakPtr& s){ return !s.expired() && s.lock()->online(); });\r
+                       [](const SessionWeakPtr& s){ \r
+                               return !s.expired() && s.lock()->online() && s.lock()->id() > 0; \r
+                       });\r
 \r
                return count;\r
        }\r
@@ -99,6 +110,62 @@ namespace network {
                return msg;\r
        }\r
 \r
+       std::string Server::GetFullStatus() const\r
+       {\r
+               using namespace boost::property_tree;\r
+               ptree xml_ptree;\r
+\r
+               xml_ptree.put_child("config", config_.pt());\r
+               xml_ptree.put("version", (boost::format("%d.%d.%d") \r
+                       % MMO_VERSION_MAJOR % MMO_VERSION_MINOR % MMO_VERSION_REVISION).str());\r
+               xml_ptree.put("protocol_version", MMO_PROTOCOL_VERSION);\r
+\r
+               {\r
+                       ptree player_array;\r
+                       auto id_list = account_.GetIDList();\r
+                       BOOST_FOREACH(const auto& s, sessions_) {\r
+                               if (!s.expired() && s.lock()->online() && s.lock()->id() > 0) {\r
+                                       auto id = s.lock()->id();\r
+                                       ptree player;\r
+                                       player.put("name", account_.GetUserName(id));\r
+                                       player.put("model_name", account_.GetUserModelName(id));\r
+                                       player_array.push_back(std::make_pair("", player));\r
+                               }\r
+                       }\r
+                       xml_ptree.put_child("players", player_array);\r
+               }\r
+\r
+               //{\r
+               //      ptree log_array;\r
+               //      BOOST_FOREACH(const std::string& msg, recent_chat_log_) {\r
+               //              log_array.push_back(std::make_pair("", msg));\r
+               //      }\r
+               //      xml_ptree.put_child("recent_chat_log", log_array);\r
+               //}\r
+\r
+               xml_ptree.put_child("channels", channel_.pt());\r
+               std::stringstream stream;\r
+               boost::archive::text_oarchive oa(stream);\r
+               oa << xml_ptree;\r
+\r
+               return stream.str();\r
+       }\r
+\r
+       const Config& Server::config() const\r
+       {\r
+               return config_;\r
+       }\r
+\r
+       Account& Server::account()\r
+       {\r
+               return account_;\r
+       }\r
+       \r
+       void Server::AddChatLog(const std::string& msg)\r
+       {\r
+               recent_chat_log_.push_back(msg);\r
+       }\r
+\r
     bool Server::Empty() const\r
     {\r
         return GetUserCount() == 0;\r
@@ -116,17 +183,17 @@ namespace network {
 \r
     void Server::ReceiveSession(const SessionPtr& session, const boost::system::error_code& error)\r
     {\r
+               \r
+               config_.Reload();\r
+\r
                const auto address = session->tcp_socket().remote_endpoint().address();\r
+\r
+               // 拒否IPでないか判定\r
                if(IsBlockedAddress(address)) {\r
                        Logger::Info("Blocked IP Address: %s", address);\r
             session->Close();\r
 \r
-               } else if (GetUserCount() >= config_.capacity()) {\r
-                       Logger::Info("Refused Session");\r
-            session->SyncSend(ClientReceiveServerCrowdedError());\r
-            session->Close();\r
-\r
-        } else {\r
+               } else {\r
             session->set_on_receive(callback_);\r
             session->Start();\r
             sessions_.push_back(SessionWeakPtr(session));\r
@@ -136,8 +203,8 @@ namespace network {
         }\r
 \r
         auto new_session = boost::make_shared<ServerSession>(io_service_);\r
-         acceptor_.async_accept(new_session->tcp_socket(),\r
-                 boost::bind(&Server::ReceiveSession, this, new_session, boost::asio::placeholders::error));\r
+        acceptor_.async_accept(new_session->tcp_socket(),\r
+                boost::bind(&Server::ReceiveSession, this, new_session, boost::asio::placeholders::error));\r
 \r
                RefreshSession();\r
     }\r
@@ -153,21 +220,31 @@ namespace network {
                Logger::Info("Active connection: %d", GetUserCount());\r
        }\r
 \r
-    void Server::SendAll(const Command& command)\r
+    void Server::SendAll(const Command& command, int channel, bool limited)\r
     {\r
         BOOST_FOREACH(SessionWeakPtr& ptr, sessions_) {\r
             if (auto session = ptr.lock()) {\r
-                session->Send(command);\r
+                               if (channel < 0 || (channel >= 0 && session->channel() == channel)) {\r
+                                       if (!limited || session->write_average_limit() > session->GetWriteByteAverage()) {\r
+                                               if (session->id() > 0) {\r
+                                                       session->Send(command);\r
+                                               }\r
+                                       }\r
+                               }\r
             }\r
         }\r
     }\r
 \r
-    void Server::SendAllLimited(const Command& command)\r
+    void Server::SendOthers(const Command& command, uint32_t self_id, int channel, bool limited)\r
     {\r
         BOOST_FOREACH(SessionWeakPtr& ptr, sessions_) {\r
             if (auto session = ptr.lock()) {\r
-                               if (session->write_average_limit() > session->GetWriteByteAverage()) {\r
-                                       session->Send(command);\r
+                               if (channel < 0 || (channel >= 0 && session->channel() == channel)) {\r
+                                       if (!limited || session->write_average_limit() > session->GetWriteByteAverage()) {\r
+                                               if (session->id() > 0 && session->id() != self_id) {\r
+                                                       session->Send(command);\r
+                                               }\r
+                                       }\r
                                }\r
             }\r
         }\r
@@ -185,34 +262,6 @@ namespace network {
                }\r
        }\r
 \r
-    void Server::SendOthers(const Command& command, SessionWeakPtr self_ptr)\r
-    {\r
-        BOOST_FOREACH(SessionWeakPtr& ptr, sessions_) {\r
-            if (auto session = ptr.lock()) {\r
-                if (auto self = self_ptr.lock()) {\r
-                    if (*session != *self) {\r
-                        session->Send(command);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    void Server::SendOthersLimited(const Command& command, SessionWeakPtr self_ptr)\r
-    {\r
-        BOOST_FOREACH(SessionWeakPtr& ptr, sessions_) {\r
-            if (auto session = ptr.lock()) {\r
-                if (auto self = self_ptr.lock()) {\r
-                    if (*session != *self) {\r
-                                               if (session->write_average_limit() > session->GetWriteByteAverage()) {\r
-                                                       session->Send(command);\r
-                                               }\r
-                    }\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
     void Server::SendUDPTestPacket(const std::string& ip_address, uint16_t port)\r
     {\r
         using boost::asio::ip::udp;\r
@@ -231,6 +280,14 @@ namespace network {
         }\r
     }\r
 \r
+       void Server::SendPublicPing()\r
+       {\r
+               static char request[] = "P";\r
+               BOOST_FOREACH(const auto& iterator, lobby_hosts_) {\r
+                       io_service_.post(boost::bind(&Server::DoWriteUDP, this, request, *iterator));\r
+               }\r
+       }\r
+\r
     void Server::SendUDP(const std::string& message, const boost::asio::ip::udp::endpoint endpoint)\r
     {\r
                io_service_.post(boost::bind(&Server::DoWriteUDP, this, message, endpoint));\r