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;
}
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;
}
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;
}
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);
}
@ -136,7 +136,7 @@ static int method_register_game_by_pid(sd_bus_message *m, void *userdata,
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);
}
@ -157,7 +157,7 @@ static int method_unregister_game_by_pid(sd_bus_message *m, void *userdata,
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);
}
@ -178,7 +178,7 @@ static int method_query_status_by_pid(sd_bus_message *m, void *userdata,
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);
}

View File

@ -291,7 +291,7 @@ static void game_mode_context_auto_expire(GameModeContext *self)
if (kill(client->pid, 0) != 0) {
LOG_MSG("Removing expired game [%i]...\n", client->pid);
pthread_rwlock_unlock(&self->rwlock);
game_mode_context_unregister(self, client->pid);
game_mode_context_unregister(self, client->pid, client->pid);
removing = true;
break;
}
@ -335,20 +335,40 @@ static int game_mode_context_num_clients(GameModeContext *self)
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 */
GameModeClient *cl = 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 */
if (game_mode_context_num_clients(self) + 1 > MAX_GAMES) {
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 */
pthread_rwlock_rdlock(&self->rwlock); // ensure our pointer is sane
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));
free(executable);
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 *prev = NULL;
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. */
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"
" -- (we will log this event). This hint will be displayed only once.\n",
client);
return false;
return -1;
}
/* 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;
}
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;
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,
* 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;
}
/**
* 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
*

View File

@ -67,17 +67,23 @@ void game_mode_context_destroy(GameModeContext *self);
* Register a new game client with the context
*
* @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
*
* @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
@ -86,41 +92,9 @@ bool game_mode_context_unregister(GameModeContext *self, pid_t pid);
* @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 requester was rejected
*/
int game_mode_context_query_status(GameModeContext *self, pid_t pid);
/**
* 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);
int game_mode_context_query_status(GameModeContext *self, pid_t pid, pid_t requester);
/**
* Query the config of a gamemode context