Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start throwing exceptions for disconnect #218

Merged
merged 5 commits into from Aug 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/common/System.cpp
Expand Up @@ -166,7 +166,7 @@ void Drop(Str::StringRef message)
errorCount = 0;
lastError = now;

throw DropErr(message.c_str());
throw DropErr(true, message);
}

#ifdef _WIN32
Expand Down
17 changes: 12 additions & 5 deletions src/common/System.h
Expand Up @@ -74,12 +74,19 @@ int Milliseconds();
NORETURN void Error(Str::StringRef errorMessage);

// Throw a DropErr with the given message, which normally will drop to the main menu
class DropErr: public std::runtime_error {
class DropErr {
public:
DropErr(const char* message)
: std::runtime_error(message) {}
DropErr(const std::string& message)
: std::runtime_error(message) {}
DropErr(bool error, std::string message)
: error(error), message(std::move(message)) {}
const std::string& what() const {
return message;
}
bool is_error() const {
return error;
}
private:
bool error;
std::string message;
};
NORETURN void Drop(Str::StringRef errorMessage);

Expand Down
6 changes: 3 additions & 3 deletions src/engine/client/ClientApplication.cpp
Expand Up @@ -84,10 +84,10 @@ class ClientApplication : public Application {
Com_Frame();
}

void OnDrop(Str::StringRef reason) override {
void OnDrop(bool error, Str::StringRef reason) override {
FS::PakPath::ClearPaks();
FS_LoadBasePak();
SV_Shutdown(Str::Format("Server crashed: %s\n", reason).c_str());
SV_Shutdown(Str::Format("Server %s: %s", error ? "crashed" : "shutdown", reason).c_str());
CL_Disconnect(true);
CL_ShutdownAll();
CL_StartHunkUsers();
Expand All @@ -102,7 +102,7 @@ class ClientApplication : public Application {

TRY_SHUTDOWN(CL_Shutdown());
TRY_SHUTDOWN(
SV_Shutdown(error ? Str::Format("Server fatal crashed: %s\n", message).c_str() : Str::Format("%s\n", message).c_str())
SV_Shutdown(error ? Str::Format("Server fatal crashed: %s", message).c_str() : message.c_str())
);
TRY_SHUTDOWN(Com_Shutdown());

Expand Down
38 changes: 19 additions & 19 deletions src/engine/client/cl_main.cpp
Expand Up @@ -508,7 +508,7 @@ CL_DemoCompleted
=================
*/

void CL_DemoCompleted()
NORETURN static void CL_DemoCompleted()
{
if ( cvar_demo_timedemo.Get() )
{
Expand All @@ -523,7 +523,7 @@ void CL_DemoCompleted()
}
}

CL_Disconnect( true );
throw Sys::DropErr(false, "Demo completed");
}

/*
Expand All @@ -542,7 +542,6 @@ void CL_ReadDemoMessage()
if ( !clc.demofile )
{
CL_DemoCompleted();
return;
}

// get the sequence number
Expand All @@ -551,7 +550,6 @@ void CL_ReadDemoMessage()
if ( r != 4 )
{
CL_DemoCompleted();
return;
}

clc.serverMessageSequence = LittleLong( s );
Expand All @@ -565,15 +563,13 @@ void CL_ReadDemoMessage()
if ( r != 4 )
{
CL_DemoCompleted();
return;
}

buf.cursize = LittleLong( buf.cursize );

if ( buf.cursize == -1 )
{
CL_DemoCompleted();
return;
}

if ( buf.cursize > buf.maxsize )
Expand All @@ -587,7 +583,6 @@ void CL_ReadDemoMessage()
{
Log::Notice("Demo file was truncated.");
CL_DemoCompleted();
return;
}

clc.lastPacketTime = cls.realtime;
Expand Down Expand Up @@ -772,7 +767,11 @@ void CL_MapLoading()
}
else
{
CL_Disconnect( false );
try {
CL_Disconnect( false );
} catch (Sys::DropErr& err) {
Sys::Error( "CL_Disconnect error during map load: %s", err.what() );
}
Q_strncpyz( cls.servername, "loopback", sizeof( cls.servername ) );
*cls.reconnectCmd = 0; // can't reconnect to this!
cls.state = connstate_t::CA_CHALLENGING; // so the connect screen is drawn
Expand Down Expand Up @@ -957,7 +956,7 @@ CL_Disconnect_f
*/
void CL_Disconnect_f()
{
CL_Disconnect( false );
throw Sys::DropErr(false, "Disconnecting.");
}

/*
Expand Down Expand Up @@ -1057,14 +1056,18 @@ void CL_Connect_f()
if ( com_sv_running->integer && !strcmp( server, "loopback" ) )
{
// if running a local server, kill it
SV_Shutdown( "Server quit\n" );
SV_Shutdown( "Server quit" );
}

// make sure a local server is killed
Cvar_Set( "sv_killserver", "1" );
SV_Frame( 0 );

CL_Disconnect( true );
try {
CL_Disconnect( true );
} catch (Sys::DropErr& err) {
Sys::Error( "CL_Disconnect error during /connect: %s", err.what() );
}
Con_Close();

if ( !NET_StringToAdr( cls.servername, &clc.serverAddress, family ) )
Expand Down Expand Up @@ -1727,8 +1730,6 @@ to the client so it doesn't have to wait for the full timeout period.
*/
void CL_DisconnectPacket( netadr_t from )
{
const char *message;

if ( cls.state < connstate_t::CA_CONNECTING )
{
return;
Expand All @@ -1752,10 +1753,9 @@ void CL_DisconnectPacket( netadr_t from )
}

// drop the connection
message = "Server disconnected for unknown reason";
Log::Notice( "%s", message );
const char* message = "Server disconnected for unknown reason";
Cvar_Set( "com_errorMessage", message );
CL_Disconnect( true );
Sys::Drop( message );
}

/*
Expand Down Expand Up @@ -2454,9 +2454,9 @@ void CL_CheckTimeout()
if ( ++cl.timeoutcount > 5 )
{
// timeoutcount saves debugger
Cvar_Set( "com_errorMessage", "Server connection timed out." );
CL_Disconnect( true );
return;
const char* message = "Server connection timed out.";
Cvar_Set( "com_errorMessage", message );
Sys::Drop( message );
}
}
else
Expand Down
6 changes: 3 additions & 3 deletions src/engine/framework/Application.cpp
Expand Up @@ -47,7 +47,7 @@ namespace Application {
void Application::Initialize(Str::StringRef) {
}

void Application::OnDrop(Str::StringRef) {
void Application::OnDrop(bool, Str::StringRef) {
}

void Application::Shutdown(bool, Str::StringRef) {
Expand All @@ -73,8 +73,8 @@ namespace Application {
GetApp().Frame();
}

void OnDrop(Str::StringRef reason) {
GetApp().OnDrop(reason);
void OnDrop(bool error, Str::StringRef reason) {
GetApp().OnDrop(error, reason);
}

void Shutdown(bool error, Str::StringRef message) {
Expand Down
4 changes: 2 additions & 2 deletions src/engine/framework/Application.h
Expand Up @@ -59,7 +59,7 @@ class Application {
virtual void Initialize(Str::StringRef uri);
virtual void Frame() {}

virtual void OnDrop(Str::StringRef reason);
virtual void OnDrop(bool error, Str::StringRef reason);
virtual void Shutdown(bool error, Str::StringRef message);

virtual void OnUnhandledCommand(const Cmd::Args& args);
Expand All @@ -74,7 +74,7 @@ void LoadInitialConfig(bool resetConfig);
void Initialize(Str::StringRef uri);
void Frame();

void OnDrop(Str::StringRef reason);
void OnDrop(bool error, Str::StringRef reason);
void Shutdown(bool error, Str::StringRef message);

void OnUnhandledCommand(const Cmd::Args& args);
Expand Down
10 changes: 7 additions & 3 deletions src/engine/framework/System.cpp
Expand Up @@ -685,10 +685,14 @@ ALIGN_STACK_FOR_MINGW int main(int argc, char** argv)
try {
while (true) {
try {
Application::Frame();
Application::Frame();
} catch (Sys::DropErr& err) {
Log::Warn(err.what());
Application::OnDrop(err.what());
if (err.is_error()) {
Log::Warn(err.what());
} else {
Log::Notice(err.what());
}
Application::OnDrop(err.is_error(), err.what());
}
}
} catch (Sys::DropErr& err) {
Expand Down
6 changes: 3 additions & 3 deletions src/engine/server/ServerApplication.cpp
Expand Up @@ -63,15 +63,15 @@ class ServerApplication : public Application {
Com_Frame();
}

void OnDrop(Str::StringRef reason) override {
void OnDrop(bool error, Str::StringRef reason) override {
FS::PakPath::ClearPaks();
FS_LoadBasePak();
SV_Shutdown(Str::Format("Server crashed: %s\n", reason).c_str());
SV_Shutdown(Str::Format("Server %s: %s", error ? "crashed" : "shutdown", reason).c_str());
}

void Shutdown(bool error, Str::StringRef message) override {
TRY_SHUTDOWN(
SV_Shutdown(error ? Str::Format("Server fatal crashed: %s\n", message).c_str() : Str::Format("%s\n", message).c_str())
SV_Shutdown(error ? Str::Format("Server fatal crashed: %s", message).c_str() : message.c_str())
);
TRY_SHUTDOWN(Com_Shutdown());
}
Expand Down
30 changes: 15 additions & 15 deletions src/engine/server/sv_sgame.cpp
Expand Up @@ -51,30 +51,22 @@ Maryland 20850 USA.

sharedEntity_t *SV_GentityNum( int num )
{
sharedEntity_t *ent;

if ( num < 0 || num >= MAX_GENTITIES )
if ( num < 0 || num >= MAX_GENTITIES || sv.gentities == nullptr )
{
Sys::Drop( "SV_GentityNum: bad num %d", num );
}

ent = ( sharedEntity_t * )( ( byte * ) sv.gentities + sv.gentitySize * ( num ) );

return ent;
return ( sharedEntity_t * )( ( byte * ) sv.gentities + sv.gentitySize * ( num ) );
}

playerState_t *SV_GameClientNum( int num )
{
playerState_t *ps;

if ( num >= sv_maxclients->integer )
if ( num < 0 || num >= sv_maxclients->integer || sv.gameClients == nullptr )
{
Sys::Drop( "SV_GameClientNum: bad num" );
}

ps = ( playerState_t * )( ( byte * ) sv.gameClients + sv.gameClientSize * ( num ) );

return ps;
return ( playerState_t * )( ( byte * ) sv.gameClients + sv.gameClientSize * ( num ) );
}

svEntity_t *SV_SvEntityForGentity( sharedEntity_t *gEnt )
Expand Down Expand Up @@ -191,20 +183,27 @@ SV_LocateGameData
void SV_LocateGameData( const IPC::SharedMemory& shmRegion, int numGEntities, int sizeofGEntity_t,
int sizeofGameClient )
{
if ( numGEntities < 0 || sizeofGEntity_t < 0 || sizeofGameClient < 0 )
if ( numGEntities < 0 || numGEntities > MAX_GENTITIES || sizeofGEntity_t < 0 || sizeofGameClient < 0
|| sizeofGEntity_t % alignof(sharedEntity_t) || sizeofGEntity_t % alignof(playerState_t) )
Sys::Drop( "SV_LocateGameData: Invalid game data parameters" );
if ( (int) shmRegion.GetSize() < numGEntities * sizeofGEntity_t + sv_maxclients->integer * sizeofGameClient )
if ( int64_t(shmRegion.GetSize()) < int64_t(MAX_GENTITIES) * sizeofGEntity_t + int64_t(sv_maxclients->integer) * sizeofGameClient )
Sys::Drop( "SV_LocateGameData: Shared memory region too small" );

char* base = static_cast<char*>(shmRegion.GetBase());
sv.gentities = reinterpret_cast<sharedEntity_t*>(base);
sv.gentitySize = sizeofGEntity_t;
sv.num_entities = numGEntities;

sv.gameClients = reinterpret_cast<playerState_t*>(base + MAX_GENTITIES * sizeofGEntity_t);
sv.gameClients = reinterpret_cast<playerState_t*>(base + MAX_GENTITIES * size_t(sizeofGEntity_t));
sv.gameClientSize = sizeofGameClient;
}

static void UnlocateGameData()
{
sv.gentities = nullptr;
sv.gameClients = nullptr;
}

/*
===============
SV_GetUsercmd
Expand Down Expand Up @@ -376,6 +375,7 @@ void GameVM::GameShutdown(bool restart)

// Release the shared memory region
this->shmRegion.Close();
UnlocateGameData();
}

bool GameVM::GameClientConnect(char* reason, size_t size, int clientNum, bool firstTime, bool isBot)
Expand Down