servers: implement consistent error handling policy for coro_* functions
- coro_ read function returns empty unique_ptr on error - coro_ write functions close socket on error - caller does need only to handle empty unique_ptr from reads, generally with immediate return
This commit is contained in:
parent
f308614328
commit
d0d9dfaf04
4 changed files with 27 additions and 31 deletions
|
@ -1153,11 +1153,9 @@ void server::handle_request_campaign(const server::request& req)
|
|||
|
||||
LOG_CS << req << "Sending add-on '" << name << "' version: " << from << " -> " << to << " (delta)\n";
|
||||
|
||||
if(utils::visit([this, &req, &doc](auto && sock) {
|
||||
boost::system::error_code ec;
|
||||
coro_send_doc(sock, doc, req.yield[ec]);
|
||||
return check_error(ec, sock);
|
||||
}, req.sock)) return;
|
||||
utils::visit([this, &req, &doc](auto && sock) {
|
||||
coro_send_doc(sock, doc, req.yield);
|
||||
}, req.sock);
|
||||
|
||||
full_pack_path.clear();
|
||||
}
|
||||
|
@ -1173,11 +1171,9 @@ void server::handle_request_campaign(const server::request& req)
|
|||
}
|
||||
|
||||
LOG_CS << req << "Sending add-on '" << name << "' version: " << to << " size: " << full_pack_size / 1024 << " KiB\n";
|
||||
if(utils::visit([this, &req, &full_pack_path](auto&& socket) {
|
||||
boost::system::error_code ec;
|
||||
coro_send_file(socket, full_pack_path, req.yield[ec]);
|
||||
return check_error(ec, socket);
|
||||
}, req.sock)) return;
|
||||
utils::visit([this, &req, &full_pack_path](auto&& socket) {
|
||||
coro_send_file(socket, full_pack_path, req.yield);
|
||||
}, req.sock);
|
||||
}
|
||||
|
||||
// Clients doing upgrades or some other specific thing shouldn't bump
|
||||
|
@ -1229,11 +1225,9 @@ void server::handle_request_campaign_hash(const server::request& req)
|
|||
}
|
||||
|
||||
LOG_CS << req << "Sending add-on hash index for '" << req.cfg["name"] << "' size: " << file_size / 1024 << " KiB\n";
|
||||
if(utils::visit([this, &path, &req](auto&& socket) {
|
||||
boost::system::error_code ec;
|
||||
coro_send_file(socket, path, req.yield[ec]);
|
||||
return check_error(ec, socket);
|
||||
}, req.sock)) return;
|
||||
utils::visit([this, &path, &req](auto&& socket) {
|
||||
coro_send_file(socket, path, req.yield);
|
||||
}, req.sock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -347,7 +347,10 @@ template<class SocketPtr> void coro_send_file_userspace(SocketPtr socket, const
|
|||
|
||||
boost::system::error_code ec;
|
||||
async_write(*socket, boost::asio::buffer(data_size.buf), yield[ec]);
|
||||
if(check_error(ec, socket)) return;
|
||||
if(check_error(ec, socket)) {
|
||||
socket->lowest_layer().close();
|
||||
return;
|
||||
}
|
||||
|
||||
auto ifs { filesystem::istream_file(filename) };
|
||||
ifs->seekg(0);
|
||||
|
@ -355,7 +358,10 @@ template<class SocketPtr> void coro_send_file_userspace(SocketPtr socket, const
|
|||
char buf[16384];
|
||||
ifs->read(buf, sizeof(buf));
|
||||
async_write(*socket, boost::asio::buffer(buf, ifs->gcount()), yield[ec]);
|
||||
if(check_error(ec, socket)) return;
|
||||
if(check_error(ec, socket)) {
|
||||
socket->lowest_layer().close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ public:
|
|||
* Receive WML document from a coroutine
|
||||
* @param socket
|
||||
* @param yield The function will suspend on read operation using this yield context
|
||||
* @return unique_ptr with doc deceived. In case of error empty unique_ptr
|
||||
*/
|
||||
template<class SocketPtr> std::unique_ptr<simple_wml::document> coro_receive_doc(SocketPtr socket, boost::asio::yield_context yield);
|
||||
|
||||
|
|
|
@ -683,13 +683,10 @@ void server::handle_new_client(tls_socket_ptr socket)
|
|||
template<class SocketPtr>
|
||||
void server::login_client(boost::asio::yield_context yield, SocketPtr socket)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
coro_send_doc(socket, version_query_response_, yield);
|
||||
|
||||
coro_send_doc(socket, version_query_response_, yield[ec]);
|
||||
if(check_error(ec, socket)) return;
|
||||
|
||||
auto doc { coro_receive_doc(socket, yield[ec]) };
|
||||
if(check_error(ec, socket) || !doc) return;
|
||||
auto doc { coro_receive_doc(socket, yield) };
|
||||
if(!doc) return;
|
||||
|
||||
std::string client_version, client_source;
|
||||
if(const simple_wml::node* const version = doc->child("version")) {
|
||||
|
@ -706,8 +703,7 @@ void server::login_client(boost::asio::yield_context yield, SocketPtr socket)
|
|||
if(accepted_it != accepted_versions_.end()) {
|
||||
LOG_SERVER << log_address(socket) << "\tplayer joined using accepted version " << client_version
|
||||
<< ":\ttelling them to log in.\n";
|
||||
coro_send_doc(socket, login_response_, yield[ec]);
|
||||
if(check_error(ec, socket)) return;
|
||||
coro_send_doc(socket, login_response_, yield);
|
||||
} else {
|
||||
simple_wml::document response;
|
||||
|
||||
|
@ -748,8 +744,8 @@ void server::login_client(boost::asio::yield_context yield, SocketPtr socket)
|
|||
bool registered, is_moderator;
|
||||
|
||||
while(true) {
|
||||
auto login_response { coro_receive_doc(socket, yield[ec]) };
|
||||
if(check_error(ec, socket) || !login_response) return;
|
||||
auto login_response { coro_receive_doc(socket, yield) };
|
||||
if(!login_response) return;
|
||||
|
||||
if(const simple_wml::node* const login = login_response->child("login")) {
|
||||
username = (*login)["username"].to_string();
|
||||
|
@ -765,8 +761,7 @@ void server::login_client(boost::asio::yield_context yield, SocketPtr socket)
|
|||
simple_wml::document join_lobby_response;
|
||||
join_lobby_response.root().add_child("join_lobby").set_attr("is_moderator", is_moderator ? "yes" : "no");
|
||||
join_lobby_response.root().child("join_lobby")->set_attr_dup("profile_url_prefix", "https://r.wesnoth.org/u");
|
||||
coro_send_doc(socket, join_lobby_response, yield[ec]);
|
||||
if(check_error(ec, socket)) return;
|
||||
coro_send_doc(socket, join_lobby_response, yield);
|
||||
|
||||
simple_wml::node& player_cfg = games_and_users_list_.root().add_child("user");
|
||||
wesnothd::player new_player(
|
||||
|
@ -1100,8 +1095,8 @@ template<class SocketPtr> void server::handle_player(boost::asio::yield_context
|
|||
|
||||
while(true) {
|
||||
boost::system::error_code ec;
|
||||
auto doc { coro_receive_doc(socket, yield[ec]) };
|
||||
if(check_error(ec, socket) || !doc) return;
|
||||
auto doc { coro_receive_doc(socket, yield) };
|
||||
if(!doc) return;
|
||||
|
||||
// DBG_SERVER << client_address(socket) << "\tWML received:\n" << doc->output() << std::endl;
|
||||
if(doc->child("refresh_lobby")) {
|
||||
|
|
Loading…
Add table
Reference in a new issue