Refactor to use single internal functions for register, unregister and query

This commit is contained in:
Marc Di Luzio 2019-02-10 11:48:41 +00:00
parent d4fdd9e3b4
commit 1d40c0cc1b
3 changed files with 92 additions and 153 deletions

View File

@ -75,9 +75,9 @@ static int method_register_game(sd_bus_message *m, void *userdata,
return ret; return ret;
} }
game_mode_context_register(context, (pid_t)pid); int status = game_mode_context_register(context, (pid_t)pid, (pid_t)pid);
return sd_bus_reply_method_return(m, "i", 0); return sd_bus_reply_method_return(m, "i", status);
} }
/** /**
@ -95,9 +95,9 @@ static int method_unregister_game(sd_bus_message *m, void *userdata,
return ret; return ret;
} }
game_mode_context_unregister(context, (pid_t)pid); int status = game_mode_context_unregister(context, (pid_t)pid, (pid_t)pid);
return sd_bus_reply_method_return(m, "i", 0); return sd_bus_reply_method_return(m, "i", status);
} }
/** /**
@ -115,7 +115,7 @@ static int method_query_status(sd_bus_message *m, void *userdata,
return ret; return ret;
} }
int status = game_mode_context_query_status(context, (pid_t)pid); int status = game_mode_context_query_status(context, (pid_t)pid, (pid_t)pid);
return sd_bus_reply_method_return(m, "i", status); return sd_bus_reply_method_return(m, "i", status);
} }
@ -136,7 +136,7 @@ static int method_register_game_by_pid(sd_bus_message *m, void *userdata,
return ret; return ret;
} }
int reply = game_mode_context_register_by_pid(context, (pid_t)callerpid, (pid_t)gamepid); int reply = game_mode_context_register(context, (pid_t)gamepid, (pid_t)callerpid);
return sd_bus_reply_method_return(m, "i", reply); return sd_bus_reply_method_return(m, "i", reply);
} }
@ -157,7 +157,7 @@ static int method_unregister_game_by_pid(sd_bus_message *m, void *userdata,
return ret; return ret;
} }
int reply = game_mode_context_unregister_by_pid(context, (pid_t)callerpid, (pid_t)gamepid); int reply = game_mode_context_unregister(context, (pid_t)gamepid, (pid_t)callerpid);
return sd_bus_reply_method_return(m, "i", reply); return sd_bus_reply_method_return(m, "i", reply);
} }
@ -178,7 +178,7 @@ static int method_query_status_by_pid(sd_bus_message *m, void *userdata,
return ret; return ret;
} }
int status = game_mode_context_query_status_by_pid(context, (pid_t)callerpid, (pid_t)gamepid); int status = game_mode_context_query_status(context, (pid_t)gamepid, (pid_t)callerpid);
return sd_bus_reply_method_return(m, "i", status); return sd_bus_reply_method_return(m, "i", status);
} }

View File

@ -291,7 +291,7 @@ static void game_mode_context_auto_expire(GameModeContext *self)
if (kill(client->pid, 0) != 0) { if (kill(client->pid, 0) != 0) {
LOG_MSG("Removing expired game [%i]...\n", client->pid); LOG_MSG("Removing expired game [%i]...\n", client->pid);
pthread_rwlock_unlock(&self->rwlock); pthread_rwlock_unlock(&self->rwlock);
game_mode_context_unregister(self, client->pid); game_mode_context_unregister(self, client->pid, client->pid);
removing = true; removing = true;
break; break;
} }
@ -335,20 +335,40 @@ static int game_mode_context_num_clients(GameModeContext *self)
return atomic_load(&self->refcount); return atomic_load(&self->refcount);
} }
bool game_mode_context_register(GameModeContext *self, pid_t client) int game_mode_context_register(GameModeContext *self, pid_t client, pid_t requester)
{ {
errno = 0;
/* Construct a new client if we can */ /* Construct a new client if we can */
GameModeClient *cl = NULL; GameModeClient *cl = NULL;
char *executable = NULL; char *executable = NULL;
/* Check our requester config first */
if (requester != client) {
/* Lookup the executable first */
executable = game_mode_context_find_exe(requester);
if (!executable) {
return -1;
}
/* Check our blacklist and whitelist */
if (!config_get_supervisor_whitelisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable);
free(executable);
return -2;
} else if (config_get_supervisor_blacklisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable);
free(executable);
return -2;
}
}
/* Cap the total number of active clients */ /* Cap the total number of active clients */
if (game_mode_context_num_clients(self) + 1 > MAX_GAMES) { if (game_mode_context_num_clients(self) + 1 > MAX_GAMES) {
LOG_ERROR("Max games (%d) reached, not registering %d\n", MAX_GAMES, client); LOG_ERROR("Max games (%d) reached, not registering %d\n", MAX_GAMES, client);
return false; goto error_cleanup;
} }
errno = 0;
/* Check the PID first to spare a potentially expensive lookup for the exe */ /* Check the PID first to spare a potentially expensive lookup for the exe */
pthread_rwlock_rdlock(&self->rwlock); // ensure our pointer is sane pthread_rwlock_rdlock(&self->rwlock); // ensure our pointer is sane
const GameModeClient *existing = game_mode_context_has_client(self, client); const GameModeClient *existing = game_mode_context_has_client(self, client);
@ -414,15 +434,37 @@ error_cleanup:
LOG_ERROR("Failed to register client [%d]: %s\n", client, strerror(errno)); LOG_ERROR("Failed to register client [%d]: %s\n", client, strerror(errno));
free(executable); free(executable);
game_mode_client_free(cl); game_mode_client_free(cl);
return false; return -1;
} }
bool game_mode_context_unregister(GameModeContext *self, pid_t client) int game_mode_context_unregister(GameModeContext *self, pid_t client, pid_t requester)
{ {
GameModeClient *cl = NULL; GameModeClient *cl = NULL;
GameModeClient *prev = NULL; GameModeClient *prev = NULL;
bool found = false; bool found = false;
/* Check our requester config first */
if (requester != client) {
/* Lookup the executable first */
char *executable = game_mode_context_find_exe(requester);
if (!executable) {
return -1;
}
/* Check our blacklist and whitelist */
if (!config_get_supervisor_whitelisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable);
free(executable);
return -2;
} else if (config_get_supervisor_blacklisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable);
free(executable);
return -2;
}
free(executable);
}
/* Requires locking. */ /* Requires locking. */
pthread_rwlock_wrlock(&self->rwlock); pthread_rwlock_wrlock(&self->rwlock);
@ -457,7 +499,7 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t client)
" -- with a nearby 'Removing expired game' which means we cleaned up properly\n" " -- with a nearby 'Removing expired game' which means we cleaned up properly\n"
" -- (we will log this event). This hint will be displayed only once.\n", " -- (we will log this event). This hint will be displayed only once.\n",
client); client);
return false; return -1;
} }
/* When we hit bottom then end the game mode */ /* When we hit bottom then end the game mode */
@ -468,11 +510,32 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t client)
return true; return true;
} }
int game_mode_context_query_status(GameModeContext *self, pid_t client) int game_mode_context_query_status(GameModeContext *self, pid_t client, pid_t requester)
{ {
GameModeClient *cl = NULL; GameModeClient *cl = NULL;
int ret = 0; int ret = 0;
/* First check the requester settings if appropriate */
if (client != requester) {
char *executable = game_mode_context_find_exe(requester);
if (!executable) {
return -1;
}
/* Check our blacklist and whitelist */
if (!config_get_supervisor_whitelisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable);
free(executable);
return -2;
} else if (config_get_supervisor_blacklisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable);
free(executable);
return -2;
}
free(executable);
}
/* /*
* Check the current refcount on gamemode, this equates to whether gamemode is active or not, * Check the current refcount on gamemode, this equates to whether gamemode is active or not,
* see game_mode_context_register and game_mode_context_unregister * see game_mode_context_register and game_mode_context_unregister
@ -502,104 +565,6 @@ int game_mode_context_query_status(GameModeContext *self, pid_t client)
return ret; return ret;
} }
/**
* Register on behalf of caller
* TODO: long config_get_require_supervisor(GameModeConfig *self);
*/
int game_mode_context_register_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid)
{
int status = 0;
/* Lookup the executable first */
char *executable = game_mode_context_find_exe(callerpid);
if (!executable) {
status = -1;
goto error_cleanup;
}
/* Check our blacklist and whitelist */
if (!config_get_supervisor_whitelisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable);
status = -2;
goto error_cleanup;
} else if (config_get_supervisor_blacklisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable);
status = -2;
goto error_cleanup;
}
/* Checks cleared, try and register the game */
return game_mode_context_register(self, gamepid);
error_cleanup:
free(executable);
return status;
}
/**
* Unregister on behalf of caller
*/
int game_mode_context_unregister_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid)
{
int status = 0;
/* Lookup the executable first */
char *executable = game_mode_context_find_exe(callerpid);
if (!executable) {
status = -1;
goto error_cleanup;
}
/* Check our blacklist and whitelist */
if (!config_get_supervisor_whitelisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable);
status = -2;
goto error_cleanup;
} else if (config_get_supervisor_blacklisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable);
status = -2;
goto error_cleanup;
}
/* Checks cleared, try and register the game */
return game_mode_context_unregister(self, gamepid);
error_cleanup:
free(executable);
return status;
}
/**
* Request status on behalf of caller
*/
int game_mode_context_query_status_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid)
{
int status = 0;
/* Lookup the executable first */
char *executable = game_mode_context_find_exe(callerpid);
if (!executable) {
status = -1;
goto error_cleanup;
}
/* Check our blacklist and whitelist */
if (!config_get_supervisor_whitelisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (not in whitelist)\n", executable);
status = -2;
goto error_cleanup;
} else if (config_get_supervisor_blacklisted(self->config, executable)) {
LOG_MSG("Supervisor [%s] was rejected (in blacklist)\n", executable);
status = -2;
goto error_cleanup;
}
/* Checks cleared, call the original query */
return game_mode_context_query_status(self, gamepid);
error_cleanup:
free(executable);
return status;
}
/** /**
* Construct a new GameModeClient for the given process ID * Construct a new GameModeClient for the given process ID
* *

View File

@ -67,17 +67,23 @@ void game_mode_context_destroy(GameModeContext *self);
* Register a new game client with the context * Register a new game client with the context
* *
* @param pid Process ID for the remote client * @param pid Process ID for the remote client
* @returns True if the new client could be registered * @param requester Process ID for the remote requestor
* @returns 0 if the request was accepted and the client could be registered
* -1 if the request was accepted but the client could not be registered
* -2 if the request was rejected
*/ */
bool game_mode_context_register(GameModeContext *self, pid_t pid); int game_mode_context_register(GameModeContext *self, pid_t pid, pid_t requester);
/** /**
* Unregister an existing remote game client from the context * Unregister an existing remote game client from the context
* *
* @param pid Process ID for the remote client * @param pid Process ID for the remote client
* @returns True if the client was removed, and existed. * @param requester Process ID for the remote requestor
* @returns 0 if the request was accepted and the client existed
* -1 if the request was accepted but the client did not exist
* -2 if the request was rejected
*/ */
bool game_mode_context_unregister(GameModeContext *self, pid_t pid); int game_mode_context_unregister(GameModeContext *self, pid_t pid, pid_t requester);
/** /**
* Query the current status of gamemode * Query the current status of gamemode
@ -86,41 +92,9 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t pid);
* @returns Positive if gamemode is active * @returns Positive if gamemode is active
* 1 if gamemode is active but the client is not registered * 1 if gamemode is active but the client is not registered
* 2 if gamemode is active and the client is registered * 2 if gamemode is active and the client is registered
* -2 if this requester was rejected
*/ */
int game_mode_context_query_status(GameModeContext *self, pid_t pid); int game_mode_context_query_status(GameModeContext *self, pid_t pid, pid_t requester);
/**
* Register a new game client with the context on behalf of another process
*
* @param callerpid Process ID for the remote client making the request
* @param gamepid Process ID for the process to be registered
* @returns 0 if the request was accepted and the client could be registered
* -1 if the request was accepted but the client could not be registered
* -2 if the request was rejected
*/
int game_mode_context_register_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid);
/**
* Unregister an existing remote game client from the context on behalf of another process
*
* @param callerpid Process ID for the remote client making the request
* @param gamepid Process ID for the process to be registered
* @returns 0 if the request was accepted and the client existed
* -1 if the request was accepted but the client did not exist
* -2 if the request was rejected
*/
int game_mode_context_unregister_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid);
/**
* Query the current status of gamemode for another process
*
* @param pid Process ID for the remote client
* @returns Positive if gamemode is active
* 1 if gamemode is active but the client is not registered
* 2 if gamemode is active and the client is registered
* -2 if this supervisor was rejected
*/
int game_mode_context_query_status_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid);
/** /**
* Query the config of a gamemode context * Query the config of a gamemode context