[Pkg-voip-commits] [janus] 56/163: Implemented way to edit some room properties dynamically in AudioBridge, VideoRoom and TextRoom (see #939)

Jonas Smedegaard dr at jones.dk
Sat Oct 28 01:22:09 UTC 2017


This is an automated email from the git hooks/post-receive script.

js pushed a commit to annotated tag debian/0.2.5-1
in repository janus.

commit e2fff24cd07253a831faaad17bb551702a997435
Author: Lorenzo Miniero <lminiero at gmail.com>
Date:   Wed Aug 2 14:00:03 2017 +0200

    Implemented way to edit some room properties dynamically in AudioBridge, VideoRoom and TextRoom (see #939)
---
 plugins/janus_audiobridge.c | 170 +++++++++++++++++++++++++++++++++++++++++---
 plugins/janus_textroom.c    | 127 ++++++++++++++++++++++++++++++++-
 plugins/janus_videoroom.c   | 142 +++++++++++++++++++++++++++++++++++-
 3 files changed, 426 insertions(+), 13 deletions(-)

diff --git a/plugins/janus_audiobridge.c b/plugins/janus_audiobridge.c
index 83d1c83..00cf23a 100644
--- a/plugins/janus_audiobridge.c
+++ b/plugins/janus_audiobridge.c
@@ -39,11 +39,12 @@ record_file =	/path/to/recording.wav (where to save the recording)
  * (invalid JSON, invalid request) which will always result in a
  * synchronous error response even for asynchronous requests. 
  * 
- * \c create , \c destroy , \c exists, \c allowed, \c kick, \c list,
+ * \c create , \c edit , \c destroy , \c exists, \c allowed, \c kick, \c list,
  * \c listparticipants and \c resetdecoder are synchronous requests,
  * which means you'll get a response directly within the context of the
  * transaction. \c create allows you to create a new audio conference bridge
- * dynamically, as an alternative to using the configuration file;
+ * dynamically, as an alternative to using the configuration file; \c edit
+ * allows you to dynamically edit some room properties (e.g., the PIN);
  * \c destroy removes an audio conference bridge and destroys it, kicking
  * all the users out as part of the process; \c exists allows you to
  * check whether a specific audio conference exists; \c allowed allows
@@ -125,6 +126,36 @@ record_file =	/path/to/recording.wav (where to save the recording)
  * include the correct \c admin_key value in an "admin_key" property
  * will succeed, and will be rejected otherwise.
  * 
+ * Once a room has been created, you can still edit some (but not all)
+ * of its properties using the \c edit request. This allows you to modify
+ * the room description, secret, pin and whether it's private or not: you
+ * won't be able to modify other more static properties, like the room ID,
+ * the sampling rate, the extensions-related stuff and so on. If you're
+ * interested in changing the ACL, instead, check the \c allowed message.
+ * An \c edit request has to be formatted as follows:
+ *
+\verbatim
+{
+	"request" : "edit",
+	"room" : <unique numeric ID of the room to destroy>,
+	"secret" : "<room secret, mandatory if configured>",
+	"new_description" : "<new pretty name of the room, optional>",
+	"new_secret" : "<new password required to edit/destroy the room, optional>",
+	"new_pin" : "<new password required to join the room, optional>",
+	"new_is_private" : <true|false, whether the room should appear in a list request>,
+	"permanent" : <true|false, whether the room should be also removed from the config file, default false>
+}
+\endverbatim
+ *
+ * A successful destruction procedure will result in an \c edited response:
+ *
+\verbatim
+{
+	"audiobridge" : "edited",
+	"room" : <unique numeric ID>
+}
+\endverbatim
+ *
  * On the other hand, \c destroy can be used to destroy an existing audio
  * room, whether created dynamically or statically, and has to be
  * formatted as follows:
@@ -632,6 +663,15 @@ static struct janus_json_parameter create_parameters[] = {
 	{"audio_level_average", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
 	{"room", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}
 };
+static struct janus_json_parameter edit_parameters[] = {
+	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
+	{"secret", JSON_STRING, 0},
+	{"new_description", JSON_STRING, 0},
+	{"new_secret", JSON_STRING, 0},
+	{"new_pin", JSON_STRING, 0},
+	{"new_is_private", JANUS_JSON_BOOL, 0},
+	{"permanent", JANUS_JSON_BOOL, 0}
+};
 static struct janus_json_parameter destroy_parameters[] = {
 	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
 	{"permanent", JANUS_JSON_BOOL, 0}
@@ -1625,16 +1665,124 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 		response = json_object();
 		json_object_set_new(response, "audiobridge", json_string("created"));
 		json_object_set_new(response, "room", json_integer(audiobridge->room_id));
+		json_object_set_new(response, "permanent", save ? json_true() : json_false());
 		/* Also notify event handlers */
 		if(notify_events && gateway->events_is_enabled()) {
 			json_t *info = json_object();
 			json_object_set_new(info, "event", json_string("created"));
 			json_object_set_new(info, "room", json_integer(audiobridge->room_id));
-			json_object_set_new(info, "permanent", save ? json_true() : json_false());
 			gateway->notify_event(&janus_audiobridge_plugin, session->handle, info);
 		}
 		janus_mutex_unlock(&rooms_mutex);
 		goto plugin_response;
+	} else if(!strcasecmp(request_text, "edit")) {
+		JANUS_LOG(LOG_VERB, "Attempt to edit an existing audiobridge room\n");
+		JANUS_VALIDATE_JSON_OBJECT(root, edit_parameters,
+			error_code, error_cause, TRUE,
+			JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT);
+		if(error_code != 0)
+			goto plugin_response;
+		/* We only allow for a limited set of properties to be edited */
+		json_t *room = json_object_get(root, "room");
+		json_t *desc = json_object_get(root, "new_description");
+		json_t *secret = json_object_get(root, "new_secret");
+		json_t *pin = json_object_get(root, "new_pin");
+		json_t *is_private = json_object_get(root, "new_is_private");
+		json_t *permanent = json_object_get(root, "permanent");
+		gboolean save = permanent ? json_is_true(permanent) : FALSE;
+		if(save && config == NULL) {
+			JANUS_LOG(LOG_ERR, "No configuration file, can't edit room permanently\n");
+			error_code = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
+			g_snprintf(error_cause, 512, "No configuration file, can't edit room permanently");
+			goto plugin_response;
+		}
+		guint64 room_id = json_integer_value(room);
+		janus_mutex_lock(&rooms_mutex);
+		janus_audiobridge_room *audiobridge = g_hash_table_lookup(rooms, &room_id);
+		if(audiobridge == NULL) {
+			janus_mutex_unlock(&rooms_mutex);
+			JANUS_LOG(LOG_ERR, "No such room (%"SCNu64")\n", room_id);
+			error_code = JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_ROOM;
+			g_snprintf(error_cause, 512, "No such room (%"SCNu64")", room_id);
+			goto plugin_response;
+		}
+		janus_mutex_lock(&audiobridge->mutex);
+		/* A secret may be required for this action */
+		JANUS_CHECK_SECRET(audiobridge->room_secret, root, "secret", error_code, error_cause,
+			JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_UNAUTHORIZED);
+		if(error_code != 0) {
+			janus_mutex_unlock(&audiobridge->mutex);
+			janus_mutex_unlock(&rooms_mutex);
+			goto plugin_response;
+		}
+		/* Edit the room properties that were provided */
+		if(desc != NULL && strlen(json_string_value(desc)) > 0) {
+			char *old_description = audiobridge->room_name;
+			char *new_description = g_strdup(json_string_value(desc));
+			audiobridge->room_name = new_description;
+			g_free(old_description);
+		}
+		if(is_private)
+			audiobridge->is_private = json_is_true(is_private);
+		if(secret && strlen(json_string_value(secret)) > 0) {
+			char *old_secret = audiobridge->room_secret;
+			char *new_secret = g_strdup(json_string_value(secret));
+			audiobridge->room_secret = new_secret;
+			g_free(old_secret);
+		}
+		if(pin && strlen(json_string_value(pin)) > 0) {
+			char *old_pin = audiobridge->room_pin;
+			char *new_pin = g_strdup(json_string_value(pin));
+			audiobridge->room_pin = new_pin;
+			g_free(old_pin);
+		}
+		if(save) {
+			/* This change is permanent: save to the configuration file too
+			 * FIXME: We should check if anything fails... */
+			JANUS_LOG(LOG_VERB, "Modifying room %"SCNu64" permanently in config file\n", room_id);
+			janus_mutex_lock(&config_mutex);
+			char cat[BUFSIZ], value[BUFSIZ];
+			/* The room ID is the category */
+			g_snprintf(cat, BUFSIZ, "%"SCNu64, room_id);
+			/* Remove the old category first */
+			janus_config_remove_category(config, cat);
+			/* Now write the room details again */
+			janus_config_add_category(config, cat);
+			janus_config_add_item(config, cat, "description", audiobridge->room_name);
+			if(audiobridge->is_private)
+				janus_config_add_item(config, cat, "is_private", "yes");
+			g_snprintf(value, BUFSIZ, "%"SCNu32, audiobridge->sampling_rate);
+			janus_config_add_item(config, cat, "sampling_rate", value);
+			if(audiobridge->room_secret)
+				janus_config_add_item(config, cat, "secret", audiobridge->room_secret);
+			if(audiobridge->room_pin)
+				janus_config_add_item(config, cat, "pin", audiobridge->room_pin);
+			if(audiobridge->record_file) {
+				janus_config_add_item(config, cat, "record", "yes");
+				janus_config_add_item(config, cat, "record_file", audiobridge->record_file);
+			}
+			/* Save modified configuration */
+			if(janus_config_save(config, config_folder, JANUS_AUDIOBRIDGE_PACKAGE) < 0)
+				save = FALSE;	/* This will notify the user the room changes are not permanent */
+			janus_mutex_unlock(&config_mutex);
+		}
+		/* Prepare response/notification */
+		response = json_object();
+		json_object_set_new(response, "audiobridge", json_string("edited"));
+		json_object_set_new(response, "room", json_integer(audiobridge->room_id));
+		json_object_set_new(response, "permanent", save ? json_true() : json_false());
+		/* Also notify event handlers */
+		if(notify_events && gateway->events_is_enabled()) {
+			json_t *info = json_object();
+			json_object_set_new(info, "event", json_string("edited"));
+			json_object_set_new(info, "room", json_integer(room_id));
+			gateway->notify_event(&janus_audiobridge_plugin, session->handle, info);
+		}
+		janus_mutex_unlock(&audiobridge->mutex);
+		janus_mutex_unlock(&rooms_mutex);
+		/* Done */
+		JANUS_LOG(LOG_VERB, "Audiobridge room edited\n");
+		goto plugin_response;
 	} else if(!strcasecmp(request_text, "destroy")) {
 		JANUS_LOG(LOG_VERB, "Attempt to destroy an existing audiobridge room\n");
 		JANUS_VALIDATE_JSON_OBJECT(root, destroy_parameters,
@@ -1682,13 +1830,14 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 			g_snprintf(cat, BUFSIZ, "%"SCNu64, room_id);
 			janus_config_remove_category(config, cat);
 			/* Save modified configuration */
-			janus_config_save(config, config_folder, JANUS_AUDIOBRIDGE_PACKAGE);
+			if(janus_config_save(config, config_folder, JANUS_AUDIOBRIDGE_PACKAGE) < 0)
+				save = FALSE;	/* This will notify the user the room destruction is not permanent */
 			janus_mutex_unlock(&config_mutex);
 		}
 		/* Prepare response/notification */
-		response = json_object();
-		json_object_set_new(response, "audiobridge", json_string("destroyed"));
-		json_object_set_new(response, "room", json_integer(room_id));
+		json_t *destroyed = json_object();
+		json_object_set_new(destroyed, "audiobridge", json_string("destroyed"));
+		json_object_set_new(destroyed, "room", json_integer(room_id));
 		/* Notify all participants that the fun is over, and that they'll be kicked */
 		JANUS_LOG(LOG_VERB, "Notifying all participants\n");
 		GHashTableIter iter;
@@ -1698,7 +1847,7 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 			janus_audiobridge_participant *p = value;
 			if(p && p->session) {
 				p->room = NULL;
-				int ret = gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, response, NULL);
+				int ret = gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, destroyed, NULL);
 				JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
 				/* Get rid of queued packets */
 				janus_mutex_lock(&p->qmutex);
@@ -1719,6 +1868,7 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 				janus_mutex_unlock(&p->qmutex);
 			}
 		}
+		json_decref(destroyed);
 		/* Also notify event handlers */
 		if(notify_events && gateway->events_is_enabled()) {
 			json_t *info = json_object();
@@ -1732,6 +1882,10 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 		janus_mutex_unlock(&rooms_mutex);
 		g_thread_join(audiobridge->thread);
 		/* Done */
+		response = json_object();
+		json_object_set_new(response, "audiobridge", json_string("destroyed"));
+		json_object_set_new(response, "room", json_integer(room_id));
+		json_object_set_new(response, "permanent", save ? json_true() : json_false());
 		JANUS_LOG(LOG_VERB, "Audiobridge room destroyed\n");
 		goto plugin_response;
 	} else if(!strcasecmp(request_text, "list")) {
diff --git a/plugins/janus_textroom.c b/plugins/janus_textroom.c
index 0bc79c8..704589f 100644
--- a/plugins/janus_textroom.c
+++ b/plugins/janus_textroom.c
@@ -15,7 +15,7 @@
  * a "setup" message, by which the user initializes the PeerConnection
  * itself. Apart from that, all other messages can be exchanged directly
  * via Data Channels. For room management purposes, though, requests like
- * "create", "destroy", "list" and "exists" are available through the
+ * "create", "edit", "destroy", "list" and "exists" are available through the
  * Janus API as well: notice that in this case you'll have to use "request"
  * and not "textroom" as the name of the request.
  *
@@ -142,6 +142,7 @@ static struct janus_json_parameter adminkey_parameters[] = {
 	{"admin_key", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
 };
 static struct janus_json_parameter create_parameters[] = {
+	{"room", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
 	{"description", JSON_STRING, 0},
 	{"secret", JSON_STRING, 0},
 	{"pin", JSON_STRING, 0},
@@ -149,6 +150,14 @@ static struct janus_json_parameter create_parameters[] = {
 	{"is_private", JANUS_JSON_BOOL, 0},
 	{"allowed", JSON_ARRAY, 0}
 };
+static struct janus_json_parameter edit_parameters[] = {
+	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
+	{"description", JSON_STRING, 0},
+	{"secret", JSON_STRING, 0},
+	{"pin", JSON_STRING, 0},
+	{"post", JSON_STRING, 0},
+	{"is_private", JANUS_JSON_BOOL, 0}
+};
 static struct janus_json_parameter allowed_parameters[] = {
 	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
 	{"secret", JSON_STRING, 0},
@@ -695,6 +704,7 @@ struct janus_plugin_result *janus_textroom_handle_message(janus_plugin_session *
 	if(!strcasecmp(request_text, "list")
 			|| !strcasecmp(request_text, "exists")
 			|| !strcasecmp(request_text, "create")
+			|| !strcasecmp(request_text, "edit")
 			|| !strcasecmp(request_text, "destroy")) {
 		/* These requests typically only belong to the datachannel
 		 * messaging, but for admin purposes we might use them on
@@ -1559,6 +1569,116 @@ janus_plugin_result *janus_textroom_handle_incoming_request(janus_plugin_session
 			json_object_set_new(reply, "room", json_integer(room_id));
 			json_object_set_new(reply, "exists", room_exists ? json_true() : json_false());
 		}
+	} else if(!strcasecmp(request_text, "edit")) {
+		JANUS_VALIDATE_JSON_OBJECT(root, edit_parameters,
+			error_code, error_cause, TRUE,
+			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT);
+		if(error_code != 0)
+			goto msg_response;
+		/* We only allow for a limited set of properties to be edited */
+		json_t *room = json_object_get(root, "room");
+		json_t *desc = json_object_get(root, "new_description");
+		json_t *secret = json_object_get(root, "new_secret");
+		json_t *is_private = json_object_get(root, "new_is_private");
+		json_t *pin = json_object_get(root, "new_pin");
+		json_t *post = json_object_get(root, "new_post");
+		json_t *permanent = json_object_get(root, "permanent");
+		gboolean save = permanent ? json_is_true(permanent) : FALSE;
+		if(save && config == NULL) {
+			JANUS_LOG(LOG_ERR, "No configuration file, can't edit room permanently\n");
+			error_code = JANUS_TEXTROOM_ERROR_UNKNOWN_ERROR;
+			g_snprintf(error_cause, 512, "No configuration file, can't edit room permanently");
+			goto msg_response;
+		}
+		guint64 room_id = json_integer_value(room);
+		janus_mutex_lock(&rooms_mutex);
+		janus_textroom_room *textroom = g_hash_table_lookup(rooms, &room_id);
+		if(textroom == NULL) {
+			janus_mutex_unlock(&rooms_mutex);
+			JANUS_LOG(LOG_ERR, "No such room (%"SCNu64")\n", room_id);
+			error_code = JANUS_TEXTROOM_ERROR_NO_SUCH_ROOM;
+			g_snprintf(error_cause, 512, "No such room (%"SCNu64")", room_id);
+			goto msg_response;
+		}
+		janus_mutex_lock(&textroom->mutex);
+		/* A secret may be required for this action */
+		JANUS_CHECK_SECRET(textroom->room_secret, root, "secret", error_code, error_cause,
+			JANUS_TEXTROOM_ERROR_MISSING_ELEMENT, JANUS_TEXTROOM_ERROR_INVALID_ELEMENT, JANUS_TEXTROOM_ERROR_UNAUTHORIZED);
+		if(error_code != 0) {
+			janus_mutex_unlock(&textroom->mutex);
+			janus_mutex_unlock(&rooms_mutex);
+			goto msg_response;
+		}
+		/* Edit the room properties that were provided */
+		if(desc != NULL && strlen(json_string_value(desc)) > 0) {
+			char *old_description = textroom->room_name;
+			char *new_description = g_strdup(json_string_value(desc));
+			textroom->room_name = new_description;
+			g_free(old_description);
+		}
+		if(is_private)
+			textroom->is_private = json_is_true(is_private);
+		if(secret && strlen(json_string_value(secret)) > 0) {
+			char *old_secret = textroom->room_secret;
+			char *new_secret = g_strdup(json_string_value(secret));
+			textroom->room_secret = new_secret;
+			g_free(old_secret);
+		}
+		if(post && strlen(json_string_value(post)) > 0) {
+			char *old_post = textroom->http_backend;
+			char *new_post = g_strdup(json_string_value(post));
+			textroom->http_backend = new_post;
+			g_free(old_post);
+		}
+		if(pin && strlen(json_string_value(pin)) > 0) {
+			char *old_pin = textroom->room_pin;
+			char *new_pin = g_strdup(json_string_value(pin));
+			textroom->room_pin = new_pin;
+			g_free(old_pin);
+		}
+		if(save) {
+			/* This change is permanent: save to the configuration file too
+			 * FIXME: We should check if anything fails... */
+			JANUS_LOG(LOG_VERB, "Modifying room %"SCNu64" permanently in config file\n", room_id);
+			janus_mutex_lock(&config_mutex);
+			char cat[BUFSIZ];
+			/* The room ID is the category */
+			g_snprintf(cat, BUFSIZ, "%"SCNu64, room_id);
+			/* Remove the old category first */
+			janus_config_remove_category(config, cat);
+			/* Now write the room details again */
+			janus_config_add_category(config, cat);
+			janus_config_add_item(config, cat, "description", textroom->room_name);
+			if(textroom->is_private)
+				janus_config_add_item(config, cat, "is_private", "yes");
+			if(textroom->room_secret)
+				janus_config_add_item(config, cat, "secret", textroom->room_secret);
+			if(textroom->room_pin)
+				janus_config_add_item(config, cat, "pin", textroom->room_pin);
+			if(textroom->http_backend)
+				janus_config_add_item(config, cat, "post", textroom->http_backend);
+			/* Save modified configuration */
+			if(janus_config_save(config, config_folder, JANUS_TEXTROOM_PACKAGE) < 0)
+				save = FALSE;	/* This will notify the user the room changes are not permanent */
+			janus_mutex_unlock(&config_mutex);
+		}
+		janus_mutex_unlock(&textroom->mutex);
+		janus_mutex_unlock(&rooms_mutex);
+		if(!internal) {
+			/* Send response back */
+			reply = json_object();
+			/* Notice that we reply differently if the request came via Janus API */
+			json_object_set_new(reply, "textroom", json_string(json == NULL ? "success" : "edited"));
+			json_object_set_new(reply, "room", json_integer(room_id));
+			json_object_set_new(reply, "permanent", save ? json_true() : json_false());
+		}
+		/* Also notify event handlers */
+		if(notify_events && gateway->events_is_enabled()) {
+			json_t *info = json_object();
+			json_object_set_new(info, "event", json_string("edited"));
+			json_object_set_new(info, "room", json_integer(room_id));
+			gateway->notify_event(&janus_textroom_plugin, session->handle, info);
+		}
 	} else if(!strcasecmp(request_text, "destroy")) {
 		JANUS_VALIDATE_JSON_OBJECT(root, room_parameters,
 			error_code, error_cause, TRUE,
@@ -1605,7 +1725,8 @@ janus_plugin_result *janus_textroom_handle_incoming_request(janus_plugin_session
 			g_snprintf(cat, BUFSIZ, "%"SCNu64, room_id);
 			janus_config_remove_category(config, cat);
 			/* Save modified configuration */
-			janus_config_save(config, config_folder, JANUS_TEXTROOM_PACKAGE);
+			if(janus_config_save(config, config_folder, JANUS_TEXTROOM_PACKAGE) < 0)
+				save = FALSE;	/* This will notify the user the room destruction is not permanent */
 			janus_mutex_unlock(&config_mutex);
 		}
 		/* Notify all participants */
@@ -1642,6 +1763,8 @@ janus_plugin_result *janus_textroom_handle_incoming_request(janus_plugin_session
 			reply = json_object();
 			/* Notice that we reply differently if the request came via Janus API */
 			json_object_set_new(reply, "textroom", json_string(json == NULL ? "success" : "destroyed"));
+			json_object_set_new(reply, "room", json_integer(room_id));
+			json_object_set_new(reply, "permanent", save ? json_true() : json_false());
 		}
 		/* We'll let the watchdog worry about freeing resources */
 		old_rooms = g_list_append(old_rooms, textroom);
diff --git a/plugins/janus_videoroom.c b/plugins/janus_videoroom.c
index 80459c8..ac41c94 100644
--- a/plugins/janus_videoroom.c
+++ b/plugins/janus_videoroom.c
@@ -89,11 +89,12 @@ rec_dir = <folder where recordings should be stored, when enabled>
  * (invalid JSON, invalid request) which will always result in a
  * synchronous error response even for asynchronous requests. 
  * 
- * \c create , \c destroy , \c exists, \c list, \c allowed, \c kick and
+ * \c create , \c destroy , \c edit , \c exists, \c list, \c allowed, \c kick and
  * and \c listparticipants are synchronous requests, which means you'll
  * get a response directly within the context of the transaction.
  * \c create allows you to create a new video room dynamically, as an
- * alternative to using the configuration file; \c destroy removes a
+ * alternative to using the configuration file; \c edit allows you to
+ * dynamically edit some room properties (e.g., the PIN); \c destroy removes a
  * video room and destroys it, kicking all the users out as part of the
  * process; \c exists allows you to check whether a specific video room
  * exists; finally, \c list lists all the available rooms, while \c
@@ -241,6 +242,19 @@ static struct janus_json_parameter create_parameters[] = {
 	{"rec_dir", JSON_STRING, 0},
 	{"permanent", JANUS_JSON_BOOL, 0}
 };
+static struct janus_json_parameter edit_parameters[] = {
+	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE},
+	{"secret", JSON_STRING, 0},
+	{"new_description", JSON_STRING, 0},
+	{"new_is_private", JANUS_JSON_BOOL, 0},
+	{"new_secret", JSON_STRING, 0},
+	{"new_pin", JSON_STRING, 0},
+	{"new_require_pvtid", JANUS_JSON_BOOL, 0},
+	{"new_bitrate", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
+	{"new_fir_freq", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
+	{"new_publishers", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE},
+	{"permanent", JANUS_JSON_BOOL, 0}
+};
 static struct janus_json_parameter room_parameters[] = {
 	{"room", JSON_INTEGER, JANUS_JSON_PARAM_REQUIRED | JANUS_JSON_PARAM_POSITIVE}
 };
@@ -1652,6 +1666,126 @@ struct janus_plugin_result *janus_videoroom_handle_message(janus_plugin_session
 			gateway->notify_event(&janus_videoroom_plugin, session->handle, info);
 		}
 		goto plugin_response;
+	} else if(!strcasecmp(request_text, "edit")) {
+		/* Edit the properties for an existing videoroom */
+		JANUS_LOG(LOG_VERB, "Attempt to edit the properties of an existing videoroom room\n");
+		JANUS_VALIDATE_JSON_OBJECT(root, edit_parameters,
+			error_code, error_cause, TRUE,
+			JANUS_VIDEOROOM_ERROR_MISSING_ELEMENT, JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT);
+		if(error_code != 0)
+			goto plugin_response;
+		/* We only allow for a limited set of properties to be edited */
+		json_t *desc = json_object_get(root, "new_description");
+		json_t *is_private = json_object_get(root, "new_is_private");
+		json_t *req_pvtid = json_object_get(root, "new_require_pvtid");
+		json_t *secret = json_object_get(root, "new_secret");
+		json_t *pin = json_object_get(root, "new_pin");
+		json_t *bitrate = json_object_get(root, "new_bitrate");
+		json_t *fir_freq = json_object_get(root, "new_fir_freq");
+		json_t *publishers = json_object_get(root, "new_publishers");
+		json_t *permanent = json_object_get(root, "permanent");
+		gboolean save = permanent ? json_is_true(permanent) : FALSE;
+		if(save && config == NULL) {
+			JANUS_LOG(LOG_ERR, "No configuration file, can't edit room permanently\n");
+			error_code = JANUS_VIDEOROOM_ERROR_UNKNOWN_ERROR;
+			g_snprintf(error_cause, 512, "No configuration file, can't edit room permanently");
+			goto plugin_response;
+		}
+		janus_mutex_lock(&rooms_mutex);
+		janus_videoroom *videoroom = NULL;
+		error_code = janus_videoroom_access_room(root, TRUE, FALSE, &videoroom, error_cause, sizeof(error_cause));
+		if(error_code != 0) {
+			janus_mutex_unlock(&rooms_mutex);
+			goto plugin_response;
+		}
+		/* Edit the room properties that were provided */
+		if(desc != NULL && strlen(json_string_value(desc)) > 0) {
+			char *old_description = videoroom->room_name;
+			char *new_description = g_strdup(json_string_value(desc));
+			videoroom->room_name = new_description;
+			g_free(old_description);
+		}
+		if(is_private)
+			videoroom->is_private = json_is_true(is_private);
+		if(req_pvtid)
+			videoroom->require_pvtid = json_is_true(req_pvtid);
+		if(publishers)
+			videoroom->max_publishers = json_integer_value(publishers);
+		if(bitrate) {
+			videoroom->bitrate = json_integer_value(bitrate);
+			if(videoroom->bitrate > 0 && videoroom->bitrate < 64000)
+				videoroom->bitrate = 64000;	/* Don't go below 64k */
+		}
+		if(fir_freq)
+			videoroom->fir_freq = json_integer_value(fir_freq);
+		if(secret && strlen(json_string_value(secret)) > 0) {
+			char *old_secret = videoroom->room_secret;
+			char *new_secret = g_strdup(json_string_value(secret));
+			videoroom->room_secret = new_secret;
+			g_free(old_secret);
+		}
+		if(pin && strlen(json_string_value(pin)) > 0) {
+			char *old_pin = videoroom->room_pin;
+			char *new_pin = g_strdup(json_string_value(pin));
+			videoroom->room_pin = new_pin;
+			g_free(old_pin);
+		}
+		if(save) {
+			/* This room is permanent: save to the configuration file too
+			 * FIXME: We should check if anything fails... */
+			JANUS_LOG(LOG_VERB, "Modifying room %"SCNu64" permanently in config file\n", videoroom->room_id);
+			janus_mutex_lock(&config_mutex);
+			char cat[BUFSIZ], value[BUFSIZ];
+			/* The room ID is the category */
+			g_snprintf(cat, BUFSIZ, "%"SCNu64, videoroom->room_id);
+			/* Remove the old category first */
+			janus_config_remove_category(config, cat);
+			/* Now write the room details again */
+			janus_config_add_category(config, cat);
+			janus_config_add_item(config, cat, "description", videoroom->room_name);
+			if(videoroom->is_private)
+				janus_config_add_item(config, cat, "is_private", "yes");
+			if(videoroom->require_pvtid)
+				janus_config_add_item(config, cat, "require_pvtid", "yes");
+			g_snprintf(value, BUFSIZ, "%"SCNu32, videoroom->bitrate);
+			janus_config_add_item(config, cat, "bitrate", value);
+			g_snprintf(value, BUFSIZ, "%d", videoroom->max_publishers);
+			janus_config_add_item(config, cat, "publishers", value);
+			if(videoroom->fir_freq) {
+				g_snprintf(value, BUFSIZ, "%"SCNu16, videoroom->fir_freq);
+				janus_config_add_item(config, cat, "fir_freq", value);
+			}
+			janus_config_add_item(config, cat, "audiocodec", janus_videoroom_audiocodec_name(videoroom->acodec));
+			janus_config_add_item(config, cat, "videocodec", janus_videoroom_videocodec_name(videoroom->vcodec));
+			if(videoroom->do_svc)
+				janus_config_add_item(config, cat, "video_svc", "yes");
+			if(videoroom->room_secret)
+				janus_config_add_item(config, cat, "secret", videoroom->room_secret);
+			if(videoroom->room_pin)
+				janus_config_add_item(config, cat, "pin", videoroom->room_pin);
+			if(videoroom->record)
+				janus_config_add_item(config, cat, "record", "yes");
+			if(videoroom->rec_dir)
+				janus_config_add_item(config, cat, "rec_dir", videoroom->rec_dir);
+			/* Save modified configuration */
+			if(janus_config_save(config, config_folder, JANUS_VIDEOROOM_PACKAGE) < 0)
+				save = FALSE;	/* This will notify the user the room changes are not permanent */
+			janus_mutex_unlock(&config_mutex);
+		}
+		janus_mutex_unlock(&rooms_mutex);
+		/* Send info back */
+		response = json_object();
+		json_object_set_new(response, "videoroom", json_string("edited"));
+		json_object_set_new(response, "room", json_integer(videoroom->room_id));
+		json_object_set_new(response, "permanent", save ? json_true() : json_false());
+		/* Also notify event handlers */
+		if(notify_events && gateway->events_is_enabled()) {
+			json_t *info = json_object();
+			json_object_set_new(info, "event", json_string("edited"));
+			json_object_set_new(info, "room", json_integer(videoroom->room_id));
+			gateway->notify_event(&janus_videoroom_plugin, session->handle, info);
+		}
+		goto plugin_response;
 	} else if(!strcasecmp(request_text, "destroy")) {
 		JANUS_LOG(LOG_VERB, "Attempt to destroy an existing videoroom room\n");
 		JANUS_VALIDATE_JSON_OBJECT(root, destroy_parameters,
@@ -1718,13 +1852,15 @@ struct janus_plugin_result *janus_videoroom_handle_message(janus_plugin_session
 			g_snprintf(cat, BUFSIZ, "%"SCNu64, room_id);
 			janus_config_remove_category(config, cat);
 			/* Save modified configuration */
-			janus_config_save(config, config_folder, JANUS_VIDEOROOM_PACKAGE);
+			if(janus_config_save(config, config_folder, JANUS_VIDEOROOM_PACKAGE) < 0)
+				save = FALSE;	/* This will notify the user the room destruction is not permanent */
 			janus_mutex_unlock(&config_mutex);
 		}
 		/* Done */
 		response = json_object();
 		json_object_set_new(response, "videoroom", json_string("destroyed"));
 		json_object_set_new(response, "room", json_integer(room_id));
+		json_object_set_new(response, "permanent", save ? json_true() : json_false());
 		goto plugin_response;
 	} else if(!strcasecmp(request_text, "list")) {
 		/* List all rooms (but private ones) and their details (except for the secret, of course...) */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/janus.git



More information about the Pkg-voip-commits mailing list