Browse Source

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

Marc Di Luzio 6 years ago
parent
commit
1d40c0cc1b
3 changed files with 89 additions and 150 deletions
  1. 8 8
      daemon/dbus_messaging.c
  2. 72 107
      daemon/gamemode.c
  3. 9 35
      daemon/gamemode.h

+ 8 - 8
daemon/dbus_messaging.c

@@ -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);
 }

+ 72 - 107
daemon/gamemode.c

@@ -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
  *

+ 9 - 35
daemon/gamemode.h

@@ -67,60 +67,34 @@ 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
- */
-bool game_mode_context_register(GameModeContext *self, pid_t pid);
-
-/**
- * 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.
- */
-bool game_mode_context_unregister(GameModeContext *self, pid_t pid);
-
-/**
- * Query the current status of gamemode
- *
- * @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
- */
-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
+ * @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
  */
-int game_mode_context_register_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid);
+int game_mode_context_register(GameModeContext *self, pid_t pid, pid_t requester);
 
 /**
- * Unregister an existing remote game client from the context on behalf of another process
+ * Unregister an existing remote game client from the context
  *
- * @param callerpid Process ID for the remote client making the request
- * @param gamepid Process ID for the process to be registered
+ * @param pid Process ID for the remote client
+ * @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
  */
-int game_mode_context_unregister_by_pid(GameModeContext *self, pid_t callerpid, pid_t gamepid);
+int game_mode_context_unregister(GameModeContext *self, pid_t pid, pid_t requester);
 
 /**
- * Query the current status of gamemode for another process
+ * Query the current status of gamemode
  *
  * @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
+ *          -2 if this requester 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