-//
-// Server.hpp
-//
-
-#pragma once
-
-#include <string>
-#include <list>
-#include <functional>
-#include "../common/network/Session.hpp"
-#include "Config.hpp"
-
-#define UDP_MAX_RECEIVE_LENGTH (2048)
-#define UDP_TEST_PACKET_TIME (5)
-
-namespace network {
-
-class Server {
- private:
- class ServerSession : public Session {
- public:
- ServerSession(boost::asio::io_service& io_service) :
- Session(io_service) {};
-
- void Start();
- };
-
- public:
- Server(const Config& config);
- void Start(CallbackFuncPtr callback);
- void Stop();
- void Stop(int interrupt_type);
- void SendAll(const Command&);
- void SendOthers(const Command&, SessionWeakPtr);
-
- bool Empty() const;
- std::string GetStatusJSON() const;
-
- int GetSessionReadAverageLimit();
- int GetUserCount() const;
- void RefreshSession();
-
- void SendUDPTestPacket(const std::string& ip_address, uint16_t port);
- void SendUDP(const std::string& message, const boost::asio::ip::udp::endpoint endpoint);
-
- bool IsBlockedAddress(const boost::asio::ip::address& address);
-
- private:
- void ReceiveSession(const SessionPtr&, const boost::system::error_code&);
-
- void ReceiveUDP(const boost::system::error_code& error, size_t bytes_recvd);
- void DoWriteUDP(const std::string& msg, const udp::endpoint& endpoint);
- void WriteUDP(const boost::system::error_code& error, boost::shared_ptr<std::string> holder);
-
- void FetchUDP(const std::string& buffer, const boost::asio::ip::udp::endpoint endpoint);
-
- private:
- Config config_;
-
- boost::asio::io_service io_service_;
- tcp::endpoint endpoint_;
- tcp::acceptor acceptor_;
-
- udp::socket socket_udp_;
- udp::endpoint sender_endpoint_;
-
- char receive_buf_udp_[2048];
+//\r
+// Server.hpp\r
+//\r
+\r
+#pragma once\r
+\r
+#include <string>\r
+#include <list>\r
+#include <functional>\r
+#include "../common/network/Session.hpp"\r
+#include "Config.hpp"\r
+\r
+#define UDP_MAX_RECEIVE_LENGTH (2048)\r
+#define UDP_TEST_PACKET_TIME (5)\r
+\r
+namespace network {\r
+\r
+class Server {\r
+ private:\r
+ class ServerSession : public Session {\r
+ public:\r
+ ServerSession(boost::asio::io_service& io_service) :\r
+ Session(io_service) {};\r
+\r
+ void Start();\r
+ };\r
+\r
+ public:\r
+ Server(const Config& config);\r
+ void Start(CallbackFuncPtr callback);\r
+ void Stop();\r
+ void Stop(int interrupt_type);\r
+ void SendAll(const Command&);\r
+ void SendTo(const Command&, uint32_t);\r
+ void SendOthers(const Command&, SessionWeakPtr);\r
+\r
+ bool Empty() const;\r
+ std::string GetStatusJSON() const;\r
+\r
+ int GetSessionReadAverageLimit();\r
+ int GetUserCount() const;\r
+ void RefreshSession();\r
+\r
+ void SendUDPTestPacket(const std::string& ip_address, uint16_t port);\r
+ void SendUDP(const std::string& message, const boost::asio::ip::udp::endpoint endpoint);\r
+\r
+ bool IsBlockedAddress(const boost::asio::ip::address& address);\r
+\r
+ private:\r
+ void ReceiveSession(const SessionPtr&, const boost::system::error_code&);\r
+\r
+ void ReceiveUDP(const boost::system::error_code& error, size_t bytes_recvd);\r
+ void DoWriteUDP(const std::string& msg, const udp::endpoint& endpoint);\r
+ void WriteUDP(const boost::system::error_code& error, boost::shared_ptr<std::string> holder);\r
+\r
+ void FetchUDP(const std::string& buffer, const boost::asio::ip::udp::endpoint endpoint);\r
+\r
+ private:\r
+ Config config_;\r
+\r
+ boost::asio::io_service io_service_;\r
+ tcp::endpoint endpoint_;\r
+ tcp::acceptor acceptor_;\r
+\r
+ udp::socket socket_udp_;\r
+ udp::endpoint sender_endpoint_;\r
+\r
+ char receive_buf_udp_[2048];\r
uint8_t udp_packet_count_;\r
-
- CallbackFuncPtr callback_;
-
- boost::mutex mutex_;
- std::list<SessionWeakPtr> sessions_;
-
-};
-
-}
+\r
+ CallbackFuncPtr callback_;\r
+\r
+ boost::mutex mutex_;\r
+ std::list<SessionWeakPtr> sessions_;\r
+\r
+};\r
+\r
+}\r
-//
-// MMO Server
-//
-
-#include <iostream>
-#include <sstream>
-#include <ctime>
-#include <boost/format.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/foreach.hpp>
-#include "version.hpp"
-#include "Server.hpp"
-#include "../common/network/Encrypter.hpp"
-#include "../common/network/Signature.hpp"
-#include "../common/database/AccountProperty.hpp"
-#include "../common/Logger.hpp"
-#include "Config.hpp"
-#include "Account.hpp"
-#include "version.hpp"
-#ifdef __linux__
-#include "ServerSigHandler.hpp"
-#include <csignal>
-#endif
-
-#ifdef _WIN32
-#include <boost/interprocess/windows_shared_memory.hpp>
-#include <boost/interprocess/mapped_region.hpp>
-#endif
-
-using namespace boost::posix_time;
-
-int main(int argc, char* argv[])
-{
- // 設定を読み込み
- Config config("config.json");
-
- Logger::Info(_T("%s"), unicode::ToTString(MMO_VERSION_TEXT));
-
- try {
-
- // 署名
- network::Signature sign("server_key");
-
- // アカウント
- Account account("account.db");
- network::Server server(config);
-
- auto callback = std::make_shared<std::function<void(network::Command)>>(
- [&server, &account, &sign, &config](network::Command c){
-
- // ログを出力
- auto msg = (boost::format("Receive: 0x%08x %dbyte") % c.header() % c.body().size()).str();
- if (auto session = c.session().lock()) {
- msg += " from " + session->global_ip();
- }
-
- // if (auto session = c.session().lock()) {
- // std::cout << "Write Average: " << session->GetReadByteAverage() << "bytes" << std::endl;
- // }
-
- switch (c.header()) {
-
- // ステータス要求
- case network::header::ServerRequstedStatus:
- {
- // ステータスを送り返す
- server.SendUDP(server.GetStatusJSON(), c.udp_endpoint());
- }
- break;
-
- // JSONメッセージ受信
- case network::header::ServerReceiveJSON:
- {
- if (auto session = c.session().lock()) {
+//\r
+// MMO Server\r
+//\r
+\r
+#include <iostream>\r
+#include <sstream>\r
+#include <ctime>\r
+#include <boost/format.hpp>\r
+#include <boost/date_time/posix_time/posix_time.hpp>\r
+#include <boost/property_tree/json_parser.hpp>\r
+#include <boost/foreach.hpp>\r
+#include "version.hpp"\r
+#include "Server.hpp"\r
+#include "../common/network/Encrypter.hpp"\r
+#include "../common/network/Signature.hpp"\r
+#include "../common/database/AccountProperty.hpp"\r
+#include "../common/Logger.hpp"\r
+#include "Config.hpp"\r
+#include "Account.hpp"\r
+#include "version.hpp"\r
+#ifdef __linux__\r
+#include "ServerSigHandler.hpp"\r
+#include <csignal>\r
+#endif\r
+\r
+#ifdef _WIN32\r
+#include <boost/interprocess/windows_shared_memory.hpp>\r
+#include <boost/interprocess/mapped_region.hpp>\r
+#endif\r
+\r
+using namespace boost::posix_time;\r
+\r
+int main(int argc, char* argv[])\r
+{\r
+ // 設定を読み込み\r
+ Config config("config.json");\r
+\r
+ Logger::Info(_T("%s"), unicode::ToTString(MMO_VERSION_TEXT));\r
+\r
+ try {\r
+\r
+ // 署名\r
+ network::Signature sign("server_key");\r
+\r
+ // アカウント\r
+ Account account("account.db");\r
+ network::Server server(config);\r
+\r
+ auto callback = std::make_shared<std::function<void(network::Command)>>(\r
+ [&server, &account, &sign, &config](network::Command c){\r
+\r
+ // ログを出力\r
+ auto msg = (boost::format("Receive: 0x%08x %dbyte") % c.header() % c.body().size()).str();\r
+ if (auto session = c.session().lock()) {\r
+ msg += " from " + session->global_ip();\r
+ }\r
+\r
+ // if (auto session = c.session().lock()) {\r
+ // std::cout << "Write Average: " << session->GetReadByteAverage() << "bytes" << std::endl;\r
+ // }\r
+\r
+ switch (c.header()) {\r
+\r
+ // ステータス要求\r
+ case network::header::ServerRequstedStatus:\r
+ {\r
+ // ステータスを送り返す\r
+ server.SendUDP(server.GetStatusJSON(), c.udp_endpoint());\r
+ }\r
+ break;\r
+\r
+ // JSONメッセージ受信\r
+ case network::header::ServerReceiveJSON:\r
+ {\r
+ if (auto session = c.session().lock()) {\r
uint32_t id = static_cast<unsigned int>(session->id());\r
- if (id == 0) {
- Logger::Error(_T("Invalid session id"));
- break;
- }
-
- ptime now = second_clock::universal_time();
- auto time_string = to_iso_extended_string(now);
-
- std::string info_json;
- info_json += "{";
- info_json += (boost::format("\"id\":\"%d\",") % id).str();
- info_json += (boost::format("\"time\":\"%s\"") % time_string).str();
- info_json += "}";
-
- std::string message_json = c.body();
-
- server.SendAll(network::ClientReceiveJSON(info_json, message_json));
- Logger::Info("Receive JSON: %s", message_json);
- Logger::Info(msg);
- }
- }
- break;
-
- // 位置情報受信
- case network::header::ServerUpdatePlayerPosition:
- {
- if (auto session = c.session().lock()) {
- PlayerPosition pos;
- network::Utils::Deserialize(c.body(), &pos.x, &pos.y, &pos.z, &pos.theta, &pos.vy);
- account.SetUserPosition(session->id(), pos);
- server.SendOthers(network::ClientUpdatePlayerPosition(session->id(),
- pos.x,pos.y,pos.z,pos.theta, pos.vy), c.session());
- }
- }
- break;
-
- // 公開鍵フィンガープリント受信
- case network::header::ServerReceiveClientInfo:
- {
- if (auto session = c.session().lock()) {
-
- std::string finger_print;
- uint16_t version;
- uint16_t udp_port;
-
- network::Utils::Deserialize(c.body(), &finger_print, &version, &udp_port);
-
- // クライアントのプロトコルバージョンをチェック
- if (version != MMO_PROTOCOL_VERSION) {
- Logger::Info("Unsupported Client Version : v%d", version);
- session->Send(network::ClientReceiveUnsupportVersionError(1));
- return;
- }
-
- // UDPパケットの宛先を設定
- session->set_udp_port(udp_port);
-
- Logger::Info("UDP destination is %s:%d", session->global_ip(), session->udp_port());
-
- // テスト送信
- server.SendUDPTestPacket(session->global_ip(), session->udp_port());
-
+ if (id == 0) {\r
+ Logger::Error(_T("Invalid session id"));\r
+ break;\r
+ }\r
+ \r
+ std::stringstream message_json(c.body());\r
+\r
+ using namespace boost::property_tree;\r
+ ptree message_tree;\r
+ json_parser::read_json(message_json, message_tree);\r
+\r
+ // プライベートメッセージの処理\r
+ std::list<uint32_t> destination_list;\r
+ auto private_list_tree = message_tree.get_child("private", ptree());\r
+ BOOST_FOREACH(const auto& user_id, private_list_tree) {\r
+ destination_list.push_back(user_id.second.get_value<uint32_t>());\r
+ }\r
+\r
+ ptime now = second_clock::universal_time();\r
+ auto time_string = to_iso_extended_string(now);\r
+\r
+ std::string info_json;\r
+ info_json += "{";\r
+ info_json += (boost::format("\"id\":\"%d\",") % id).str();\r
+ info_json += (boost::format("\"time\":\"%s\"") % time_string).str();\r
+ info_json += "}";\r
+\r
+ auto send_command = network::ClientReceiveJSON(info_json, message_json.str());\r
+\r
+ if (destination_list.size() > 0) {\r
+ BOOST_FOREACH(uint32_t user_id, destination_list) {\r
+ server.SendTo(send_command, user_id);\r
+ }\r
+ } else {\r
+ server.SendAll(send_command);\r
+ }\r
+\r
+ Logger::Info("Receive JSON: %s", message_json);\r
+ }\r
+ }\r
+ break;\r
+\r
+ // 位置情報受信\r
+ case network::header::ServerUpdatePlayerPosition:\r
+ {\r
+ if (auto session = c.session().lock()) {\r
+ PlayerPosition pos;\r
+ network::Utils::Deserialize(c.body(), &pos.x, &pos.y, &pos.z, &pos.theta, &pos.vy);\r
+ account.SetUserPosition(session->id(), pos);\r
+ server.SendOthers(network::ClientUpdatePlayerPosition(session->id(),\r
+ pos.x,pos.y,pos.z,pos.theta, pos.vy), c.session());\r
+ }\r
+ }\r
+ break;\r
+\r
+ // 公開鍵フィンガープリント受信\r
+ case network::header::ServerReceiveClientInfo:\r
+ {\r
+ if (auto session = c.session().lock()) {\r
+\r
+ std::string finger_print;\r
+ uint16_t version;\r
+ uint16_t udp_port;\r
+\r
+ network::Utils::Deserialize(c.body(), &finger_print, &version, &udp_port);\r
+\r
+ // クライアントのプロトコルバージョンをチェック\r
+ if (version != MMO_PROTOCOL_VERSION) {\r
+ Logger::Info("Unsupported Client Version : v%d", version);\r
+ session->Send(network::ClientReceiveUnsupportVersionError(1));\r
+ return;\r
+ }\r
+\r
+ // UDPパケットの宛先を設定\r
+ session->set_udp_port(udp_port);\r
+\r
+ Logger::Info("UDP destination is %s:%d", session->global_ip(), session->udp_port());\r
+\r
+ // テスト送信\r
+ server.SendUDPTestPacket(session->global_ip(), session->udp_port());\r
+\r
uint32_t id = account.GetUserIdFromFingerPrint(finger_print);\r
- if (id == 0) {
- // 未登録の場合、公開鍵を要求
- session->Send(network::ClientRequestedPublicKey());
- } else {
+ if (id == 0) {\r
+ // 未登録の場合、公開鍵を要求\r
+ session->Send(network::ClientRequestedPublicKey());\r
+ } else {\r
uint32_t user_id = static_cast<uint32_t>(id);\r
- // ログイン
- session->set_id(user_id);
- account.LogIn(user_id);
- session->encrypter().SetPublicKey(account.GetPublicKey(user_id));
-
- account.SetUserIPAddress(session->id(), session->global_ip());
- account.SetUserUDPPort(session->id(), session->udp_port());
-
- // 共通鍵を送り返す
- auto key = session->encrypter().GetCryptedCommonKey();
- session->Send(network::ClientReceiveCommonKey(key, sign.Sign(key), user_id));
-
- }
- Logger::Info(msg);
- }
- }
- break;
-
- // 公開鍵受信
- case network::header::ServerReceivePublicKey:
- {
- if (auto session = c.session().lock()) {
+ // ログイン\r
+ session->set_id(user_id);\r
+ account.LogIn(user_id);\r
+ session->encrypter().SetPublicKey(account.GetPublicKey(user_id));\r
+\r
+ account.SetUserIPAddress(session->id(), session->global_ip());\r
+ account.SetUserUDPPort(session->id(), session->udp_port());\r
+\r
+ // 共通鍵を送り返す\r
+ auto key = session->encrypter().GetCryptedCommonKey();\r
+ session->Send(network::ClientReceiveCommonKey(key, sign.Sign(key), user_id));\r
+\r
+ }\r
+ Logger::Info(msg);\r
+ }\r
+ }\r
+ break;\r
+\r
+ // 公開鍵受信\r
+ case network::header::ServerReceivePublicKey:\r
+ {\r
+ if (auto session = c.session().lock()) {\r
uint32_t user_id = account.RegisterPublicKey(c.body());\r
- assert(user_id > 0);
-
- // ログイン
- session->set_id(user_id);
- account.LogIn(user_id);
- session->encrypter().SetPublicKey(account.GetPublicKey(user_id));
-
- account.SetUserIPAddress(session->id(), session->global_ip());
- account.SetUserUDPPort(session->id(), session->udp_port());
-
- // 共通鍵を送り返す
- auto key = session->encrypter().GetCryptedCommonKey();
- session->Send(network::ClientReceiveCommonKey(key, sign.Sign(key), user_id));
-
- }
- Logger::Info(msg);
- }
- break;
-
- // 暗号化通信開始
- case network::header::ServerStartEncryptedSession:
- {
- if (auto session = c.session().lock()) {
-
- session->Send(network::ClientReceiveServerInfo(config.stage()));
-
- session->Send(network::ClientStartEncryptedSession());
- session->EnableEncryption();
-
- Logger::Info(msg);
- }
- }
- break;
-
- // アカウント初期化情報の受信
- case network::header::ServerReceiveAccountInitializeData:
- {
- if (auto session = c.session().lock()) {
- account.LoadInitializeData(session->id(), c.body());
-
- const auto& list = account.GetIDList();
- BOOST_FOREACH(UserID user_id, list) {
- session->Send(network::ClientReceiveAccountRevisionUpdateNotify(user_id,
- account.GetUserRevision(user_id)));
- }
-
- server.SendOthers(
- network::ClientReceiveAccountRevisionUpdateNotify(session->id(),
- account.GetUserRevision(session->id())), c.session());
-
- Logger::Info(msg);
- }
- }
- break;
-
- // アカウント更新情報の要求
- case network::header::ServerRequestedAccountRevisionPatch:
- {
- if (auto session = c.session().lock()) {
+ assert(user_id > 0);\r
+\r
+ // ログイン\r
+ session->set_id(user_id);\r
+ account.LogIn(user_id);\r
+ session->encrypter().SetPublicKey(account.GetPublicKey(user_id));\r
+\r
+ account.SetUserIPAddress(session->id(), session->global_ip());\r
+ account.SetUserUDPPort(session->id(), session->udp_port());\r
+\r
+ // 共通鍵を送り返す\r
+ auto key = session->encrypter().GetCryptedCommonKey();\r
+ session->Send(network::ClientReceiveCommonKey(key, sign.Sign(key), user_id));\r
+\r
+ }\r
+ Logger::Info(msg);\r
+ }\r
+ break;\r
+\r
+ // 暗号化通信開始\r
+ case network::header::ServerStartEncryptedSession:\r
+ {\r
+ if (auto session = c.session().lock()) {\r
+ \r
+ session->Send(network::ClientReceiveServerInfo(config.stage()));\r
+\r
+ session->Send(network::ClientStartEncryptedSession());\r
+ session->EnableEncryption();\r
+\r
+ Logger::Info(msg);\r
+ }\r
+ }\r
+ break;\r
+\r
+ // アカウント初期化情報の受信\r
+ case network::header::ServerReceiveAccountInitializeData:\r
+ {\r
+ if (auto session = c.session().lock()) {\r
+ account.LoadInitializeData(session->id(), c.body());\r
+\r
+ const auto& list = account.GetIDList();\r
+ BOOST_FOREACH(UserID user_id, list) {\r
+ session->Send(network::ClientReceiveAccountRevisionUpdateNotify(user_id,\r
+ account.GetUserRevision(user_id)));\r
+ }\r
+\r
+ server.SendOthers(\r
+ network::ClientReceiveAccountRevisionUpdateNotify(session->id(),\r
+ account.GetUserRevision(session->id())), c.session());\r
+\r
+ Logger::Info(msg);\r
+ }\r
+ }\r
+ break;\r
+\r
+ // アカウント更新情報の要求\r
+ case network::header::ServerRequestedAccountRevisionPatch:\r
+ {\r
+ if (auto session = c.session().lock()) {\r
uint32_t user_id;\r
uint32_t client_revision;\r
- network::Utils::Deserialize(c.body(), &user_id, &client_revision);
-
- if (client_revision < account.GetUserRevision(user_id)) {
- session->Send(network::ClientReceiveAccountRevisionPatch(
- account.GetUserRevisionPatch(user_id, client_revision)));
- }
- Logger::Info(msg);
- }
- }
- break;
-
- case network::header::ServerUpdateAccountProperty:
- {
- if (auto session = c.session().lock()) {
- AccountProperty property;
- std::string value;
- network::Utils::Deserialize(c.body(), &property, &value);
-
- auto old_revision = account.GetUserRevision(session->id());
-
- switch (property) {
-
- case NAME:
- {
- account.SetUserName(session->id(), value);
- }
- break;
- case TRIP:
- {
- account.SetUserTrip(session->id(), value);
- }
- break;
- case MODEL_NAME:
- {
- account.SetUserModelName(session->id(), value);
- }
- break;
- default:
- ;
- }
-
- auto new_revison = account.GetUserRevision(session->id());
- if (new_revison > old_revision) {
- server.SendAll(
- network::ClientReceiveAccountRevisionUpdateNotify(
- session->id(),new_revison));
- }
-
- Logger::Info(msg);
- }
- }
- break;
-
- // エラー
- case network::header::FatalConnectionError:
- {
- if (c.body().size() > 0) {
- int user_id;
- network::Utils::Deserialize(c.body(), &user_id);
- account.LogOut(user_id);
-
- server.SendAll(
- network::ClientReceiveAccountRevisionUpdateNotify(user_id,
- account.GetUserRevision(user_id)));
-
- Logger::Info("Logout User: %d", user_id);
- // account.Remove(user_id);
- }
- }
- Logger::Info(msg);
- break;
-
- default:
- break;
- }
-
- });
-
- bool execute_with_client;
- try {
- #ifdef _WIN32
- using namespace boost::interprocess;
- windows_shared_memory shm(open_only, "MMO_SERVER_WITH_CLIENT", read_only);
- #endif
- execute_with_client = true;
- } catch(std::exception& e) {
- Logger::Info("Stand-alone Mode");
- execute_with_client = false;
- }
-
- // クライアントから起動している場合、クライアントの状態を監視
- #ifdef _WIN32
- if (execute_with_client) {
- boost::thread([&server](){
- while (1) {
- boost::this_thread::sleep(boost::posix_time::milliseconds(4000));
- try {
- using namespace boost::interprocess;
- windows_shared_memory shm(open_only, "MMO_SERVER_WITH_CLIENT", read_only);
- } catch(std::exception& e) {
- server.Stop();
- break;
- }
- }
- });
- }
- #endif
- #ifdef __linux__
- network::ServerSigHandler handler(SIGINT,&server);
- #endif
- server.Start(callback);
-
- } catch (std::exception& e) {
- Logger::Error(e.what());
-
- Logger::Info("Stop Server");
- }
-
- return 0;
-
-}
+ network::Utils::Deserialize(c.body(), &user_id, &client_revision);\r
+\r
+ if (client_revision < account.GetUserRevision(user_id)) {\r
+ session->Send(network::ClientReceiveAccountRevisionPatch(\r
+ account.GetUserRevisionPatch(user_id, client_revision)));\r
+ }\r
+ Logger::Info(msg);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case network::header::ServerUpdateAccountProperty:\r
+ {\r
+ if (auto session = c.session().lock()) {\r
+ AccountProperty property;\r
+ std::string value;\r
+ network::Utils::Deserialize(c.body(), &property, &value);\r
+\r
+ auto old_revision = account.GetUserRevision(session->id());\r
+\r
+ switch (property) {\r
+\r
+ case NAME:\r
+ {\r
+ account.SetUserName(session->id(), value);\r
+ }\r
+ break;\r
+ case TRIP:\r
+ {\r
+ account.SetUserTrip(session->id(), value);\r
+ }\r
+ break;\r
+ case MODEL_NAME:\r
+ {\r
+ account.SetUserModelName(session->id(), value);\r
+ }\r
+ break;\r
+ default:\r
+ ;\r
+ }\r
+\r
+ auto new_revison = account.GetUserRevision(session->id());\r
+ if (new_revison > old_revision) {\r
+ server.SendAll(\r
+ network::ClientReceiveAccountRevisionUpdateNotify(\r
+ session->id(),new_revison));\r
+ }\r
+\r
+ Logger::Info(msg);\r
+ }\r
+ }\r
+ break;\r
+\r
+ // エラー\r
+ case network::header::FatalConnectionError:\r
+ {\r
+ if (c.body().size() > 0) {\r
+ int user_id;\r
+ network::Utils::Deserialize(c.body(), &user_id);\r
+ account.LogOut(user_id);\r
+\r
+ server.SendAll(\r
+ network::ClientReceiveAccountRevisionUpdateNotify(user_id,\r
+ account.GetUserRevision(user_id)));\r
+\r
+ Logger::Info("Logout User: %d", user_id);\r
+ // account.Remove(user_id);\r
+ }\r
+ }\r
+ Logger::Info(msg);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ });\r
+\r
+ bool execute_with_client;\r
+ try {\r
+ #ifdef _WIN32\r
+ using namespace boost::interprocess;\r
+ windows_shared_memory shm(open_only, "MMO_SERVER_WITH_CLIENT", read_only);\r
+ #endif\r
+ execute_with_client = true;\r
+ } catch(std::exception& e) {\r
+ Logger::Info("Stand-alone Mode");\r
+ execute_with_client = false;\r
+ }\r
+\r
+ // クライアントから起動している場合、クライアントの状態を監視\r
+ #ifdef _WIN32\r
+ if (execute_with_client) {\r
+ boost::thread([&server](){\r
+ while (1) {\r
+ boost::this_thread::sleep(boost::posix_time::milliseconds(4000));\r
+ try {\r
+ using namespace boost::interprocess;\r
+ windows_shared_memory shm(open_only, "MMO_SERVER_WITH_CLIENT", read_only);\r
+ } catch(std::exception& e) {\r
+ server.Stop();\r
+ break;\r
+ }\r
+ }\r
+ });\r
+ }\r
+ #endif\r
+ #ifdef __linux__\r
+ network::ServerSigHandler handler(SIGINT,&server);\r
+ #endif\r
+ server.Start(callback);\r
+\r
+ } catch (std::exception& e) {\r
+ Logger::Error(e.what());\r
+ \r
+ Logger::Info("Stop Server");\r
+ }\r
+\r
+ return 0;\r
+\r
+}\r