wesnoth/src/wesnothd_connection_error.hpp
P. J. McDermott 78d3b0c05c Store jailbreak exceptions in constructors, not in LUAI_TRY()
LUAI_TRY() is an internal part of Lua that may not exist forever, and
reliance on overriding it prevents the use of system copies of Lua.

Document in lua_jailbreak_exception this requirement to call
this->store() in derived class constructors.

Also, count the luaW_pcall_internal() recursion depth and store and
rethrow jailbreak exceptions until the recursion depth reaches 0,
because:

 1. luaW_pcall_internal() sometimes runs recursively (C++ calls Lua
    calls C++ calls Lua calls C++), so the middle C++ layer needs to
    rethrow exceptions instead of clearing them.  LUAI_TRY() previously
    stored them each time, but now lua_jailbreak_exception::rethrow()
    needs to know when not to clear().

 2. Jailbreak exceptions can be thrown while no Lua code is running.
    Now that constructors store() all exceptions instead of LUAI_TRY()
    storing only those caught by Lua, lua_jailbreak_exception::store()
    needs to know when not to store them.  Otherwise, for example,
    leaving a game to return to the menu while no Lua code is running
    throws and needlessly stores an exception that isn't cleared, with
    two possible effects:

     a. If another jailbreak exception is thrown and the constructor
        tries to store it, we abort from assert() because one is already
        stored.

     b. Otherwise, if luaW_pcall_internal() runs without a new jailbreak
        exception being thrown, the stored one is rethrown and handled a
        second time (e.g. immediately leaving a new game).
2024-02-11 23:21:15 -06:00

89 lines
2.4 KiB
C++

/*
Copyright (C) 2011 - 2024
by Sergey Popov <loonycyborg@gmail.com>
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
#include "exceptions.hpp"
#include "lua_jailbreak_exception.hpp"
#include <boost/system/error_code.hpp>
/** An error occurred during when trying to communicate with the wesnothd server. */
struct wesnothd_error : public game::error
{
wesnothd_error(const std::string& error)
: game::error(error)
{
}
};
/**
* Error used when the client is rejected by the MP server.
* Technically, this is not an error but the only way to handle the condition is as if it were an error.
*/
struct wesnothd_rejected_client_error : public game::error
{
wesnothd_rejected_client_error(const std::string& msg)
: game::error(msg)
{
}
};
/**
* We received invalid data from wesnothd during a game
* This means we cannot continue with the game but we can stay connected to wesnothd and start a new game.
* TODO: find a short name
*/
struct ingame_wesnothd_error final : public wesnothd_error, public lua_jailbreak_exception
{
ingame_wesnothd_error(const std::string& error)
: wesnothd_error(error)
{
this->store();
}
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(ingame_wesnothd_error)
};
struct leavegame_wesnothd_error final : public wesnothd_error, public lua_jailbreak_exception
{
leavegame_wesnothd_error(const std::string& error)
: wesnothd_error(error)
{
this->store();
}
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(leavegame_wesnothd_error)
};
/**
* An error occurred inside the underlying network communication code (boost asio)
* TODO: find a short name
*/
struct wesnothd_connection_error final : public wesnothd_error, public lua_jailbreak_exception
{
wesnothd_connection_error(const boost::system::error_code& error, const std::string& msg = "")
: wesnothd_error(error.message())
, user_message(msg)
{
this->store();
}
/** User-friendly and potentially translated message for use in the UI. */
std::string user_message;
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(wesnothd_connection_error)
};