Revisão | 4169eaba9b61717a5898fe1bd883d52240008c21 (tree) |
---|---|
Hora | 2012-10-07 21:58:12 |
Autor | h2so5 <h2so5@git....> |
Commiter | h2so5 |
Linux環境でビルドが通らない問題を修正
チャンネル機能を途中まで実装
@@ -1,6 +1,15 @@ | ||
1 | 1 | { |
2 | 2 | "port": 39390, |
3 | + | |
3 | 4 | "server_name": "MMO Server", |
5 | + "server_note": "MikuMikuOnlineのサーバーです", | |
6 | + | |
7 | + "public": true, | |
8 | + "lobby_servers": | |
9 | + [ | |
10 | + "m2op.net" | |
11 | + ], | |
12 | + | |
4 | 13 | "stage": "stage:ケロリン町", |
5 | 14 | "capacity": 20, |
6 | 15 |
@@ -28,6 +28,11 @@ boost::asio::ip::udp::endpoint Command::udp_endpoint() const | ||
28 | 28 | return udp_endpoint_; |
29 | 29 | } |
30 | 30 | |
31 | +bool Command::plain() const | |
32 | +{ | |
33 | + return plain_; | |
34 | +} | |
35 | + | |
31 | 36 | FatalConnectionError::FatalConnectionError() : |
32 | 37 | Command(header::FatalConnectionError, "") |
33 | 38 | { |
@@ -132,4 +137,10 @@ ClientReceiveFullServerInfo::ClientReceiveFullServerInfo(const std::string& xml) | ||
132 | 137 | |
133 | 138 | } |
134 | 139 | |
140 | +ClientReceivePlainFullServerInfo::ClientReceivePlainFullServerInfo(const std::string& xml) : | |
141 | + Command(header::ClientReceivePlainFullServerInfo, Utils::Serialize(xml)) | |
142 | +{ | |
143 | + plain_ = true; | |
144 | +} | |
145 | + | |
135 | 146 | } |
@@ -19,20 +19,25 @@ typedef boost::weak_ptr<Session> SessionWeakPtr; | ||
19 | 19 | |
20 | 20 | class Command { |
21 | 21 | public: |
22 | - Command(header::CommandHeader header, const std::string body) : | |
23 | - header_(header), body_(body) {} | |
22 | + Command(header::CommandHeader header, | |
23 | + const std::string body) : | |
24 | + header_(header), body_(body), plain_(false) {} | |
24 | 25 | |
25 | - Command(header::CommandHeader header, const std::string body, const SessionWeakPtr& session) : | |
26 | - header_(header), body_(body), session_(session) {} | |
26 | + Command(header::CommandHeader header, | |
27 | + const std::string body, | |
28 | + const SessionWeakPtr& session) : | |
29 | + header_(header), body_(body), session_(session), plain_(false) {} | |
27 | 30 | |
28 | - Command(header::CommandHeader header, const std::string body, | |
31 | + Command(header::CommandHeader header, | |
32 | + const std::string body, | |
29 | 33 | const boost::asio::ip::udp::endpoint& udp_endpoint) : |
30 | - header_(header), body_(body), udp_endpoint_(udp_endpoint) {} | |
34 | + header_(header), body_(body), udp_endpoint_(udp_endpoint), plain_(false) {} | |
31 | 35 | |
32 | 36 | header::CommandHeader header() const; |
33 | 37 | const std::string& body() const; |
34 | 38 | SessionWeakPtr session(); |
35 | 39 | boost::asio::ip::udp::endpoint udp_endpoint() const; |
40 | + bool plain() const; | |
36 | 41 | |
37 | 42 | private: |
38 | 43 | header::CommandHeader header_; |
@@ -41,6 +46,7 @@ typedef boost::weak_ptr<Session> SessionWeakPtr; | ||
41 | 46 | std::string body_; |
42 | 47 | SessionWeakPtr session_; |
43 | 48 | boost::asio::ip::udp::endpoint udp_endpoint_; |
49 | + bool plain_; | |
44 | 50 | }; |
45 | 51 | |
46 | 52 | template<header::CommandHeader Header> |
@@ -56,6 +62,7 @@ typedef boost::weak_ptr<Session> SessionWeakPtr; | ||
56 | 62 | typedef CommandTemplate<header::ClientRequestedClientInfo> ClientRequestedClientInfo; |
57 | 63 | typedef CommandTemplate<header::ClientReceiveServerCrowdedError> ClientReceiveServerCrowdedError; |
58 | 64 | typedef CommandTemplate<header::ServerRequestedFullServerInfo> ServerRequestedFullServerInfo; |
65 | + typedef CommandTemplate<header::ServerRequestedPlainFullServerInfo> ServerRequestedPlainFullServerInfo; | |
59 | 66 | |
60 | 67 | // コネクションの切断 |
61 | 68 | class FatalConnectionError : public Command { |
@@ -153,4 +160,8 @@ typedef boost::weak_ptr<Session> SessionWeakPtr; | ||
153 | 160 | ClientReceiveFullServerInfo(const std::string& xml); |
154 | 161 | }; |
155 | 162 | |
163 | + class ClientReceivePlainFullServerInfo : public Command { | |
164 | + public: | |
165 | + ClientReceivePlainFullServerInfo(const std::string& xml); | |
166 | + }; | |
156 | 167 | } |
@@ -32,6 +32,10 @@ namespace header { | ||
32 | 32 | ClientReceiveFullServerInfo = 0x17, |
33 | 33 | |
34 | 34 | ServerReceiveWriteLimit = 0x20, |
35 | + | |
36 | + ServerRequestedPlainFullServerInfo = 0x40, | |
37 | + ClientReceivePlainFullServerInfo = 0x41, | |
38 | + | |
35 | 39 | ServerRequstedStatus = 0xE0, |
36 | 40 | |
37 | 41 | LZ4_COMPRESS_HEADER = 0xF0, |
@@ -43,7 +43,7 @@ namespace network { | ||
43 | 43 | |
44 | 44 | void Session::Send(const Command& command) |
45 | 45 | { |
46 | - auto msg = Serialize(command); | |
46 | + auto msg = Serialize(command, command.plain()); | |
47 | 47 | write_byte_sum_ += msg.size(); |
48 | 48 | UpdateWriteByteAverage(); |
49 | 49 |
@@ -54,7 +54,7 @@ namespace network { | ||
54 | 54 | |
55 | 55 | void Session::SyncSend(const Command& command) |
56 | 56 | { |
57 | - auto msg = Serialize(command); | |
57 | + auto msg = Serialize(command, command.plain()); | |
58 | 58 | write_byte_sum_ += msg.size(); |
59 | 59 | UpdateWriteByteAverage(); |
60 | 60 |
@@ -194,7 +194,7 @@ namespace network { | ||
194 | 194 | write_average_limit_ = limit; |
195 | 195 | } |
196 | 196 | |
197 | - std::string Session::Serialize(const Command& command) | |
197 | + std::string Session::Serialize(const Command& command, bool plain) | |
198 | 198 | { |
199 | 199 | assert(command.header() < 0xFF); |
200 | 200 | auto header = static_cast<uint8_t>(command.header()); |
@@ -202,24 +202,29 @@ namespace network { | ||
202 | 202 | |
203 | 203 | std::string msg = Utils::Serialize(header) + body; |
204 | 204 | |
205 | - // 圧縮 | |
206 | - if (body.size() >= COMPRESS_MIN_LENGTH) { | |
207 | - auto compressed = Utils::LZ4Compress(msg); | |
208 | - if (msg.size() > compressed.size() + sizeof(uint8_t)) { | |
209 | - assert(msg.size() < 65535); | |
210 | - msg = Utils::Serialize(static_cast<uint8_t>(header::LZ4_COMPRESS_HEADER), | |
211 | - static_cast<uint16_t>(msg.size())) | |
212 | - + compressed; | |
213 | - } | |
214 | - } | |
215 | - | |
216 | - // 暗号化 | |
217 | - if (encryption_) { | |
218 | - msg = Utils::Serialize(static_cast<uint8_t>(header::ENCRYPT_HEADER)) | |
219 | - + encrypter_.Encrypt(msg); | |
220 | - } | |
205 | + if (plain) { | |
206 | + auto length = Utils::Serialize(static_cast<unsigned int>(msg.size())); | |
207 | + return length + msg; | |
208 | + } else { | |
209 | + // 圧縮 | |
210 | + if (body.size() >= COMPRESS_MIN_LENGTH) { | |
211 | + auto compressed = Utils::LZ4Compress(msg); | |
212 | + if (msg.size() > compressed.size() + sizeof(uint8_t)) { | |
213 | + assert(msg.size() < 65535); | |
214 | + msg = Utils::Serialize(static_cast<uint8_t>(header::LZ4_COMPRESS_HEADER), | |
215 | + static_cast<uint16_t>(msg.size())) | |
216 | + + compressed; | |
217 | + } | |
218 | + } | |
219 | + | |
220 | + // 暗号化 | |
221 | + if (encryption_) { | |
222 | + msg = Utils::Serialize(static_cast<uint8_t>(header::ENCRYPT_HEADER)) | |
223 | + + encrypter_.Encrypt(msg); | |
224 | + } | |
225 | + return Utils::Encode(msg); | |
226 | + } | |
221 | 227 | |
222 | - return Utils::Encode(msg); | |
223 | 228 | } |
224 | 229 | |
225 | 230 | Command Session::Deserialize(const std::string& msg) |
@@ -247,7 +252,7 @@ namespace network { | ||
247 | 252 | |
248 | 253 | std::string body = decoded_msg.substr(sizeof(header)); |
249 | 254 | |
250 | - return Command(static_cast<header::CommandHeader>(header), body, shared_from_this()); | |
255 | + return Command(static_cast<header::CommandHeader>(header), body, shared_from_this()); | |
251 | 256 | } |
252 | 257 | |
253 | 258 | void Session::ReceiveTCP(const boost::system::error_code& error) |
@@ -81,7 +81,7 @@ namespace network { | ||
81 | 81 | void UpdateReadByteAverage(); |
82 | 82 | void UpdateWriteByteAverage(); |
83 | 83 | |
84 | - std::string Serialize(const Command& command); | |
84 | + std::string Serialize(const Command& command, bool plain); | |
85 | 85 | Command Deserialize(const std::string& msg); |
86 | 86 | |
87 | 87 | void ReceiveTCP(const boost::system::error_code& error); |
@@ -9,7 +9,7 @@ | ||
9 | 9 | #include <boost/date_time/posix_time/posix_time.hpp> |
10 | 10 | #include <assert.h> |
11 | 11 | |
12 | -Account::Account(const std::string& logfile) : | |
12 | +Account::Account() : | |
13 | 13 | revision_(0), |
14 | 14 | max_user_id_(0) |
15 | 15 | { |
@@ -15,10 +15,11 @@ | ||
15 | 15 | #include <boost/thread.hpp> |
16 | 16 | |
17 | 17 | typedef uint32_t UserID; |
18 | +#undef GetUserName | |
18 | 19 | |
19 | 20 | class Account { |
20 | 21 | public: |
21 | - Account(const std::string&); | |
22 | + Account(); | |
22 | 23 | ~Account(); |
23 | 24 | |
24 | 25 | void LoadInitializeData(UserID user_id, std::string data); |
@@ -0,0 +1,43 @@ | ||
1 | +// | |
2 | +// Channel.hpp | |
3 | +// | |
4 | + | |
5 | +#include "Channel.hpp" | |
6 | +#include <boost/filesystem.hpp> | |
7 | + | |
8 | +using namespace boost::filesystem; | |
9 | + | |
10 | +Channel::Channel() | |
11 | +{ | |
12 | + Load(); | |
13 | +} | |
14 | + | |
15 | +void Channel::Load() | |
16 | +{ | |
17 | + pt_.clear(); | |
18 | + path p("./channels"); | |
19 | + | |
20 | + if (exists(p) && is_directory(p)) { | |
21 | + for (auto it_dir = directory_iterator(p); it_dir != directory_iterator(); ++it_dir) { | |
22 | + if (is_directory(*it_dir)) { | |
23 | + path json_path = it_dir->path() / "config.json"; | |
24 | + if (exists(json_path)) { | |
25 | + auto channel_str = it_dir->path().leaf().string(); | |
26 | + try { | |
27 | + boost::property_tree::ptree config_pt; | |
28 | + read_json(json_path.string(), config_pt); | |
29 | + pt_.put_child(channel_str, config_pt); | |
30 | + | |
31 | + } catch (const std::exception& e) { | |
32 | + Logger::Error("%d", e.what()); | |
33 | + } | |
34 | + } | |
35 | + } | |
36 | + } | |
37 | + } | |
38 | +} | |
39 | + | |
40 | +const boost::property_tree::ptree& Channel::pt() const | |
41 | +{ | |
42 | + return pt_; | |
43 | +} | |
\ No newline at end of file |
@@ -0,0 +1,19 @@ | ||
1 | +// | |
2 | +// Channel.cpp | |
3 | +// | |
4 | + | |
5 | +#pragma once | |
6 | +#include <boost/property_tree/json_parser.hpp> | |
7 | + | |
8 | +class Channel { | |
9 | + public: | |
10 | + Channel(); | |
11 | + | |
12 | + const boost::property_tree::ptree& pt() const; | |
13 | + | |
14 | + private: | |
15 | + void Load(); | |
16 | + | |
17 | + private: | |
18 | + boost::property_tree::ptree pt_; | |
19 | +}; | |
\ No newline at end of file |
@@ -40,15 +40,19 @@ Config::Config() | ||
40 | 40 | |
41 | 41 | void Config::Load() |
42 | 42 | { |
43 | + | |
43 | 44 | try { |
44 | - read_json(std::ifstream(CONFIG_JSON), pt_); | |
45 | + std::ifstream ifs; | |
46 | + ifs.open(CONFIG_JSON); | |
47 | + read_json(ifs, pt_); | |
45 | 48 | } catch(std::exception& e) { |
46 | 49 | Logger::Error(unicode::ToTString(e.what())); |
47 | 50 | } |
48 | 51 | |
49 | 52 | port_ = pt_.get<uint16_t>("port", 39390); |
50 | - server_name_ = pt_.get<std::string>("server_name", "MMO Server"); | |
51 | - stage_ = pt_.get<std::string>("stage", unicode::sjis2utf8("stage:ケロリン町")); | |
53 | + server_name_ = pt_.get<std::string>("server_name", "MMO Server"); | |
54 | + server_note_ = pt_.get<std::string>("server_note", ""); | |
55 | + stage_ = pt_.get<std::string>("stage", unicode::ToString(_T("stage:ケロリン町"))); | |
52 | 56 | capacity_ = pt_.get<int>("capacity", 20); |
53 | 57 | |
54 | 58 | public_ = pt_.get<bool>("public", false); |
@@ -60,6 +64,11 @@ void Config::Load() | ||
60 | 64 | BOOST_FOREACH(const auto& item, patterns) { |
61 | 65 | blocking_address_patterns_.push_back(item.second.get_value<std::string>()); |
62 | 66 | } |
67 | + | |
68 | + auto lobby_servers = pt_.get_child("lobby_servers", ptree()); | |
69 | + BOOST_FOREACH(const auto& item, lobby_servers) { | |
70 | + lobby_servers_.push_back(item.second.get_value<std::string>()); | |
71 | + } | |
63 | 72 | |
64 | 73 | if (exists(CONFIG_JSON)) { |
65 | 74 | timestamp_ = last_write_time(CONFIG_JSON); |
@@ -89,6 +98,16 @@ const std::string& Config::server_name() const | ||
89 | 98 | return server_name_; |
90 | 99 | } |
91 | 100 | |
101 | +const std::string& Config::server_note() const | |
102 | +{ | |
103 | + return server_note_; | |
104 | +} | |
105 | + | |
106 | +bool Config::is_public() const | |
107 | +{ | |
108 | + return public_; | |
109 | +} | |
110 | + | |
92 | 111 | const std::string& Config::stage() const |
93 | 112 | { |
94 | 113 | return stage_; |
@@ -113,6 +132,11 @@ const std::list<std::string>& Config::blocking_address_patterns() const | ||
113 | 132 | { |
114 | 133 | return blocking_address_patterns_; |
115 | 134 | } |
135 | + | |
136 | +const std::list<std::string>& Config::lobby_servers() const | |
137 | +{ | |
138 | + return lobby_servers_; | |
139 | +} | |
116 | 140 | |
117 | 141 | const boost::property_tree::ptree& Config::pt() const |
118 | 142 | { |
@@ -21,6 +21,7 @@ class Config | ||
21 | 21 | |
22 | 22 | uint16_t port_; |
23 | 23 | std::string server_name_; |
24 | + std::string server_note_; | |
24 | 25 | std::string stage_; |
25 | 26 | int capacity_; |
26 | 27 |
@@ -30,12 +31,17 @@ class Config | ||
30 | 31 | int receive_limit_2_; |
31 | 32 | |
32 | 33 | std::list<std::string> blocking_address_patterns_; |
34 | + std::list<std::string> lobby_servers_; | |
33 | 35 | |
34 | 36 | boost::property_tree::ptree pt_; |
35 | 37 | |
36 | 38 | public: |
37 | 39 | uint16_t port() const; |
38 | 40 | const std::string& server_name() const; |
41 | + const std::string& server_note() const; | |
42 | + | |
43 | + bool is_public() const; | |
44 | + | |
39 | 45 | const std::string& stage() const; |
40 | 46 | int capacity() const; |
41 | 47 |
@@ -43,6 +49,7 @@ class Config | ||
43 | 49 | int receive_limit_2() const; |
44 | 50 | |
45 | 51 | const std::list<std::string>& blocking_address_patterns() const; |
52 | + const std::list<std::string>& lobby_servers() const; | |
46 | 53 | |
47 | 54 | const boost::property_tree::ptree& pt() const; |
48 | 55 |
@@ -15,6 +15,7 @@ OBJS += $(patsubst %.c,%.o,$(wildcard ../common/network/lz4/*.c)) | ||
15 | 15 | |
16 | 16 | all: stdafx.h.gch $(OBJS) |
17 | 17 | $(LD) $(CXXFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LIBDIRS) |
18 | + cp ../client/bin/server/config.json . | |
18 | 19 | |
19 | 20 | clean: |
20 | 21 | @rm -f $(OBJS) $(TARGET) stdafx.h.gch |
@@ -13,12 +13,12 @@ | ||
13 | 13 | |
14 | 14 | namespace network { |
15 | 15 | |
16 | - Server::Server(Config& config) : | |
17 | - config_(config), | |
18 | - endpoint_(tcp::v4(), config.port()), | |
16 | + Server::Server() : | |
17 | + endpoint_(tcp::v4(), config_.port()), | |
19 | 18 | acceptor_(io_service_, endpoint_), |
20 | - socket_udp_(io_service_, udp::endpoint(udp::v4(), config.port())), | |
21 | - udp_packet_count_(0) | |
19 | + socket_udp_(io_service_, udp::endpoint(udp::v4(), config_.port())), | |
20 | + udp_packet_count_(0), | |
21 | + recent_chat_log_(10) | |
22 | 22 | { |
23 | 23 | } |
24 | 24 |
@@ -48,6 +48,12 @@ namespace network { | ||
48 | 48 | |
49 | 49 | }); |
50 | 50 | |
51 | + BOOST_FOREACH(const auto& host, config().lobby_servers()) { | |
52 | + udp::resolver resolver(io_service_); | |
53 | + udp::resolver::query query(udp::v4(), host.c_str(), "39380"); | |
54 | + lobby_hosts_.push_back(resolver.resolve(query)); | |
55 | + } | |
56 | + | |
51 | 57 | { |
52 | 58 | auto new_session = boost::make_shared<ServerSession>(io_service_); |
53 | 59 | acceptor_.async_accept(new_session->tcp_socket(), |
@@ -105,12 +111,52 @@ namespace network { | ||
105 | 111 | ptree xml_ptree; |
106 | 112 | |
107 | 113 | xml_ptree.put_child("config", config_.pt()); |
114 | + xml_ptree.put("version", (boost::format("%d.%d.%d") | |
115 | + % MMO_VERSION_MAJOR % MMO_VERSION_MINOR % MMO_VERSION_REVISION).str()); | |
116 | + xml_ptree.put("protocol_version", MMO_PROTOCOL_VERSION); | |
117 | + | |
118 | + { | |
119 | + ptree player_array; | |
120 | + auto id_list = account_.GetIDList(); | |
121 | + BOOST_FOREACH(unsigned int id, id_list) { | |
122 | + ptree player; | |
123 | + player.put("name", account_.GetUserName(id)); | |
124 | + player.put("model_name", account_.GetUserModelName(id)); | |
125 | + player_array.push_back(std::make_pair("", player)); | |
126 | + } | |
127 | + xml_ptree.put_child("players", player_array); | |
128 | + } | |
129 | + | |
130 | + { | |
131 | + ptree log_array; | |
132 | + BOOST_FOREACH(const std::string& msg, recent_chat_log_) { | |
133 | + log_array.push_back(std::make_pair("", msg)); | |
134 | + } | |
135 | + xml_ptree.put_child("recent_chat_log", log_array); | |
136 | + } | |
108 | 137 | |
138 | + xml_ptree.put_child("channels", channel_.pt()); | |
139 | + | |
109 | 140 | std::stringstream stream; |
110 | 141 | write_xml(stream, xml_ptree); |
111 | 142 | return stream.str(); |
112 | 143 | } |
113 | 144 | |
145 | + const Config& Server::config() const | |
146 | + { | |
147 | + return config_; | |
148 | + } | |
149 | + | |
150 | + Account& Server::account() | |
151 | + { | |
152 | + return account_; | |
153 | + } | |
154 | + | |
155 | + void Server::AddChatLog(const std::string& msg) | |
156 | + { | |
157 | + recent_chat_log_.push_back(msg); | |
158 | + } | |
159 | + | |
114 | 160 | bool Server::Empty() const |
115 | 161 | { |
116 | 162 | return GetUserCount() == 0; |
@@ -171,7 +217,9 @@ namespace network { | ||
171 | 217 | if (auto session = ptr.lock()) { |
172 | 218 | if (channel < 0 || (channel >= 0 && session->channel() == channel)) { |
173 | 219 | if (!limited || session->write_average_limit() > session->GetWriteByteAverage()) { |
174 | - session->Send(command); | |
220 | + if (session->id() > 0) { | |
221 | + session->Send(command); | |
222 | + } | |
175 | 223 | } |
176 | 224 | } |
177 | 225 | } |
@@ -184,7 +232,7 @@ namespace network { | ||
184 | 232 | if (auto session = ptr.lock()) { |
185 | 233 | if (channel < 0 || (channel >= 0 && session->channel() == channel)) { |
186 | 234 | if (!limited || session->write_average_limit() > session->GetWriteByteAverage()) { |
187 | - if (session->id() != self_id) { | |
235 | + if (session->id() > 0 && session->id() != self_id) { | |
188 | 236 | session->Send(command); |
189 | 237 | } |
190 | 238 | } |
@@ -223,6 +271,14 @@ namespace network { | ||
223 | 271 | } |
224 | 272 | } |
225 | 273 | |
274 | + void Server::SendPublicPing() | |
275 | + { | |
276 | + static char request[] = "P"; | |
277 | + BOOST_FOREACH(const auto& iterator, lobby_hosts_) { | |
278 | + io_service_.post(boost::bind(&Server::DoWriteUDP, this, request, *iterator)); | |
279 | + } | |
280 | + } | |
281 | + | |
226 | 282 | void Server::SendUDP(const std::string& message, const boost::asio::ip::udp::endpoint endpoint) |
227 | 283 | { |
228 | 284 | io_service_.post(boost::bind(&Server::DoWriteUDP, this, message, endpoint)); |
@@ -7,8 +7,11 @@ | ||
7 | 7 | #include <string> |
8 | 8 | #include <list> |
9 | 9 | #include <functional> |
10 | +#include <boost/circular_buffer.hpp> | |
10 | 11 | #include "../common/network/Session.hpp" |
11 | 12 | #include "Config.hpp" |
13 | +#include "Account.hpp" | |
14 | +#include "Channel.hpp" | |
12 | 15 | |
13 | 16 | #define UDP_MAX_RECEIVE_LENGTH (2048) |
14 | 17 | #define UDP_TEST_PACKET_TIME (5) |
@@ -26,7 +29,7 @@ class Server { | ||
26 | 29 | }; |
27 | 30 | |
28 | 31 | public: |
29 | - Server(Config& config); | |
32 | + Server(); | |
30 | 33 | void Start(CallbackFuncPtr callback); |
31 | 34 | void Stop(); |
32 | 35 | void Stop(int interrupt_type); |
@@ -39,12 +42,18 @@ class Server { | ||
39 | 42 | std::string GetStatusJSON() const; |
40 | 43 | std::string GetFullStatus() const; |
41 | 44 | |
45 | + const Config& config() const; | |
46 | + Account& account(); | |
47 | + | |
48 | + void AddChatLog(const std::string& msg); | |
49 | + | |
42 | 50 | int GetSessionReadAverageLimit(); |
43 | 51 | int GetUserCount() const; |
44 | 52 | void RefreshSession(); |
45 | 53 | |
46 | 54 | void SendUDPTestPacket(const std::string& ip_address, uint16_t port); |
47 | 55 | void SendUDP(const std::string& message, const boost::asio::ip::udp::endpoint endpoint); |
56 | + void SendPublicPing(); | |
48 | 57 | |
49 | 58 | bool IsBlockedAddress(const boost::asio::ip::address& address); |
50 | 59 |
@@ -58,7 +67,9 @@ class Server { | ||
58 | 67 | void FetchUDP(const std::string& buffer, const boost::asio::ip::udp::endpoint endpoint); |
59 | 68 | |
60 | 69 | private: |
61 | - Config& config_; | |
70 | + Config config_; | |
71 | + Account account_; | |
72 | + Channel channel_; | |
62 | 73 | |
63 | 74 | boost::asio::io_service io_service_; |
64 | 75 | tcp::endpoint endpoint_; |
@@ -75,6 +86,9 @@ class Server { | ||
75 | 86 | boost::mutex mutex_; |
76 | 87 | std::list<SessionWeakPtr> sessions_; |
77 | 88 | |
89 | + boost::circular_buffer<std::string> recent_chat_log_; | |
90 | + std::list<udp::resolver::iterator> lobby_hosts_; | |
91 | + | |
78 | 92 | }; |
79 | 93 | |
80 | 94 | } |
@@ -16,7 +16,6 @@ | ||
16 | 16 | #include "../common/database/AccountProperty.hpp" |
17 | 17 | #include "../common/Logger.hpp" |
18 | 18 | #include "Config.hpp" |
19 | -#include "Account.hpp" | |
20 | 19 | #include "version.hpp" |
21 | 20 | |
22 | 21 | #ifdef __linux__ |
@@ -32,6 +31,7 @@ | ||
32 | 31 | using namespace boost::posix_time; |
33 | 32 | |
34 | 33 | void client_sync(network::Server& server); |
34 | +void public_ping(network::Server& server); | |
35 | 35 | void server(); |
36 | 36 | |
37 | 37 | int main(int argc, char* argv[]) |
@@ -58,18 +58,14 @@ int main(int argc, char* argv[]) | ||
58 | 58 | void server() |
59 | 59 | { |
60 | 60 | |
61 | - // 設定を読み込み | |
62 | - Config config; | |
63 | - | |
64 | 61 | // 署名 |
65 | 62 | network::Signature sign("server_key"); |
66 | 63 | |
67 | 64 | // アカウント |
68 | - Account account("account.db"); | |
69 | - network::Server server(config); | |
65 | + network::Server server; | |
70 | 66 | |
71 | 67 | auto callback = std::make_shared<std::function<void(network::Command)>>( |
72 | - [&server, &account, &sign, &config](network::Command c){ | |
68 | + [&server, &sign](network::Command c){ | |
73 | 69 | |
74 | 70 | // ログを出力 |
75 | 71 | auto msg = (boost::format("Receive: 0x%08x %dbyte") % c.header() % c.body().size()).str(); |
@@ -80,10 +76,9 @@ void server() | ||
80 | 76 | // if (auto session = c.session().lock()) { |
81 | 77 | // std::cout << "Write Average: " << session->GetReadByteAverage() << "bytes" << std::endl; |
82 | 78 | // } |
83 | - | |
79 | + auto header = c.header(); | |
84 | 80 | switch (c.header()) { |
85 | 81 | |
86 | - // フルステータス要求 | |
87 | 82 | case network::header::ServerRequestedFullServerInfo: |
88 | 83 | { |
89 | 84 | if (auto session = c.session().lock()) { |
@@ -92,6 +87,14 @@ void server() | ||
92 | 87 | } |
93 | 88 | break; |
94 | 89 | |
90 | + case network::header::ServerRequestedPlainFullServerInfo: | |
91 | + { | |
92 | + if (auto session = c.session().lock()) { | |
93 | + session->Send(network::ClientReceivePlainFullServerInfo(server.GetFullStatus())); | |
94 | + } | |
95 | + } | |
96 | + break; | |
97 | + | |
95 | 98 | // ステータス要求 |
96 | 99 | case network::header::ServerRequstedStatus: |
97 | 100 | { |
@@ -139,6 +142,10 @@ void server() | ||
139 | 142 | server.SendTo(send_command, user_id); |
140 | 143 | } |
141 | 144 | } else { |
145 | + auto name = server.account().GetUserName(id); | |
146 | + auto body = message_tree.get<std::string>("body", std::string()); | |
147 | + server.AddChatLog((boost::format("[%s] %s") % name % body).str()); | |
148 | + | |
142 | 149 | server.SendAll(send_command, session->channel()); |
143 | 150 | } |
144 | 151 |
@@ -154,7 +161,7 @@ void server() | ||
154 | 161 | if (auto session = c.session().lock()) { |
155 | 162 | PlayerPosition pos; |
156 | 163 | network::Utils::Deserialize(c.body(), &pos.x, &pos.y, &pos.z, &pos.theta, &pos.vy); |
157 | - account.SetUserPosition(session->id(), pos); | |
164 | + server.account().SetUserPosition(session->id(), pos); | |
158 | 165 | server.SendOthers(network::ClientUpdatePlayerPosition(session->id(), |
159 | 166 | pos.x,pos.y,pos.z,pos.theta, pos.vy), session->id(), session->channel(), true); |
160 | 167 | } |
@@ -167,7 +174,7 @@ void server() | ||
167 | 174 | if (auto session = c.session().lock()) { |
168 | 175 | |
169 | 176 | // 最大接続数を超えていないか判定 |
170 | - if (server.GetUserCount() >= config.capacity()) { | |
177 | + if (server.GetUserCount() >= server.config().capacity()) { | |
171 | 178 | Logger::Info("Refused Session"); |
172 | 179 | session->SyncSend(network::ClientReceiveServerCrowdedError()); |
173 | 180 | session->Close(); |
@@ -197,7 +204,7 @@ void server() | ||
197 | 204 | // テスト送信 |
198 | 205 | server.SendUDPTestPacket(session->global_ip(), session->udp_port()); |
199 | 206 | |
200 | - uint32_t id = account.GetUserIdFromFingerPrint(finger_print); | |
207 | + uint32_t id = server.account().GetUserIdFromFingerPrint(finger_print); | |
201 | 208 | if (id == 0) { |
202 | 209 | // 未登録の場合、公開鍵を要求 |
203 | 210 | session->Send(network::ClientRequestedPublicKey()); |
@@ -205,11 +212,11 @@ void server() | ||
205 | 212 | uint32_t user_id = static_cast<uint32_t>(id); |
206 | 213 | // ログイン |
207 | 214 | session->set_id(user_id); |
208 | - account.LogIn(user_id); | |
209 | - session->encrypter().SetPublicKey(account.GetPublicKey(user_id)); | |
215 | + server.account().LogIn(user_id); | |
216 | + session->encrypter().SetPublicKey(server.account().GetPublicKey(user_id)); | |
210 | 217 | |
211 | - account.SetUserIPAddress(session->id(), session->global_ip()); | |
212 | - account.SetUserUDPPort(session->id(), session->udp_port()); | |
218 | + server.account().SetUserIPAddress(session->id(), session->global_ip()); | |
219 | + server.account().SetUserUDPPort(session->id(), session->udp_port()); | |
213 | 220 | |
214 | 221 | // 共通鍵を送り返す |
215 | 222 | auto key = session->encrypter().GetCryptedCommonKey(); |
@@ -225,18 +232,18 @@ void server() | ||
225 | 232 | case network::header::ServerReceivePublicKey: |
226 | 233 | { |
227 | 234 | if (auto session = c.session().lock()) { |
228 | - uint32_t user_id = account.RegisterPublicKey(c.body()); | |
235 | + uint32_t user_id = server.account().RegisterPublicKey(c.body()); | |
229 | 236 | assert(user_id > 0); |
230 | 237 | |
231 | 238 | session->ResetReadByteAverage(); |
232 | 239 | |
233 | 240 | // ログイン |
234 | 241 | session->set_id(user_id); |
235 | - account.LogIn(user_id); | |
236 | - session->encrypter().SetPublicKey(account.GetPublicKey(user_id)); | |
242 | + server.account().LogIn(user_id); | |
243 | + session->encrypter().SetPublicKey(server.account().GetPublicKey(user_id)); | |
237 | 244 | |
238 | - account.SetUserIPAddress(session->id(), session->global_ip()); | |
239 | - account.SetUserUDPPort(session->id(), session->udp_port()); | |
245 | + server.account().SetUserIPAddress(session->id(), session->global_ip()); | |
246 | + server.account().SetUserUDPPort(session->id(), session->udp_port()); | |
240 | 247 | |
241 | 248 | // 共通鍵を送り返す |
242 | 249 | auto key = session->encrypter().GetCryptedCommonKey(); |
@@ -252,7 +259,7 @@ void server() | ||
252 | 259 | { |
253 | 260 | if (auto session = c.session().lock()) { |
254 | 261 | |
255 | - session->Send(network::ClientReceiveServerInfo(config.stage())); | |
262 | + session->Send(network::ClientReceiveServerInfo(server.config().stage())); | |
256 | 263 | |
257 | 264 | session->Send(network::ClientStartEncryptedSession()); |
258 | 265 | session->EnableEncryption(); |
@@ -266,17 +273,17 @@ void server() | ||
266 | 273 | case network::header::ServerReceiveAccountInitializeData: |
267 | 274 | { |
268 | 275 | if (auto session = c.session().lock()) { |
269 | - account.LoadInitializeData(session->id(), c.body()); | |
276 | + server.account().LoadInitializeData(session->id(), c.body()); | |
270 | 277 | |
271 | - const auto& list = account.GetIDList(); | |
278 | + const auto& list = server.account().GetIDList(); | |
272 | 279 | BOOST_FOREACH(UserID user_id, list) { |
273 | 280 | session->Send(network::ClientReceiveAccountRevisionUpdateNotify(user_id, |
274 | - account.GetUserRevision(user_id))); | |
281 | + server.account().GetUserRevision(user_id))); | |
275 | 282 | } |
276 | 283 | |
277 | 284 | server.SendOthers( |
278 | 285 | network::ClientReceiveAccountRevisionUpdateNotify(session->id(), |
279 | - account.GetUserRevision(session->id())), session->id()); | |
286 | + server.account().GetUserRevision(session->id())), session->id()); | |
280 | 287 | |
281 | 288 | Logger::Info(msg); |
282 | 289 | } |
@@ -291,9 +298,9 @@ void server() | ||
291 | 298 | uint32_t client_revision; |
292 | 299 | network::Utils::Deserialize(c.body(), &user_id, &client_revision); |
293 | 300 | |
294 | - if (client_revision < account.GetUserRevision(user_id)) { | |
301 | + if (client_revision < server.account().GetUserRevision(user_id)) { | |
295 | 302 | session->Send(network::ClientReceiveAccountRevisionPatch( |
296 | - account.GetUserRevisionPatch(user_id, client_revision))); | |
303 | + server.account().GetUserRevisionPatch(user_id, client_revision))); | |
297 | 304 | } |
298 | 305 | Logger::Info(msg); |
299 | 306 | } |
@@ -307,7 +314,7 @@ void server() | ||
307 | 314 | std::string buffer = c.body().substr(sizeof(AccountProperty)); |
308 | 315 | network::Utils::Deserialize(c.body(), &property); |
309 | 316 | |
310 | - auto old_revision = account.GetUserRevision(session->id()); | |
317 | + auto old_revision = server.account().GetUserRevision(session->id()); | |
311 | 318 | |
312 | 319 | switch (property) { |
313 | 320 |
@@ -315,36 +322,37 @@ void server() | ||
315 | 322 | { |
316 | 323 | std::string value; |
317 | 324 | network::Utils::Deserialize(buffer, &value); |
318 | - account.SetUserName(session->id(), value); | |
325 | + server.account().SetUserName(session->id(), value); | |
319 | 326 | } |
320 | 327 | break; |
321 | 328 | case TRIP: |
322 | 329 | { |
323 | 330 | std::string value; |
324 | 331 | network::Utils::Deserialize(buffer, &value); |
325 | - account.SetUserTrip(session->id(), value); | |
332 | + server.account().SetUserTrip(session->id(), value); | |
326 | 333 | } |
327 | 334 | break; |
328 | 335 | case MODEL_NAME: |
329 | 336 | { |
330 | 337 | std::string value; |
331 | 338 | network::Utils::Deserialize(buffer, &value); |
332 | - account.SetUserModelName(session->id(), value); | |
339 | + server.account().SetUserModelName(session->id(), value); | |
340 | + } | |
341 | + break; | |
342 | + case CHANNEL: | |
343 | + { | |
344 | + std::string value; | |
345 | + network::Utils::Deserialize(buffer, &value); | |
346 | + auto channel = *reinterpret_cast<const unsigned int*>(value.data()); | |
347 | + server.account().SetUserChannel(session->id(), channel); | |
348 | + session->set_channel(channel); | |
333 | 349 | } |
334 | 350 | break; |
335 | - // case CHANNEL: | |
336 | - // { | |
337 | - //unsigned char value; | |
338 | - //network::Utils::Deserialize(buffer, &value); | |
339 | - // account.SetUserChannel(session->id(), value); | |
340 | - //session->set_channel(value); | |
341 | - // } | |
342 | - // break; | |
343 | 351 | default: |
344 | 352 | ; |
345 | 353 | } |
346 | 354 | |
347 | - auto new_revison = account.GetUserRevision(session->id()); | |
355 | + auto new_revison = server.account().GetUserRevision(session->id()); | |
348 | 356 | if (new_revison > old_revision) { |
349 | 357 | server.SendAll( |
350 | 358 | network::ClientReceiveAccountRevisionUpdateNotify( |
@@ -362,14 +370,14 @@ void server() | ||
362 | 370 | if (c.body().size() > 0) { |
363 | 371 | int user_id; |
364 | 372 | network::Utils::Deserialize(c.body(), &user_id); |
365 | - account.LogOut(user_id); | |
373 | + server.account().LogOut(user_id); | |
366 | 374 | |
367 | 375 | server.SendAll( |
368 | 376 | network::ClientReceiveAccountRevisionUpdateNotify(user_id, |
369 | - account.GetUserRevision(user_id))); | |
377 | + server.account().GetUserRevision(user_id))); | |
370 | 378 | |
371 | 379 | Logger::Info("Logout User: %d", user_id); |
372 | - account.Remove(user_id); | |
380 | + server.account().Remove(user_id); | |
373 | 381 | } |
374 | 382 | } |
375 | 383 | Logger::Info(msg); |
@@ -382,9 +390,24 @@ void server() | ||
382 | 390 | }); |
383 | 391 | |
384 | 392 | client_sync(server); |
393 | + | |
394 | + if (server.config().is_public()) { | |
395 | + public_ping(server); | |
396 | + } | |
397 | + | |
385 | 398 | server.Start(callback); |
386 | 399 | } |
387 | 400 | |
401 | +void public_ping(network::Server& server) | |
402 | +{ | |
403 | + boost::thread([&server](){ | |
404 | + while (1) { | |
405 | + boost::this_thread::sleep(boost::posix_time::seconds(10)); | |
406 | + server.SendPublicPing(); | |
407 | + } | |
408 | + }); | |
409 | +} | |
410 | + | |
388 | 411 | void client_sync(network::Server& server) |
389 | 412 | { |
390 | 413 | bool execute_with_client; |
@@ -404,7 +427,7 @@ void client_sync(network::Server& server) | ||
404 | 427 | if (execute_with_client) { |
405 | 428 | boost::thread([&server](){ |
406 | 429 | while (1) { |
407 | - boost::this_thread::sleep(boost::posix_time::milliseconds(4000)); | |
430 | + boost::this_thread::sleep(boost::posix_time::seconds(4)); | |
408 | 431 | try { |
409 | 432 | using namespace boost::interprocess; |
410 | 433 | windows_shared_memory shm(open_only, "MMO_SERVER_WITH_CLIENT", read_only); |
@@ -54,5 +54,7 @@ | ||
54 | 54 | #include <boost/format.hpp> |
55 | 55 | #include <boost/thread.hpp> |
56 | 56 | #include <boost/foreach.hpp> |
57 | +#include <boost/circular_buffer.hpp> | |
58 | +#include <boost/lexical_cast.hpp> | |
57 | 59 | |
58 | 60 | #include "../common/Logger.hpp" |
\ No newline at end of file |