From d601fe2bd26fc6f042593d01de070fb2e5bc06bd Mon Sep 17 00:00:00 2001 From: Mikael Nousiainen Date: Wed, 11 May 2022 22:47:39 +0300 Subject: [PATCH 1/5] Add kick_all request and possibility to remove PIN code to both the Audiobridge and the Streaming plugins --- src/plugins/janus_audiobridge.c | 135 +++++++++++++++++++++++++++++- src/plugins/janus_streaming.c | 143 +++++++++++++++++++++++++++++++- 2 files changed, 270 insertions(+), 8 deletions(-) diff --git a/src/plugins/janus_audiobridge.c b/src/plugins/janus_audiobridge.c index ae78a7050a..04b8e853af 100644 --- a/src/plugins/janus_audiobridge.c +++ b/src/plugins/janus_audiobridge.c @@ -202,7 +202,7 @@ room-: { "secret" : "", "new_description" : "", "new_secret" : "", - "new_pin" : "", + "new_pin" : "", "new_is_private" : , "new_record_dir" : "", "new_mjrs_dir" : "", @@ -354,6 +354,29 @@ room-: { { "audiobridge" : "success", } +\endverbatim + * + * If you're the administrator of a room (that is, you created it and have access + * to the secret) you can kick all participants using the \c kick_all request. Notice + * that this only kicks all users out of the room, but does not prevent them from + * re-joining: to ban them, you need to first remove them from the list of + * authorized users (see \c allowed request) and then perform \c kick_all. + * The \c kick_all request has to be formatted as follows: + * +\verbatim +{ + "request" : "kick_all", + "secret" : "", + "room" : +} +\endverbatim + * + * A successful request will result in a \c success response: + * +\verbatim +{ + "audiobridge" : "success", +} \endverbatim * * To get a list of the available rooms (excluded those configured or @@ -3476,10 +3499,14 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s audiobridge->room_secret = new_secret; g_free(old_secret); } - if(pin && strlen(json_string_value(pin)) > 0) { + if(pin) { char *old_pin = audiobridge->room_pin; - char *new_pin = g_strdup(json_string_value(pin)); - audiobridge->room_pin = new_pin; + if(strlen(json_string_value(pin)) > 0) { + char *new_pin = g_strdup(json_string_value(pin)); + audiobridge->room_pin = new_pin; + } else { + audiobridge->room_pin = NULL; + } g_free(old_pin); } if(recdir) { @@ -4412,6 +4439,106 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s janus_mutex_unlock(&audiobridge->mutex); janus_refcount_decrease(&audiobridge->ref); goto prepare_response; + } else if(!strcasecmp(request_text, "kick_all")) { + JANUS_LOG(LOG_VERB, "Attempt to kick all participants from an existing AudioBridge room\n"); + JANUS_VALIDATE_JSON_OBJECT(root, secret_parameters, + error_code, error_cause, TRUE, + JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT); + if(error_code != 0) + goto prepare_response; + if(!string_ids) { + JANUS_VALIDATE_JSON_OBJECT(root, room_parameters, + error_code, error_cause, TRUE, + JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT); + } else { + JANUS_VALIDATE_JSON_OBJECT(root, roomstr_parameters, + error_code, error_cause, TRUE, + JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT); + } + if(error_code != 0) + goto prepare_response; + json_t *room = json_object_get(root, "room"); + guint64 room_id = 0; + char room_id_num[30], *room_id_str = NULL; + if(!string_ids) { + room_id = json_integer_value(room); + g_snprintf(room_id_num, sizeof(room_id_num), "%"SCNu64, room_id); + room_id_str = room_id_num; + } else { + room_id_str = (char *)json_string_value(room); + } + janus_mutex_lock(&rooms_mutex); + janus_audiobridge_room *audiobridge = g_hash_table_lookup(rooms, + string_ids ? (gpointer)room_id_str : (gpointer)&room_id); + if(audiobridge == NULL) { + janus_mutex_unlock(&rooms_mutex); + error_code = JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_ROOM; + JANUS_LOG(LOG_ERR, "No such room (%s)\n", room_id_str); + g_snprintf(error_cause, 512, "No such room (%s)", room_id_str); + goto prepare_response; + } + janus_refcount_increase(&audiobridge->ref); + janus_mutex_lock(&audiobridge->mutex); + janus_mutex_unlock(&rooms_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_refcount_decrease(&audiobridge->ref); + goto prepare_response; + } + GHashTableIter kick_iter; + gpointer kick_value; + g_hash_table_iter_init(&kick_iter, audiobridge->participants); + while(g_hash_table_iter_next(&kick_iter, NULL, &kick_value)) { + janus_audiobridge_participant *participant = kick_value; + JANUS_LOG(LOG_VERB, "Kicking participant %s (%s)\n", + participant->user_id_str, participant->display ? participant->display : "??"); + guint64 user_id = 0; + char user_id_num[30], *user_id_str = NULL; + if(string_ids) { + user_id_str = participant->user_id_str; + } else { + user_id = participant->user_id; + g_snprintf(user_id_num, sizeof(user_id_num), "%"SCNu64, user_id); + user_id_str = user_id_num; + } + /* Notify all participants about the kick */ + json_t *event = json_object(); + json_object_set_new(event, "audiobridge", json_string("event")); + json_object_set_new(event, "room", string_ids ? json_string(room_id_str) : json_integer(room_id)); + json_object_set_new(event, "kicked", string_ids ? json_string(user_id_str) : json_integer(user_id)); + GHashTableIter iter; + gpointer value; + g_hash_table_iter_init(&iter, audiobridge->participants); + while(g_hash_table_iter_next(&iter, NULL, &value)) { + janus_audiobridge_participant *p = value; + JANUS_LOG(LOG_VERB, "Notifying participant %s (%s)\n", p->user_id_str, p->display ? p->display : "??"); + int ret = gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, event, NULL); + JANUS_LOG(LOG_VERB, " >> %d (%s)\n", ret, janus_get_api_error(ret)); + } + json_decref(event); + /* Also notify event handlers */ + if(notify_events && gateway->events_is_enabled()) { + json_t *info = json_object(); + json_object_set_new(info, "event", json_string("kicked")); + json_object_set_new(info, "room", string_ids ? json_string(room_id_str) : json_integer(room_id)); + json_object_set_new(info, "id", string_ids ? json_string(user_id_str) : json_integer(user_id)); + gateway->notify_event(&janus_audiobridge_plugin, session ? session->handle : NULL, info); + } + /* Tell the core to tear down the PeerConnection, hangup_media will do the rest */ + if(participant && participant->session) + gateway->close_pc(participant->session->handle); + JANUS_LOG(LOG_VERB, "Kicked user %s from room %s\n", user_id_str, room_id_str); + } + /* Prepare response */ + response = json_object(); + json_object_set_new(response, "audiobridge", json_string("success")); + /* Done */ + janus_mutex_unlock(&audiobridge->mutex); + janus_refcount_decrease(&audiobridge->ref); + goto prepare_response; } else if(!strcasecmp(request_text, "listparticipants")) { /* List all participants in a room */ if(!string_ids) { diff --git a/src/plugins/janus_streaming.c b/src/plugins/janus_streaming.c index cf1e4a4a1d..6ddf0ba264 100644 --- a/src/plugins/janus_streaming.c +++ b/src/plugins/janus_streaming.c @@ -464,7 +464,7 @@ multistream-test: { "new_description" : "", "new_metadata" : "", "new_secret" : "", - "new_pin" : "", + "new_pin" : "", "new_is_private" : , "permanent" : } @@ -548,6 +548,26 @@ multistream-test: { { "streaming" : "ok" } +\endverbatim + * + * You can kick all viewers from a mountpoint using the \c kick_all request. Notice + * that this only removes all viewers, but does not prevent them from starting to watch + * the mountpoint again. The \c kick_all request has to be formatted as follows: + * +\verbatim +{ + "request" : "kick_all", + "id" : , + "secret" : "", +} +\endverbatim + * + * If successful, a generic \c ok is returned: + * +\verbatim +{ + "streaming" : "ok", +} \endverbatim * * Finally, you can record a mountpoint to the internal Janus .mjr format @@ -4222,10 +4242,14 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi mp->secret = new_secret; g_free(old_secret); } - if(pin && strlen(json_string_value(pin)) > 0) { + if(pin) { char *old_pin = mp->pin; - char *new_pin = g_strdup(json_string_value(pin)); - mp->pin = new_pin; + if(strlen(json_string_value(pin)) > 0) { + char *new_pin = g_strdup(json_string_value(pin)); + mp->pin = new_pin; + } else { + mp->pin = NULL; + } g_free(old_pin); } if(save) { @@ -4402,6 +4426,117 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi /* Done */ JANUS_LOG(LOG_VERB, "Streaming mountpoint edited\n"); goto prepare_response; + } else if(!strcasecmp(request_text, "kick_all")) { + if(!string_ids) { + JANUS_VALIDATE_JSON_OBJECT(root, id_parameters, + error_code, error_cause, TRUE, + JANUS_STREAMING_ERROR_MISSING_ELEMENT, JANUS_STREAMING_ERROR_INVALID_ELEMENT); + } else { + JANUS_VALIDATE_JSON_OBJECT(root, idstr_parameters, + error_code, error_cause, TRUE, + JANUS_STREAMING_ERROR_MISSING_ELEMENT, JANUS_STREAMING_ERROR_INVALID_ELEMENT); + } + if(error_code != 0) + goto prepare_response; + json_t *id = json_object_get(root, "id"); + guint64 id_value = 0; + char id_num[30], *id_value_str = NULL; + if(!string_ids) { + id_value = json_integer_value(id); + g_snprintf(id_num, sizeof(id_num), "%"SCNu64, id_value); + id_value_str = id_num; + } else { + id_value_str = (char *)json_string_value(id); + } + janus_mutex_lock(&mountpoints_mutex); + janus_streaming_mountpoint *mp = g_hash_table_lookup(mountpoints, + string_ids ? (gpointer)id_value_str : (gpointer)&id_value); + if(mp == NULL) { + janus_mutex_unlock(&mountpoints_mutex); + JANUS_LOG(LOG_VERB, "No such mountpoint/stream %s\n", id_value_str); + error_code = JANUS_STREAMING_ERROR_NO_SUCH_MOUNTPOINT; + g_snprintf(error_cause, 512, "No such mountpoint/stream %s", id_value_str); + goto prepare_response; + } + janus_refcount_increase(&mp->ref); + /* A secret may be required for this action */ + JANUS_CHECK_SECRET(mp->secret, root, "secret", error_code, error_cause, + JANUS_STREAMING_ERROR_MISSING_ELEMENT, JANUS_STREAMING_ERROR_INVALID_ELEMENT, JANUS_STREAMING_ERROR_UNAUTHORIZED); + if(error_code != 0) { + janus_refcount_decrease(&mp->ref); + janus_mutex_unlock(&mountpoints_mutex); + goto prepare_response; + } + JANUS_LOG(LOG_VERB, "Request to kick all viewers from mountpoint/stream %s\n", id_value_str); + janus_mutex_lock(&mp->mutex); + GList *viewer = g_list_first(mp->viewers); + /* Prepare JSON event */ + json_t *event = json_object(); + json_object_set_new(event, "streaming", json_string("event")); + json_t *result = json_object(); + json_object_set_new(result, "status", json_string("kicked")); + json_object_set_new(event, "result", result); + while(viewer) { + janus_streaming_session *s = (janus_streaming_session *)viewer->data; + if(s == NULL) { + mp->viewers = g_list_remove_all(mp->viewers, s); + viewer = g_list_first(mp->viewers); + continue; + } + janus_mutex_lock(&s->mutex); + if(s->mountpoint != mp) { + mp->viewers = g_list_remove_all(mp->viewers, s); + viewer = g_list_first(mp->viewers); + janus_mutex_unlock(&s->mutex); + continue; + } + g_atomic_int_set(&s->stopping, 1); + g_atomic_int_set(&s->started, 0); + g_atomic_int_set(&s->paused, 0); + s->mountpoint = NULL; + /* Tell the core to tear down the PeerConnection, hangup_media will do the rest */ + gateway->push_event(s->handle, &janus_streaming_plugin, NULL, event, NULL); + gateway->close_pc(s->handle); + janus_refcount_decrease(&s->ref); + janus_refcount_decrease(&mp->ref); + if(mp->streaming_source == janus_streaming_source_rtp) { + /* Remove the viewer from the helper threads too, if any */ + if(mp->helper_threads > 0) { + GList *l = mp->threads; + while(l) { + janus_streaming_helper *ht = (janus_streaming_helper *)l->data; + janus_mutex_lock(&ht->mutex); + if(g_list_find(ht->viewers, s) != NULL) { + ht->num_viewers--; + ht->viewers = g_list_remove_all(ht->viewers, s); + janus_mutex_unlock(&ht->mutex); + JANUS_LOG(LOG_VERB, "Removing viewer from helper thread #%d (destroy)\n", ht->id); + break; + } + janus_mutex_unlock(&ht->mutex); + l = l->next; + } + } + } + mp->viewers = g_list_remove_all(mp->viewers, s); + viewer = g_list_first(mp->viewers); + janus_mutex_unlock(&s->mutex); + } + json_decref(event); + janus_mutex_unlock(&mp->mutex); + janus_refcount_decrease(&mp->ref); + /* Also notify event handlers */ + if(notify_events && gateway->events_is_enabled()) { + json_t *info = json_object(); + json_object_set_new(info, "event", json_string("kicked_all")); + json_object_set_new(info, "id", string_ids ? json_string(id_value_str) : json_integer(id_value)); + gateway->notify_event(&janus_streaming_plugin, session ? session->handle : NULL, info); + } + janus_mutex_unlock(&mountpoints_mutex); + /* Send info back */ + response = json_object(); + json_object_set_new(response, "streaming", json_string("ok")); + goto prepare_response; } else if(!strcasecmp(request_text, "destroy")) { /* Get rid of an existing stream (notice this doesn't remove it from the config file, though) */ JANUS_VALIDATE_JSON_OBJECT(root, destroy_parameters, From 1095511050eba1c928d3715dfed9fb8f507061d8 Mon Sep 17 00:00:00 2001 From: Mikael Nousiainen Date: Thu, 12 May 2022 23:07:36 +0300 Subject: [PATCH 2/5] Notify each audiobridge user only once of kick_all request --- src/plugins/janus_audiobridge.c | 16 +++++----------- src/plugins/janus_streaming.c | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/plugins/janus_audiobridge.c b/src/plugins/janus_audiobridge.c index 04b8e853af..ebd4e6d64e 100644 --- a/src/plugins/janus_audiobridge.c +++ b/src/plugins/janus_audiobridge.c @@ -4508,21 +4508,15 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s json_t *event = json_object(); json_object_set_new(event, "audiobridge", json_string("event")); json_object_set_new(event, "room", string_ids ? json_string(room_id_str) : json_integer(room_id)); - json_object_set_new(event, "kicked", string_ids ? json_string(user_id_str) : json_integer(user_id)); - GHashTableIter iter; - gpointer value; - g_hash_table_iter_init(&iter, audiobridge->participants); - while(g_hash_table_iter_next(&iter, NULL, &value)) { - janus_audiobridge_participant *p = value; - JANUS_LOG(LOG_VERB, "Notifying participant %s (%s)\n", p->user_id_str, p->display ? p->display : "??"); - int ret = gateway->push_event(p->session->handle, &janus_audiobridge_plugin, NULL, event, NULL); - JANUS_LOG(LOG_VERB, " >> %d (%s)\n", ret, janus_get_api_error(ret)); - } + json_object_set_new(event, "kicked_all", string_ids ? json_string(user_id_str) : json_integer(user_id)); + JANUS_LOG(LOG_VERB, "Notifying participant %s (%s)\n", participant->user_id_str, participant->display ? participant->display : "??"); + int ret = gateway->push_event(participant->session->handle, &janus_audiobridge_plugin, NULL, event, NULL); + JANUS_LOG(LOG_VERB, " >> %d (%s)\n", ret, janus_get_api_error(ret)); json_decref(event); /* Also notify event handlers */ if(notify_events && gateway->events_is_enabled()) { json_t *info = json_object(); - json_object_set_new(info, "event", json_string("kicked")); + json_object_set_new(info, "event", json_string("kicked_all")); json_object_set_new(info, "room", string_ids ? json_string(room_id_str) : json_integer(room_id)); json_object_set_new(info, "id", string_ids ? json_string(user_id_str) : json_integer(user_id)); gateway->notify_event(&janus_audiobridge_plugin, session ? session->handle : NULL, info); diff --git a/src/plugins/janus_streaming.c b/src/plugins/janus_streaming.c index 709cfb899a..4200811422 100644 --- a/src/plugins/janus_streaming.c +++ b/src/plugins/janus_streaming.c @@ -4476,7 +4476,7 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi json_t *event = json_object(); json_object_set_new(event, "streaming", json_string("event")); json_t *result = json_object(); - json_object_set_new(result, "status", json_string("kicked")); + json_object_set_new(result, "status", json_string("kicked_all")); json_object_set_new(event, "result", result); while(viewer) { janus_streaming_session *s = (janus_streaming_session *)viewer->data; From dcc4e4b044000f4d3c3213066574557a66dbe53e Mon Sep 17 00:00:00 2001 From: Mikael Nousiainen Date: Fri, 13 May 2022 18:19:06 +0300 Subject: [PATCH 3/5] Add note about kick_all compatibility with mountpoint types --- src/plugins/janus_streaming.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/janus_streaming.c b/src/plugins/janus_streaming.c index 4200811422..202bc874cd 100644 --- a/src/plugins/janus_streaming.c +++ b/src/plugins/janus_streaming.c @@ -552,7 +552,8 @@ multistream-test: { * * You can kick all viewers from a mountpoint using the \c kick_all request. Notice * that this only removes all viewers, but does not prevent them from starting to watch - * the mountpoint again. The \c kick_all request has to be formatted as follows: + * the mountpoint again. Please note this request works with all mountpoint types, + * except for on-demand streaming. The \c kick_all request has to be formatted as follows: * \verbatim { @@ -4429,6 +4430,8 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi JANUS_LOG(LOG_VERB, "Streaming mountpoint edited\n"); goto prepare_response; } else if(!strcasecmp(request_text, "kick_all")) { + /* Note the kick_all request works with all mountpoint types except for on-demand streaming, + * because each on-demand viewer has their own thread and their own playback context. */ if(!string_ids) { JANUS_VALIDATE_JSON_OBJECT(root, id_parameters, error_code, error_cause, TRUE, From 7486b770c10583ca723fc2a9ca10e4ce224b23c5 Mon Sep 17 00:00:00 2001 From: Mikael Nousiainen Date: Thu, 19 May 2022 10:27:55 +0300 Subject: [PATCH 4/5] PR review --- src/plugins/janus_audiobridge.c | 6 +++--- src/plugins/janus_streaming.c | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/plugins/janus_audiobridge.c b/src/plugins/janus_audiobridge.c index ebd4e6d64e..03a86a13f9 100644 --- a/src/plugins/janus_audiobridge.c +++ b/src/plugins/janus_audiobridge.c @@ -3847,7 +3847,7 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s janus_mutex_unlock(&participant->rec_mutex); } } - } + } janus_mutex_unlock(&audiobridge->mutex); janus_refcount_decrease(&audiobridge->ref); response = json_object(); @@ -4376,8 +4376,8 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s goto prepare_response; } janus_refcount_increase(&audiobridge->ref); - janus_mutex_lock(&audiobridge->mutex); janus_mutex_unlock(&rooms_mutex); + 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); @@ -4478,8 +4478,8 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s goto prepare_response; } janus_refcount_increase(&audiobridge->ref); - janus_mutex_lock(&audiobridge->mutex); janus_mutex_unlock(&rooms_mutex); + 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); diff --git a/src/plugins/janus_streaming.c b/src/plugins/janus_streaming.c index 202bc874cd..9a38bb1f95 100644 --- a/src/plugins/janus_streaming.c +++ b/src/plugins/janus_streaming.c @@ -563,11 +563,11 @@ multistream-test: { } \endverbatim * - * If successful, a generic \c ok is returned: + * If successful, a \c kicked_all response is returned: * \verbatim { - "streaming" : "ok", + "streaming" : "kicked_all", } \endverbatim * @@ -4488,22 +4488,21 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi viewer = g_list_first(mp->viewers); continue; } - janus_mutex_lock(&s->mutex); + janus_mutex_lock(&s->mutex); if(s->mountpoint != mp) { mp->viewers = g_list_remove_all(mp->viewers, s); viewer = g_list_first(mp->viewers); - janus_mutex_unlock(&s->mutex); + janus_mutex_unlock(&s->mutex); continue; } g_atomic_int_set(&s->stopping, 1); g_atomic_int_set(&s->started, 0); g_atomic_int_set(&s->paused, 0); s->mountpoint = NULL; + janus_mutex_unlock(&s->mutex); /* Tell the core to tear down the PeerConnection, hangup_media will do the rest */ gateway->push_event(s->handle, &janus_streaming_plugin, NULL, event, NULL); gateway->close_pc(s->handle); - janus_refcount_decrease(&s->ref); - janus_refcount_decrease(&mp->ref); if(mp->streaming_source == janus_streaming_source_rtp) { /* Remove the viewer from the helper threads too, if any */ if(mp->helper_threads > 0) { @@ -4525,7 +4524,8 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi } mp->viewers = g_list_remove_all(mp->viewers, s); viewer = g_list_first(mp->viewers); - janus_mutex_unlock(&s->mutex); + janus_refcount_decrease(&s->ref); + janus_refcount_decrease(&mp->ref); } json_decref(event); janus_mutex_unlock(&mp->mutex); @@ -4540,7 +4540,7 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi janus_mutex_unlock(&mountpoints_mutex); /* Send info back */ response = json_object(); - json_object_set_new(response, "streaming", json_string("ok")); + json_object_set_new(response, "streaming", json_string("kicked_all")); goto prepare_response; } else if(!strcasecmp(request_text, "destroy")) { /* Get rid of an existing stream (notice this doesn't remove it from the config file, though) */ @@ -4631,8 +4631,6 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi /* Tell the core to tear down the PeerConnection, hangup_media will do the rest */ gateway->push_event(session->handle, &janus_streaming_plugin, NULL, event, NULL); gateway->close_pc(session->handle); - janus_refcount_decrease(&s->ref); - janus_refcount_decrease(&mp->ref); if(mp->streaming_source == janus_streaming_source_rtp) { /* Remove the viewer from the helper threads too, if any */ if(mp->helper_threads > 0) { @@ -4655,6 +4653,8 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi mp->viewers = g_list_remove_all(mp->viewers, s); viewer = g_list_first(mp->viewers); janus_mutex_unlock(&session->mutex); + janus_refcount_decrease(&s->ref); + janus_refcount_decrease(&mp->ref); } json_decref(event); janus_mutex_unlock(&mp->mutex); From 85d0d70e2d5cd93ab9f0254854ebccffa7ee4a16 Mon Sep 17 00:00:00 2001 From: Mikael Nousiainen Date: Wed, 8 Jun 2022 10:27:10 +0300 Subject: [PATCH 5/5] Fix mutex --- src/plugins/janus_streaming.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/janus_streaming.c b/src/plugins/janus_streaming.c index ad12e21243..d012fcccc7 100644 --- a/src/plugins/janus_streaming.c +++ b/src/plugins/janus_streaming.c @@ -4652,7 +4652,7 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi } mp->viewers = g_list_remove_all(mp->viewers, s); viewer = g_list_first(mp->viewers); - janus_mutex_unlock(&session->mutex); + janus_mutex_unlock(&s->mutex); janus_refcount_decrease(&s->ref); janus_refcount_decrease(&mp->ref); }