[Pkg-voip-commits] [janus] 219/282: Use active sessions lookup in every plugin (excluding videocall). Make a synchronous hangup_media in streaming and recordplay.

Jonas Smedegaard dr at jones.dk
Wed Dec 20 21:53:43 UTC 2017


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

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

commit 91907bbec4c422fddac1943a63bd1765be57eff7
Author: Alessandro Toppi <atoppi at meetecho.com>
Date:   Wed Nov 29 18:59:51 2017 +0100

    Use active sessions lookup in every plugin (excluding videocall). Make a synchronous hangup_media in streaming and recordplay.
---
 plugins/janus_audiobridge.c |  67 +++++++++++-----
 plugins/janus_echotest.c    |  59 ++++++++++----
 plugins/janus_nosip.c       |  47 ++++++++---
 plugins/janus_recordplay.c  | 190 +++++++++++++++++++++++++-------------------
 plugins/janus_sip.c         |  49 +++++++++---
 plugins/janus_sipre.c       |  47 ++++++++---
 plugins/janus_streaming.c   |  84 +++++++++-----------
 plugins/janus_textroom.c    |  54 +++++++++----
 plugins/janus_videoroom.c   |  25 +++---
 plugins/janus_voicemail.c   |  45 ++++++++---
 10 files changed, 428 insertions(+), 239 deletions(-)

diff --git a/plugins/janus_audiobridge.c b/plugins/janus_audiobridge.c
index 97267dd..9f140d5 100644
--- a/plugins/janus_audiobridge.c
+++ b/plugins/janus_audiobridge.c
@@ -747,6 +747,7 @@ static void *janus_audiobridge_handler(void *data);
 static void janus_audiobridge_relay_rtp_packet(gpointer data, gpointer user_data);
 static void *janus_audiobridge_mixer_thread(void *data);
 static void *janus_audiobridge_participant_thread(void *data);
+static void janus_audiobridge_hangup_media_internal(janus_plugin_session *handle);
 
 typedef struct janus_audiobridge_message {
 	janus_plugin_session *handle;
@@ -1418,6 +1419,14 @@ const char *janus_audiobridge_get_package(void) {
 	return JANUS_AUDIOBRIDGE_PACKAGE;
 }
 
+static janus_audiobridge_session *janus_audiobridge_lookup_session(janus_plugin_session *handle) {
+	janus_audiobridge_session *session = NULL;
+	if (g_hash_table_contains(sessions,handle)) {
+		session = (janus_audiobridge_session *)handle->plugin_handle;
+	}
+	return session;
+}
+
 void janus_audiobridge_create_session(janus_plugin_session *handle, int *error) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		*error = -1;
@@ -1442,18 +1451,19 @@ void janus_audiobridge_destroy_session(janus_plugin_session *handle, int *error)
 		*error = -1;
 		return;
 	}	
-	janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle; 
+	janus_mutex_lock(&sessions_mutex);
+	janus_audiobridge_session *session = janus_audiobridge_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No AudioBridge session associated with this handle...\n");
 		*error = -2;
 		return;
 	}
-	JANUS_LOG(LOG_VERB, "Removing AudioBridge session...\n");
-	janus_mutex_lock(&sessions_mutex);
 	if(!session->destroyed) {
-		g_hash_table_remove(sessions, handle);
-		janus_audiobridge_hangup_media(handle);
+		JANUS_LOG(LOG_VERB, "Removing AudioBridge session...\n");
+		janus_audiobridge_hangup_media_internal(handle);
 		session->destroyed = janus_get_monotonic_time();
+		g_hash_table_remove(sessions, handle);
 		/* Cleaning up and removing the session is done in a lazy way */
 		old_sessions = g_list_append(old_sessions, session);
 	}
@@ -1481,8 +1491,10 @@ json_t *janus_audiobridge_query_session(janus_plugin_session *handle) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		return NULL;
 	}	
-	janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_audiobridge_session *session = janus_audiobridge_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return NULL;
 	}
@@ -1520,6 +1532,7 @@ json_t *janus_audiobridge_query_session(janus_plugin_session *handle) {
 	}
 	json_object_set_new(info, "started", session->started ? json_true() : json_false());
 	json_object_set_new(info, "destroyed", json_integer(session->destroyed));
+	janus_mutex_unlock(&sessions_mutex);
 	return info;
 }
 
@@ -1533,6 +1546,8 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 	json_t *root = message;
 	json_t *response = NULL;
 	
+	janus_mutex_lock(&sessions_mutex);
+
 	if(message == NULL) {
 		JANUS_LOG(LOG_ERR, "No message??\n");
 		error_code = JANUS_AUDIOBRIDGE_ERROR_NO_MESSAGE;
@@ -1540,7 +1555,7 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 		goto plugin_response;
 	}
 
-	janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;	
+	janus_audiobridge_session *session = janus_audiobridge_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		error_code = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
@@ -2460,6 +2475,7 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 	} else if(!strcasecmp(request_text, "join") || !strcasecmp(request_text, "configure")
 			|| !strcasecmp(request_text, "changeroom") || !strcasecmp(request_text, "leave")) {
 		/* These messages are handled asynchronously */
+		janus_mutex_unlock(&sessions_mutex);
 		janus_audiobridge_message *msg = g_malloc0(sizeof(janus_audiobridge_message));
 		msg->handle = handle;
 		msg->transaction = transaction;
@@ -2477,6 +2493,7 @@ struct janus_plugin_result *janus_audiobridge_handle_message(janus_plugin_sessio
 
 plugin_response:
 		{
+			janus_mutex_unlock(&sessions_mutex);
 			if(error_code == 0 && !response) {
 				error_code = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
 				g_snprintf(error_cause, 512, "Invalid response");
@@ -2504,25 +2521,32 @@ void janus_audiobridge_setup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;	
+	janus_mutex_lock(&sessions_mutex);
+	janus_audiobridge_session *session = janus_audiobridge_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
-	if(!participant)
+	if(!participant) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	g_atomic_int_set(&session->hangingup, 0);
 	/* FIXME Only send this peer the audio mix when we get this event */
 	session->started = TRUE;
+	janus_mutex_unlock(&sessions_mutex);
 }
 
 void janus_audiobridge_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len) {
 	if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;	
+	janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;
 	if(!session || session->destroyed || session->stopping || !session->participant)
 		return;
 	janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
@@ -2672,19 +2696,27 @@ void janus_audiobridge_incoming_rtcp(janus_plugin_session *handle, int video, ch
 }
 
 void janus_audiobridge_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_audiobridge_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_audiobridge_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_audiobridge_session *session = (janus_audiobridge_session *)handle->plugin_handle;
+	janus_audiobridge_session *session = janus_audiobridge_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
 	session->started = FALSE;
-	if(session->destroyed || !session->participant)
+	if(session->destroyed || !session->participant) {
 		return;
-	if(g_atomic_int_add(&session->hangingup, 1))
+	}
+	if(g_atomic_int_add(&session->hangingup, 1)) {
 		return;
+	}
 	/* Get rid of participant */
 	janus_audiobridge_participant *participant = (janus_audiobridge_participant *)session->participant;
 	janus_mutex_lock(&rooms_mutex);
@@ -2788,11 +2820,9 @@ static void *janus_audiobridge_handler(void *data) {
 			janus_audiobridge_message_free(msg);
 			continue;
 		}
-		janus_audiobridge_session *session = NULL;
+		JANUS_LOG(LOG_WARN, ">>>> AAAA\n");
 		janus_mutex_lock(&sessions_mutex);
-		if(g_hash_table_lookup(sessions, msg->handle) != NULL) {
-			session = (janus_audiobridge_session *)msg->handle->plugin_handle;
-		}
+		janus_audiobridge_session *session = janus_audiobridge_lookup_session(msg->handle);
 		if(!session) {
 			janus_mutex_unlock(&sessions_mutex);
 			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
@@ -2804,6 +2834,7 @@ static void *janus_audiobridge_handler(void *data) {
 			janus_audiobridge_message_free(msg);
 			continue;
 		}
+		JANUS_LOG(LOG_WARN, ">>>> BBBB\n");
 		janus_mutex_unlock(&sessions_mutex);
 		/* Handle request */
 		error_code = 0;
diff --git a/plugins/janus_echotest.c b/plugins/janus_echotest.c
index d33300a..3ff58fe 100644
--- a/plugins/janus_echotest.c
+++ b/plugins/janus_echotest.c
@@ -168,6 +168,7 @@ static janus_callbacks *gateway = NULL;
 static GThread *handler_thread;
 static GThread *watchdog;
 static void *janus_echotest_handler(void *data);
+static void janus_echotest_hangup_media_internal(janus_plugin_session *handle);
 
 typedef struct janus_echotest_message {
 	janus_plugin_session *handle;
@@ -385,6 +386,14 @@ const char *janus_echotest_get_package(void) {
 	return JANUS_ECHOTEST_PACKAGE;
 }
 
+static janus_echotest_session *janus_echotest_lookup_session(janus_plugin_session *handle) {
+	janus_echotest_session *session = NULL;
+	if (g_hash_table_contains(sessions,handle)) {
+		session = (janus_echotest_session *)handle->plugin_handle;
+	}
+	return session;
+}
+
 void janus_echotest_create_session(janus_plugin_session *handle, int *error) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		*error = -1;
@@ -425,15 +434,17 @@ void janus_echotest_destroy_session(janus_plugin_session *handle, int *error) {
 		*error = -1;
 		return;
 	}	
-	janus_echotest_session *session = (janus_echotest_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_echotest_session *session = janus_echotest_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		*error = -2;
 		return;
 	}
-	JANUS_LOG(LOG_VERB, "Removing Echo Test session...\n");
-	janus_mutex_lock(&sessions_mutex);
 	if(!session->destroyed) {
+		JANUS_LOG(LOG_VERB, "Removing Echo Test session...\n");
+		janus_echotest_hangup_media_internal(handle);
 		session->destroyed = janus_get_monotonic_time();
 		g_hash_table_remove(sessions, handle);
 		/* Cleaning up and removing the session is done in a lazy way */
@@ -447,8 +458,10 @@ json_t *janus_echotest_query_session(janus_plugin_session *handle) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		return NULL;
 	}	
-	janus_echotest_session *session = (janus_echotest_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_echotest_session *session = janus_echotest_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return NULL;
 	}
@@ -481,6 +494,7 @@ json_t *janus_echotest_query_session(janus_plugin_session *handle) {
 	}
 	json_object_set_new(info, "slowlink_count", json_integer(session->slowlink_count));
 	json_object_set_new(info, "destroyed", json_integer(session->destroyed));
+	janus_mutex_unlock(&sessions_mutex);
 	return info;
 }
 
@@ -505,14 +519,19 @@ void janus_echotest_setup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_echotest_session *session = (janus_echotest_session *)handle->plugin_handle;	
+	janus_mutex_lock(&sessions_mutex);
+	janus_echotest_session *session = janus_echotest_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	g_atomic_int_set(&session->hangingup, 0);
+	janus_mutex_unlock(&sessions_mutex);
 	/* We really don't care, as we only send RTP/RTCP we get in the first place back anyway */
 }
 
@@ -728,13 +747,17 @@ void janus_echotest_slow_link(janus_plugin_session *handle, int uplink, int vide
 	/* The core is informing us that our peer got or sent too many NACKs, are we pushing media too hard? */
 	if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_echotest_session *session = (janus_echotest_session *)handle->plugin_handle;	
+	janus_mutex_lock(&sessions_mutex);
+	janus_echotest_session *session = janus_echotest_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	session->slowlink_count++;
 	if(uplink && !video && !session->audio_active) {
 		/* We're not relaying audio and the peer is expecting it, so NACKs are normal */
@@ -773,21 +796,30 @@ void janus_echotest_slow_link(janus_plugin_session *handle, int uplink, int vide
 			json_decref(event);
 		}
 	}
+	janus_mutex_unlock(&sessions_mutex);
 }
 
 void janus_echotest_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_echotest_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_echotest_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_echotest_session *session = (janus_echotest_session *)handle->plugin_handle;
+	janus_echotest_session *session = janus_echotest_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
 		return;
-	if(g_atomic_int_add(&session->hangingup, 1))
+	}
+	if(g_atomic_int_add(&session->hangingup, 1)) {
 		return;
+	}
 	/* Send an event to the browser and tell it's over */
 	json_t *event = json_object();
 	json_object_set_new(event, "echotest", json_string("event"));
@@ -853,11 +885,8 @@ static void *janus_echotest_handler(void *data) {
 			janus_echotest_message_free(msg);
 			continue;
 		}
-		janus_echotest_session *session = NULL;
 		janus_mutex_lock(&sessions_mutex);
-		if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
-			session = (janus_echotest_session *)msg->handle->plugin_handle;
-		}
+		janus_echotest_session *session = janus_echotest_lookup_session(msg->handle);
 		if(!session) {
 			janus_mutex_unlock(&sessions_mutex);
 			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
diff --git a/plugins/janus_nosip.c b/plugins/janus_nosip.c
index 09230c9..01128d7 100644
--- a/plugins/janus_nosip.c
+++ b/plugins/janus_nosip.c
@@ -165,6 +165,7 @@ static uint16_t rtp_range_max = 60000;
 static GThread *handler_thread;
 static GThread *watchdog;
 static void *janus_nosip_handler(void *data);
+static void janus_nosip_hangup_media_internal(janus_plugin_session *handle);
 
 typedef struct janus_nosip_message {
 	janus_plugin_session *handle;
@@ -587,6 +588,14 @@ const char *janus_nosip_get_package(void) {
 	return JANUS_NOSIP_PACKAGE;
 }
 
+static janus_nosip_session *janus_nosip_lookup_session(janus_plugin_session *handle) {
+	janus_nosip_session *session = NULL;
+	if (g_hash_table_contains(sessions,handle)) {
+		session = (janus_nosip_session *)handle->plugin_handle;
+	}
+	return session;
+}
+
 void janus_nosip_create_session(janus_plugin_session *handle, int *error) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		*error = -1;
@@ -652,18 +661,19 @@ void janus_nosip_destroy_session(janus_plugin_session *handle, int *error) {
 		*error = -1;
 		return;
 	}
-	janus_nosip_session *session = (janus_nosip_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_nosip_session *session = janus_nosip_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No NoSIP session associated with this handle...\n");
 		*error = -2;
 		return;
 	}
-	janus_mutex_lock(&sessions_mutex);
 	if(!session->destroyed) {
-		g_hash_table_remove(sessions, handle);
-		janus_nosip_hangup_media(handle);
-		session->destroyed = janus_get_monotonic_time();
 		JANUS_LOG(LOG_VERB, "Destroying NoSIP session (%p)...\n", session);
+		janus_nosip_hangup_media_internal(handle);
+		session->destroyed = janus_get_monotonic_time();
+		g_hash_table_remove(sessions, handle);
 		/* Cleaning up and removing the session is done in a lazy way */
 		old_sessions = g_list_append(old_sessions, session);
 	}
@@ -675,8 +685,10 @@ json_t *janus_nosip_query_session(janus_plugin_session *handle) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		return NULL;
 	}
-	janus_nosip_session *session = (janus_nosip_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_nosip_session *session = janus_nosip_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return NULL;
 	}
@@ -700,6 +712,7 @@ json_t *janus_nosip_query_session(janus_plugin_session *handle) {
 		json_object_set_new(info, "recording", recording);
 	}
 	json_object_set_new(info, "destroyed", json_integer(session->destroyed));
+	janus_mutex_unlock(&sessions_mutex);
 	return info;
 }
 
@@ -721,14 +734,19 @@ void janus_nosip_setup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_nosip_session *session = (janus_nosip_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_nosip_session *session = janus_nosip_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	g_atomic_int_set(&session->hangingup, 0);
+	janus_mutex_unlock(&sessions_mutex);
 }
 
 void janus_nosip_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len) {
@@ -850,10 +868,16 @@ void janus_nosip_incoming_rtcp(janus_plugin_session *handle, int video, char *bu
 }
 
 void janus_nosip_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_nosip_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_nosip_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_nosip_session *session = (janus_nosip_session *)handle->plugin_handle;
+	janus_nosip_session *session = janus_nosip_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
@@ -916,11 +940,8 @@ static void *janus_nosip_handler(void *data) {
 			janus_nosip_message_free(msg);
 			continue;
 		}
-		janus_nosip_session *session = NULL;
 		janus_mutex_lock(&sessions_mutex);
-		if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
-			session = (janus_nosip_session *)msg->handle->plugin_handle;
-		}
+		janus_nosip_session *session = janus_nosip_lookup_session(msg->handle);
 		if(!session) {
 			janus_mutex_unlock(&sessions_mutex);
 			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
diff --git a/plugins/janus_recordplay.c b/plugins/janus_recordplay.c
index 18634fe..c5787ed 100644
--- a/plugins/janus_recordplay.c
+++ b/plugins/janus_recordplay.c
@@ -347,6 +347,7 @@ static janus_callbacks *gateway = NULL;
 static GThread *handler_thread;
 static GThread *watchdog;
 static void *janus_recordplay_handler(void *data);
+static void janus_recordplay_hangup_media_internal(janus_plugin_session *handle);
 
 typedef struct janus_recordplay_message {
 	janus_plugin_session *handle;
@@ -791,6 +792,14 @@ const char *janus_recordplay_get_package(void) {
 	return JANUS_RECORDPLAY_PACKAGE;
 }
 
+static janus_recordplay_session *janus_recordplay_lookup_session(janus_plugin_session *handle) {
+	janus_recordplay_session *session = NULL;
+	if (g_hash_table_contains(sessions,handle)) {
+		session = (janus_recordplay_session *)handle->plugin_handle;
+	}
+	return session;
+}
+
 void janus_recordplay_create_session(janus_plugin_session *handle, int *error) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		*error = -1;
@@ -825,16 +834,17 @@ void janus_recordplay_destroy_session(janus_plugin_session *handle, int *error)
 		*error = -1;
 		return;
 	}	
-	janus_recordplay_session *session = (janus_recordplay_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_recordplay_session *session = janus_recordplay_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No Record&Play session associated with this handle...\n");
 		*error = -2;
 		return;
 	}
-	janus_mutex_lock(&sessions_mutex);
 	if(!session->destroyed) {
 		JANUS_LOG(LOG_VERB, "Removing Record&Play session...\n");
-		janus_recordplay_hangup_media(handle);
+		janus_recordplay_hangup_media_internal(handle);
 		session->destroyed = janus_get_monotonic_time();
 		g_hash_table_remove(sessions, handle);
 		/* Cleaning up and removing the session is done in a lazy way */
@@ -848,8 +858,10 @@ json_t *janus_recordplay_query_session(janus_plugin_session *handle) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		return NULL;
 	}	
-	janus_recordplay_session *session = (janus_recordplay_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_recordplay_session *session = janus_recordplay_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return NULL;
 	}
@@ -861,6 +873,7 @@ json_t *janus_recordplay_query_session(janus_plugin_session *handle) {
 		json_object_set_new(info, "recording_name", json_string(session->recording->name));
 	}
 	json_object_set_new(info, "destroyed", json_integer(session->destroyed));
+	janus_mutex_unlock(&sessions_mutex);
 	return info;
 }
 
@@ -874,6 +887,8 @@ struct janus_plugin_result *janus_recordplay_handle_message(janus_plugin_session
 	json_t *root = message;
 	json_t *response = NULL;
 	
+	janus_mutex_lock(&sessions_mutex);
+
 	if(message == NULL) {
 		JANUS_LOG(LOG_ERR, "No message??\n");
 		error_code = JANUS_RECORDPLAY_ERROR_NO_MESSAGE;
@@ -881,7 +896,7 @@ struct janus_plugin_result *janus_recordplay_handle_message(janus_plugin_session
 		goto plugin_response;
 	}
 
-	janus_recordplay_session *session = (janus_recordplay_session *)handle->plugin_handle;	
+	janus_recordplay_session *session = janus_recordplay_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		error_code = JANUS_RECORDPLAY_ERROR_UNKNOWN_ERROR;
@@ -974,6 +989,7 @@ struct janus_plugin_result *janus_recordplay_handle_message(janus_plugin_session
 	} else if(!strcasecmp(request_text, "record") || !strcasecmp(request_text, "play")
 			|| !strcasecmp(request_text, "start") || !strcasecmp(request_text, "stop")) {
 		/* These messages are handled asynchronously */
+		janus_mutex_unlock(&sessions_mutex);
 		janus_recordplay_message *msg = g_malloc0(sizeof(janus_recordplay_message));
 		msg->handle = handle;
 		msg->transaction = transaction;
@@ -991,6 +1007,7 @@ struct janus_plugin_result *janus_recordplay_handle_message(janus_plugin_session
 
 plugin_response:
 		{
+			janus_mutex_unlock(&sessions_mutex);
 			if(error_code == 0 && !response) {
 				error_code = JANUS_RECORDPLAY_ERROR_UNKNOWN_ERROR;
 				g_snprintf(error_cause, 512, "Invalid response");
@@ -1018,13 +1035,17 @@ void janus_recordplay_setup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_recordplay_session *session = (janus_recordplay_session *)handle->plugin_handle;	
+	janus_mutex_lock(&sessions_mutex);
+	janus_recordplay_session *session = janus_recordplay_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	g_atomic_int_set(&session->hangingup, 0);
 	/* Take note of the fact that the session is now active */
 	session->active = TRUE;
@@ -1036,6 +1057,7 @@ void janus_recordplay_setup_media(janus_plugin_session *handle) {
 			JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the Record&Play playout thread...\n", error->code, error->message ? error->message : "??");
 		}
 	}
+	janus_mutex_unlock(&sessions_mutex);
 }
 
 void janus_recordplay_send_rtcp_feedback(janus_plugin_session *handle, int video, char *buf, int len) {
@@ -1125,9 +1147,12 @@ void janus_recordplay_slow_link(janus_plugin_session *handle, int uplink, int vi
 	if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized) || !gateway)
 		return;
 
-	janus_recordplay_session *session = (janus_recordplay_session *)handle->plugin_handle;
-	if(!session || session->destroyed)
+	janus_mutex_lock(&sessions_mutex);
+	janus_recordplay_session *session = janus_recordplay_lookup_session(handle);
+	if(!session || session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 
 	json_t *event = json_object();
 	json_object_set_new(event, "recordplay", json_string("event"));
@@ -1139,22 +1164,31 @@ void janus_recordplay_slow_link(janus_plugin_session *handle, int uplink, int vi
 	json_object_set_new(event, "result", result);
 	gateway->push_event(session->handle, &janus_recordplay_plugin, NULL, event, NULL);
 	json_decref(event);
+	janus_mutex_unlock(&sessions_mutex);
 }
 
 void janus_recordplay_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_recordplay_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_recordplay_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_recordplay_session *session = (janus_recordplay_session *)handle->plugin_handle;
+	janus_recordplay_session *session = janus_recordplay_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
 	session->active = FALSE;
-	if(session->destroyed || !session->recorder)
+	if(session->destroyed || !session->recorder) {
 		return;
-	if(g_atomic_int_add(&session->hangingup, 1))
+	}
+	if(g_atomic_int_add(&session->hangingup, 1)) {
 		return;
+	}
 	session->simulcast_ssrc = 0;
 
 	/* Send an event to the browser and tell it's over */
@@ -1165,13 +1199,65 @@ void janus_recordplay_hangup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
 	json_decref(event);
 
-	/* FIXME Simulate a "stop" coming from the browser */
-	janus_recordplay_message *msg = g_malloc0(sizeof(janus_recordplay_message));
-	msg->handle = handle;
-	msg->message = json_pack("{ss}", "request", "stop");
-	msg->transaction = NULL;
-	msg->jsep = NULL;
-	g_async_queue_push(messages, msg);
+	session->active = FALSE;
+	janus_mutex_lock(&session->rec_mutex);
+	if(session->arc) {
+		janus_recorder_close(session->arc);
+		JANUS_LOG(LOG_INFO, "Closed audio recording %s\n", session->arc->filename ? session->arc->filename : "??");
+		janus_recorder_free(session->arc);
+	}
+	session->arc = NULL;
+	if(session->vrc) {
+		janus_recorder_close(session->vrc);
+		JANUS_LOG(LOG_INFO, "Closed video recording %s\n", session->vrc->filename ? session->vrc->filename : "??");
+		janus_recorder_free(session->vrc);
+	}
+	session->vrc = NULL;
+	janus_mutex_unlock(&session->rec_mutex);
+	if(session->recorder) {
+		/* Create a .nfo file for this recording */
+		char nfofile[1024], nfo[1024];
+		g_snprintf(nfofile, 1024, "%s/%"SCNu64".nfo", recordings_path, session->recording->id);
+		FILE *file = fopen(nfofile, "wt");
+		if(file == NULL) {
+			JANUS_LOG(LOG_ERR, "Error creating file %s...\n", nfofile);
+		} else {
+			if(session->recording->arc_file && session->recording->vrc_file) {
+				g_snprintf(nfo, 1024,
+					"[%"SCNu64"]\r\n"
+					"name = %s\r\n"
+					"date = %s\r\n"
+					"audio = %s.mjr\r\n"
+					"video = %s.mjr\r\n",
+						session->recording->id, session->recording->name, session->recording->date,
+						session->recording->arc_file, session->recording->vrc_file);
+			} else if(session->recording->arc_file) {
+				g_snprintf(nfo, 1024,
+					"[%"SCNu64"]\r\n"
+					"name = %s\r\n"
+					"date = %s\r\n"
+					"audio = %s.mjr\r\n",
+						session->recording->id, session->recording->name, session->recording->date,
+						session->recording->arc_file);
+			} else if(session->recording->vrc_file) {
+				g_snprintf(nfo, 1024,
+					"[%"SCNu64"]\r\n"
+					"name = %s\r\n"
+					"date = %s\r\n"
+					"video = %s.mjr\r\n",
+						session->recording->id, session->recording->name, session->recording->date,
+						session->recording->vrc_file);
+			}
+			/* Write to the file now */
+			fwrite(nfo, strlen(nfo), sizeof(char), file);
+			fclose(file);
+			/* Generate the offer */
+			if(janus_recordplay_generate_offer(session->recording) < 0) {
+				JANUS_LOG(LOG_WARN, "Could not generate offer for recording %"SCNu64"...\n", session->recording->id);
+			}
+			session->recording->completed = TRUE;
+		}
+	}
 }
 
 /* Thread to handle incoming messages */
@@ -1191,11 +1277,8 @@ static void *janus_recordplay_handler(void *data) {
 			janus_recordplay_message_free(msg);
 			continue;
 		}
-		janus_recordplay_session *session = NULL;
 		janus_mutex_lock(&sessions_mutex);
-		if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
-			session = (janus_recordplay_session *)msg->handle->plugin_handle;
-		}
+		janus_recordplay_session *session = janus_recordplay_lookup_session(msg->handle);
 		if(!session) {
 			janus_mutex_unlock(&sessions_mutex);
 			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
@@ -1466,65 +1549,8 @@ static void *janus_recordplay_handler(void *data) {
 			}
 		} else if(!strcasecmp(request_text, "stop")) {
 			/* Stop the recording/playout */
-			session->active = FALSE;
-			janus_mutex_lock(&session->rec_mutex);
-			if(session->arc) {
-				janus_recorder_close(session->arc);
-				JANUS_LOG(LOG_INFO, "Closed audio recording %s\n", session->arc->filename ? session->arc->filename : "??");
-				janus_recorder_free(session->arc);
-			}
-			session->arc = NULL;
-			if(session->vrc) {
-				janus_recorder_close(session->vrc);
-				JANUS_LOG(LOG_INFO, "Closed video recording %s\n", session->vrc->filename ? session->vrc->filename : "??");
-				janus_recorder_free(session->vrc);
-			}
-			session->vrc = NULL;
-			janus_mutex_unlock(&session->rec_mutex);
-			if(session->recorder) {
-				/* Create a .nfo file for this recording */
-				char nfofile[1024], nfo[1024];
-				g_snprintf(nfofile, 1024, "%s/%"SCNu64".nfo", recordings_path, session->recording->id);
-				FILE *file = fopen(nfofile, "wt");
-				if(file == NULL) {
-					JANUS_LOG(LOG_ERR, "Error creating file %s...\n", nfofile);
-				} else {
-					if(session->recording->arc_file && session->recording->vrc_file) {
-						g_snprintf(nfo, 1024,
-							"[%"SCNu64"]\r\n"
-							"name = %s\r\n"
-							"date = %s\r\n"
-							"audio = %s.mjr\r\n"
-							"video = %s.mjr\r\n",
-								session->recording->id, session->recording->name, session->recording->date,
-								session->recording->arc_file, session->recording->vrc_file);
-					} else if(session->recording->arc_file) {
-						g_snprintf(nfo, 1024,
-							"[%"SCNu64"]\r\n"
-							"name = %s\r\n"
-							"date = %s\r\n"
-							"audio = %s.mjr\r\n",
-								session->recording->id, session->recording->name, session->recording->date,
-								session->recording->arc_file);
-					} else if(session->recording->vrc_file) {
-						g_snprintf(nfo, 1024,
-							"[%"SCNu64"]\r\n"
-							"name = %s\r\n"
-							"date = %s\r\n"
-							"video = %s.mjr\r\n",
-								session->recording->id, session->recording->name, session->recording->date,
-								session->recording->vrc_file);
-					}
-					/* Write to the file now */
-					fwrite(nfo, strlen(nfo), sizeof(char), file);
-					fclose(file);
-					/* Generate the offer */
-					if(janus_recordplay_generate_offer(session->recording) < 0) {
-						JANUS_LOG(LOG_WARN, "Could not generate offer for recording %"SCNu64"...\n", session->recording->id);
-					}
-					session->recording->completed = TRUE;
-				}
-			}
+			janus_recordplay_hangup_media(session->handle);
+
 			/* Done! */
 			result = json_object();
 			json_object_set_new(result, "status", json_string("stopped"));
diff --git a/plugins/janus_sip.c b/plugins/janus_sip.c
index ad3511f..37bf20d 100644
--- a/plugins/janus_sip.c
+++ b/plugins/janus_sip.c
@@ -208,6 +208,7 @@ static uint16_t rtp_range_max = 60000;
 static GThread *handler_thread;
 static GThread *watchdog;
 static void *janus_sip_handler(void *data);
+static void janus_sip_hangup_media_internal(janus_plugin_session *handle);
 
 typedef struct janus_sip_message {
 	janus_plugin_session *handle;
@@ -980,6 +981,14 @@ const char *janus_sip_get_package(void) {
 	return JANUS_SIP_PACKAGE;
 }
 
+static janus_sip_session *janus_sip_lookup_session(janus_plugin_session *handle) {
+	janus_sip_session *session = NULL;
+	if (g_hash_table_contains(sessions,handle)) {
+		session = (janus_sip_session *)handle->plugin_handle;
+	}
+	return session;
+}
+
 void janus_sip_create_session(janus_plugin_session *handle, int *error) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		*error = -1;
@@ -1067,18 +1076,19 @@ void janus_sip_destroy_session(janus_plugin_session *handle, int *error) {
 		*error = -1;
 		return;
 	}
-	janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_sip_session *session = janus_sip_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No SIP session associated with this handle...\n");
 		*error = -2;
 		return;
 	}
-	janus_mutex_lock(&sessions_mutex);
 	if(!session->destroyed) {
-		g_hash_table_remove(sessions, handle);
-		janus_sip_hangup_media(handle);
-		session->destroyed = janus_get_monotonic_time();
 		JANUS_LOG(LOG_VERB, "Destroying SIP session (%s)...\n", session->account.username ? session->account.username : "unregistered user");
+		janus_sip_hangup_media_internal(handle);
+		session->destroyed = janus_get_monotonic_time();
+		g_hash_table_remove(sessions, handle);
 		if(session->stack != NULL) {
 			/* Shutdown the NUA: this will remove the session later on */
 			nua_shutdown(session->stack->s_nua);
@@ -1095,8 +1105,10 @@ json_t *janus_sip_query_session(janus_plugin_session *handle) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		return NULL;
 	}
-	janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_sip_session *session = janus_sip_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return NULL;
 	}
@@ -1130,6 +1142,7 @@ json_t *janus_sip_query_session(janus_plugin_session *handle) {
 		json_object_set_new(info, "recording", recording);
 	}
 	json_object_set_new(info, "destroyed", json_integer(session->destroyed));
+	janus_mutex_unlock(&sessions_mutex);
 	return info;
 }
 
@@ -1151,14 +1164,19 @@ void janus_sip_setup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_sip_session *session = janus_sip_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	g_atomic_int_set(&session->hangingup, 0);
+	janus_mutex_unlock(&sessions_mutex);
 	/* TODO Only relay RTP/RTCP when we get this event */
 }
 
@@ -1357,10 +1375,16 @@ void janus_sip_incoming_rtcp(janus_plugin_session *handle, int video, char *buf,
 }
 
 void janus_sip_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_sip_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_sip_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
+	janus_sip_session *session = janus_sip_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
@@ -1427,11 +1451,8 @@ static void *janus_sip_handler(void *data) {
 			janus_sip_message_free(msg);
 			continue;
 		}
-		janus_sip_session *session = NULL;
 		janus_mutex_lock(&sessions_mutex);
-		if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
-			session = (janus_sip_session *)msg->handle->plugin_handle;
-		}
+		janus_sip_session *session = janus_sip_lookup_session(msg->handle);
 		if(!session) {
 			janus_mutex_unlock(&sessions_mutex);
 			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
@@ -2656,6 +2677,7 @@ static void *janus_sip_handler(void *data) {
 			goto error;
 		}
 
+		janus_mutex_unlock(&sessions_mutex);
 		/* Prepare JSON event */
 		json_t *event = json_object();
 		json_object_set_new(event, "sip", json_string("event"));
@@ -2669,6 +2691,7 @@ static void *janus_sip_handler(void *data) {
 
 error:
 		{
+			janus_mutex_unlock(&sessions_mutex);
 			/* Prepare JSON error event */
 			json_t *event = json_object();
 			json_object_set_new(event, "sip", json_string("event"));
diff --git a/plugins/janus_sipre.c b/plugins/janus_sipre.c
index 0a83c0d..df4ca0b 100644
--- a/plugins/janus_sipre.c
+++ b/plugins/janus_sipre.c
@@ -206,6 +206,7 @@ static uint16_t rtp_range_max = 60000;
 static GThread *handler_thread;
 static GThread *watchdog;
 static void *janus_sipre_handler(void *data);
+static void janus_sipre_hangup_media_internal(janus_plugin_session *handle);
 
 typedef struct janus_sipre_message {
 	janus_plugin_session *handle;
@@ -1031,6 +1032,14 @@ const char *janus_sipre_get_package(void) {
 	return JANUS_SIPRE_PACKAGE;
 }
 
+static janus_sipre_session *janus_sipre_lookup_session(janus_plugin_session *handle) {
+	janus_sipre_session *session = NULL;
+	if (g_hash_table_contains(sessions,handle)) {
+		session = (janus_sipre_session *)handle->plugin_handle;
+	}
+	return session;
+}
+
 void janus_sipre_create_session(janus_plugin_session *handle, int *error) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		*error = -1;
@@ -1119,18 +1128,19 @@ void janus_sipre_destroy_session(janus_plugin_session *handle, int *error) {
 		*error = -1;
 		return;
 	}
-	janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_sipre_session *session = janus_sipre_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No SIPre session associated with this handle...\n");
 		*error = -2;
 		return;
 	}
-	janus_mutex_lock(&sessions_mutex);
 	if(!session->destroyed) {
-		g_hash_table_remove(sessions, handle);
-		janus_sipre_hangup_media(handle);
-		session->destroyed = janus_get_monotonic_time();
 		JANUS_LOG(LOG_VERB, "Destroying SIPre session (%s)...\n", session->account.username ? session->account.username : "unregistered user");
+		janus_sipre_hangup_media_internal(handle);
+		session->destroyed = janus_get_monotonic_time();
+		g_hash_table_remove(sessions, handle);
 		/* Unregister */
 		mqueue_push(mq, janus_sipre_mqueue_event_do_unregister, janus_sipre_mqueue_payload_create(session, NULL, 0, NULL));
 		/* Close re-related stuff for this SIP session */
@@ -1146,8 +1156,10 @@ json_t *janus_sipre_query_session(janus_plugin_session *handle) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		return NULL;
 	}
-	janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_sipre_session *session = janus_sipre_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return NULL;
 	}
@@ -1180,6 +1192,7 @@ json_t *janus_sipre_query_session(janus_plugin_session *handle) {
 		json_object_set_new(info, "recording", recording);
 	}
 	json_object_set_new(info, "destroyed", json_integer(session->destroyed));
+	janus_mutex_unlock(&sessions_mutex);
 	return info;
 }
 
@@ -1201,14 +1214,19 @@ void janus_sipre_setup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_sipre_session *session = janus_sipre_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	g_atomic_int_set(&session->hangingup, 0);
+	janus_mutex_unlock(&sessions_mutex);
 	/* TODO Only relay RTP/RTCP when we get this event */
 }
 
@@ -1339,10 +1357,16 @@ void janus_sipre_incoming_rtcp(janus_plugin_session *handle, int video, char *bu
 }
 
 void janus_sipre_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_sipre_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_sipre_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
+	janus_sipre_session *session = janus_sipre_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
@@ -1406,11 +1430,8 @@ static void *janus_sipre_handler(void *data) {
 			janus_sipre_message_free(msg);
 			continue;
 		}
-		janus_sipre_session *session = NULL;
 		janus_mutex_lock(&sessions_mutex);
-		if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
-			session = (janus_sipre_session *)msg->handle->plugin_handle;
-		}
+		janus_sipre_session *session = janus_sipre_lookup_session(msg->handle);
 		if(!session) {
 			janus_mutex_unlock(&sessions_mutex);
 			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
diff --git a/plugins/janus_streaming.c b/plugins/janus_streaming.c
index 37d65cf..eab02b8 100644
--- a/plugins/janus_streaming.c
+++ b/plugins/janus_streaming.c
@@ -356,6 +356,7 @@ static void *janus_streaming_ondemand_thread(void *data);
 static void *janus_streaming_filesource_thread(void *data);
 static void janus_streaming_relay_rtp_packet(gpointer data, gpointer user_data);
 static void *janus_streaming_relay_thread(void *data);
+static void janus_streaming_hangup_media_internal(janus_plugin_session *handle);
 
 typedef enum janus_streaming_type {
 	janus_streaming_type_none = 0,
@@ -1243,14 +1244,15 @@ void janus_streaming_destroy_session(janus_plugin_session *handle, int *error) {
 		*error = -2;
 		return;
 	}
-	JANUS_LOG(LOG_VERB, "Removing streaming session...\n");
-	janus_streaming_mountpoint *mp = session->mountpoint;
-	if(mp) {
-		janus_mutex_lock(&mp->mutex);
-		mp->listeners = g_list_remove_all(mp->listeners, session);
-		janus_mutex_unlock(&mp->mutex);
-	}
 	if(!session->destroyed) {
+		JANUS_LOG(LOG_VERB, "Removing streaming session...\n");
+		janus_streaming_mountpoint *mp = session->mountpoint;
+		if(mp) {
+			janus_mutex_lock(&mp->mutex);
+			mp->listeners = g_list_remove_all(mp->listeners, session);
+			janus_mutex_unlock(&mp->mutex);
+		}
+		janus_streaming_hangup_media_internal(handle);
 		session->destroyed = janus_get_monotonic_time();
 		g_hash_table_remove(sessions, handle);
 		/* Cleaning up and removing the session is done in a lazy way */
@@ -2306,6 +2308,7 @@ struct janus_plugin_result *janus_streaming_handle_message(janus_plugin_session
 			|| !strcasecmp(request_text, "pause") || !strcasecmp(request_text, "stop")
 			|| !strcasecmp(request_text, "configure") || !strcasecmp(request_text, "switch")) {
 		/* These messages are handled asynchronously */
+		janus_mutex_unlock(&sessions_mutex);
 		janus_streaming_message *msg = g_malloc0(sizeof(janus_streaming_message));
 		msg->handle = handle;
 		msg->transaction = transaction;
@@ -2313,7 +2316,6 @@ struct janus_plugin_result *janus_streaming_handle_message(janus_plugin_session
 		msg->jsep = jsep;
 
 		g_async_queue_push(messages, msg);
-		janus_mutex_unlock(&sessions_mutex);
 		return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, NULL, NULL);
 	} else {
 		JANUS_LOG(LOG_VERB, "Unknown request '%s'\n", request_text);
@@ -2428,22 +2430,24 @@ void janus_streaming_incoming_rtcp(janus_plugin_session *handle, int video, char
 }
 
 void janus_streaming_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_streaming_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_streaming_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_mutex_lock(&sessions_mutex);
 	janus_streaming_session *session = janus_streaming_lookup_session(handle);
 	if(!session) {
-		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
 	if(session->destroyed) {
-		janus_mutex_unlock(&sessions_mutex);
 		return;
 	}
 	if(g_atomic_int_add(&session->hangingup, 1)) {
-		janus_mutex_unlock(&sessions_mutex);
 		return;
 	}
 	session->substream = -1;
@@ -2452,14 +2456,26 @@ void janus_streaming_hangup_media(janus_plugin_session *handle) {
 	session->templayer_target = 0;
 	session->last_relayed = 0;
 	janus_vp8_simulcast_context_reset(&session->simulcast_context);
-	/* FIXME Simulate a "stop" coming from the browser */
-	janus_streaming_message *msg = g_malloc0(sizeof(janus_streaming_message));
-	msg->handle = handle;
-	msg->message = json_pack("{ss}", "request", "stop");
-	msg->transaction = NULL;
-	msg->jsep = NULL;
-	g_async_queue_push(messages, msg);
-	janus_mutex_unlock(&sessions_mutex);
+	session->stopping = TRUE;
+	session->started = FALSE;
+	session->paused = FALSE;
+	session->substream = -1;
+	session->substream_target = 0;
+	session->templayer = -1;
+	session->templayer_target = 0;
+	session->last_relayed = 0;
+	janus_vp8_simulcast_context_reset(&session->simulcast_context);
+	janus_streaming_mountpoint *mp = session->mountpoint;
+	if(mp) {
+		janus_mutex_lock(&mp->mutex);
+		JANUS_LOG(LOG_VERB, "  -- Removing the session from the mountpoint listeners\n");
+		if(g_list_find(mp->listeners, session) != NULL) {
+			JANUS_LOG(LOG_VERB, "  -- -- Found!\n");
+		}
+		mp->listeners = g_list_remove_all(mp->listeners, session);
+		janus_mutex_unlock(&mp->mutex);
+	}
+	session->mountpoint = NULL;
 }
 
 /* Thread to handle incoming messages */
@@ -2868,36 +2884,8 @@ static void *janus_streaming_handler(void *data) {
 				continue;
 			}
 			JANUS_LOG(LOG_VERB, "Stopping the streaming\n");
-			session->stopping = TRUE;
-			session->started = FALSE;
-			session->paused = FALSE;
-			session->substream = -1;
-			session->substream_target = 0;
-			session->templayer = -1;
-			session->templayer_target = 0;
-			session->last_relayed = 0;
-			janus_vp8_simulcast_context_reset(&session->simulcast_context);
 			result = json_object();
 			json_object_set_new(result, "status", json_string("stopping"));
-			janus_streaming_mountpoint *mp = session->mountpoint;
-			if(mp) {
-				janus_mutex_lock(&mp->mutex);
-				JANUS_LOG(LOG_VERB, "  -- Removing the session from the mountpoint listeners\n");
-				if(g_list_find(mp->listeners, session) != NULL) {
-					JANUS_LOG(LOG_VERB, "  -- -- Found!\n");
-				}
-				mp->listeners = g_list_remove_all(mp->listeners, session);
-				janus_mutex_unlock(&mp->mutex);
-			}
-			/* Also notify event handlers */
-			if(notify_events && gateway->events_is_enabled()) {
-				json_t *info = json_object();
-				json_object_set_new(info, "status", json_string("stopping"));
-				if(mp)
-					json_object_set_new(info, "id", json_integer(mp->id));
-				gateway->notify_event(&janus_streaming_plugin, session->handle, info);
-			}
-			session->mountpoint = NULL;
 			/* Tell the core to tear down the PeerConnection, hangup_media will do the rest */
 			gateway->close_pc(session->handle);
 		} else {
diff --git a/plugins/janus_textroom.c b/plugins/janus_textroom.c
index 04fe334..384f719 100644
--- a/plugins/janus_textroom.c
+++ b/plugins/janus_textroom.c
@@ -194,6 +194,7 @@ static janus_callbacks *gateway = NULL;
 static GThread *handler_thread;
 static GThread *watchdog;
 static void *janus_textroom_handler(void *data);
+static void janus_textroom_hangup_media_internal(janus_plugin_session *handle);
 
 /* JSON serialization options */
 static size_t json_format = JSON_INDENT(3) | JSON_PRESERVE_ORDER;
@@ -594,6 +595,14 @@ const char *janus_textroom_get_package(void) {
 	return JANUS_TEXTROOM_PACKAGE;
 }
 
+static janus_textroom_session *janus_textroom_lookup_session(janus_plugin_session *handle) {
+	janus_textroom_session *session = NULL;
+	if (g_hash_table_contains(sessions,handle)) {
+		session = (janus_textroom_session *)handle->plugin_handle;
+	}
+	return session;
+}
+
 void janus_textroom_create_session(janus_plugin_session *handle, int *error) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		*error = -1;
@@ -619,18 +628,19 @@ void janus_textroom_destroy_session(janus_plugin_session *handle, int *error) {
 		*error = -1;
 		return;
 	}
-	janus_textroom_session *session = (janus_textroom_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_textroom_session *session = janus_textroom_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		*error = -2;
 		return;
 	}
-	JANUS_LOG(LOG_VERB, "Removing Echo Test session...\n");
-	janus_mutex_lock(&sessions_mutex);
 	if(!session->destroyed) {
-		g_hash_table_remove(sessions, handle);
-		janus_textroom_hangup_media(handle);
+		JANUS_LOG(LOG_VERB, "Removing Text Room session...\n");
+		janus_textroom_hangup_media_internal(handle);
 		session->destroyed = janus_get_monotonic_time();
+		g_hash_table_remove(sessions, handle);
 		/* Cleaning up and removing the session is done in a lazy way */
 		old_sessions = g_list_append(old_sessions, session);
 	}
@@ -642,14 +652,17 @@ json_t *janus_textroom_query_session(janus_plugin_session *handle) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		return NULL;
 	}
-	janus_textroom_session *session = (janus_textroom_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_textroom_session *session = janus_textroom_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return NULL;
 	}
 	/* TODO Return meaningful info: participant details, rooms they're in, etc. */
 	json_t *info = json_object();
 	json_object_set_new(info, "destroyed", json_integer(session->destroyed));
+	janus_mutex_unlock(&sessions_mutex);
 	return info;
 }
 
@@ -663,6 +676,8 @@ struct janus_plugin_result *janus_textroom_handle_message(janus_plugin_session *
 	json_t *root = message;
 	json_t *response = NULL;
 
+	janus_mutex_lock(&sessions_mutex);
+
 	if(message == NULL) {
 		JANUS_LOG(LOG_ERR, "No message??\n");
 		error_code = JANUS_TEXTROOM_ERROR_NO_MESSAGE;
@@ -670,7 +685,7 @@ struct janus_plugin_result *janus_textroom_handle_message(janus_plugin_session *
 		goto plugin_response;
 	}
 
-	janus_textroom_session *session = (janus_textroom_session *)handle->plugin_handle;
+	janus_textroom_session *session = janus_textroom_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		error_code = JANUS_TEXTROOM_ERROR_UNKNOWN_ERROR;
@@ -710,6 +725,7 @@ struct janus_plugin_result *janus_textroom_handle_message(janus_plugin_session *
 		json_object_set_new(root, "textroom", json_string(request_text));
 		json_object_set_new(root, "transaction", json_string(transaction));
 		janus_plugin_result *result = janus_textroom_handle_incoming_request(session->handle, NULL, root, FALSE);
+		janus_mutex_unlock(&sessions_mutex);
 		if(result == NULL) {
 			JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
 			error_code = JANUS_TEXTROOM_ERROR_INVALID_JSON;
@@ -724,6 +740,7 @@ struct janus_plugin_result *janus_textroom_handle_message(janus_plugin_session *
 		return result;
 	} else if(!strcasecmp(request_text, "setup") || !strcasecmp(request_text, "ack")) {
 		/* These messages are handled asynchronously */
+		janus_mutex_unlock(&sessions_mutex);
 		janus_textroom_message *msg = g_malloc0(sizeof(janus_textroom_message));
 		msg->handle = handle;
 		msg->transaction = transaction;
@@ -741,6 +758,7 @@ struct janus_plugin_result *janus_textroom_handle_message(janus_plugin_session *
 
 plugin_response:
 		{
+			janus_mutex_unlock(&sessions_mutex);
 			if(!response) {
 				/* Prepare JSON error event */
 				response = json_object();
@@ -763,14 +781,19 @@ void janus_textroom_setup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_textroom_session *session = (janus_textroom_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_textroom_session *session = janus_textroom_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	g_atomic_int_set(&session->hangingup, 0);
+	janus_mutex_unlock(&sessions_mutex);
 }
 
 void janus_textroom_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len) {
@@ -1818,10 +1841,16 @@ void janus_textroom_slow_link(janus_plugin_session *handle, int uplink, int vide
 }
 
 void janus_textroom_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_textroom_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_textroom_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_textroom_session *session = (janus_textroom_session *)handle->plugin_handle;
+	janus_textroom_session *session = janus_textroom_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
@@ -1878,11 +1907,8 @@ static void *janus_textroom_handler(void *data) {
 			janus_textroom_message_free(msg);
 			continue;
 		}
-		janus_textroom_session *session = NULL;
 		janus_mutex_lock(&sessions_mutex);
-		if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
-			session = (janus_textroom_session *)msg->handle->plugin_handle;
-		}
+		janus_textroom_session *session = janus_textroom_lookup_session(msg->handle);
 		if(!session) {
 			janus_mutex_unlock(&sessions_mutex);
 			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
diff --git a/plugins/janus_videoroom.c b/plugins/janus_videoroom.c
index a8ab7a9..404f88e 100644
--- a/plugins/janus_videoroom.c
+++ b/plugins/janus_videoroom.c
@@ -367,7 +367,6 @@ static void janus_videoroom_relay_rtp_packet(gpointer data, gpointer user_data);
 static void janus_videoroom_relay_data_packet(gpointer data, gpointer user_data);
 static void janus_videoroom_hangup_media_internal(janus_plugin_session *handle);
 
-
 typedef enum janus_videoroom_p_type {
 	janus_videoroom_p_type_none = 0,
 	janus_videoroom_p_type_subscriber,			/* Generic listener/subscriber */
@@ -1299,9 +1298,9 @@ void janus_videoroom_destroy_session(janus_plugin_session *handle, int *error) {
 		JANUS_LOG(LOG_WARN, "VideoRoom session already marked as destroyed...\n");
 		return;
 	}
-	JANUS_LOG(LOG_VERB, "Removing VideoRoom session...\n");
 	/* Cleaning up and removing the session is done in a lazy way */
 	if(!session->destroyed) {
+		JANUS_LOG(LOG_VERB, "Removing VideoRoom session...\n");
 		/* Any related WebRTC PeerConnection is not available anymore either */
 		janus_videoroom_hangup_media_internal(handle);
 		session->destroyed = janus_get_monotonic_time();
@@ -2729,6 +2728,7 @@ struct janus_plugin_result *janus_videoroom_handle_message(janus_plugin_session
 			|| !strcasecmp(request_text, "start") || !strcasecmp(request_text, "pause") || !strcasecmp(request_text, "switch") || !strcasecmp(request_text, "stop")
 			|| !strcasecmp(request_text, "add") || !strcasecmp(request_text, "remove") || !strcasecmp(request_text, "leave")) {
 		/* These messages are handled asynchronously */
+		janus_mutex_unlock(&sessions_mutex);
 
 		janus_videoroom_message *msg = g_malloc0(sizeof(janus_videoroom_message));
 		msg->handle = handle;
@@ -2737,7 +2737,6 @@ struct janus_plugin_result *janus_videoroom_handle_message(janus_plugin_session
 		msg->jsep = jsep;
 		g_async_queue_push(messages, msg);
 
-		janus_mutex_unlock(&sessions_mutex);
 		return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, NULL, NULL);
 	} else {
 		JANUS_LOG(LOG_VERB, "Unknown request '%s'\n", request_text);
@@ -3148,9 +3147,12 @@ void janus_videoroom_slow_link(janus_plugin_session *handle, int uplink, int vid
 	/* The core is informing us that our peer got too many NACKs, are we pushing media too hard? */
 	if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized) || !gateway)
 		return;
-	janus_videoroom_session *session = (janus_videoroom_session *)handle->plugin_handle;
-	if(!session || session->destroyed || !session->participant)
+	janus_mutex_lock(&sessions_mutex);
+	janus_videoroom_session *session = janus_videoroom_lookup_session(handle);
+	if(!session || session->destroyed || !session->participant) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	/* Check if it's an uplink (publisher) or downlink (viewer) issue */
 	if(session->participant_type == janus_videoroom_p_type_publisher) {
 		if(!uplink) {
@@ -3184,6 +3186,7 @@ void janus_videoroom_slow_link(janus_plugin_session *handle, int uplink, int vid
 			JANUS_LOG(LOG_WARN, "Got a slow downlink on a VideoRoom viewer? Weird, because it doesn't send media...\n");
 		}
 	}
+	janus_mutex_unlock(&sessions_mutex);
 }
 
 static void janus_videoroom_recorder_create(janus_videoroom_participant *participant, gboolean audio, gboolean video, gboolean data) {
@@ -3275,6 +3278,12 @@ static void janus_videoroom_recorder_close(janus_videoroom_participant *particip
 	participant->drc = NULL;
 }
 
+void janus_videoroom_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_videoroom_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
 static void janus_videoroom_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
@@ -3365,12 +3374,6 @@ static void janus_videoroom_hangup_media_internal(janus_plugin_session *handle)
 	}
 }
 
-void janus_videoroom_hangup_media(janus_plugin_session *handle) {
-	janus_mutex_lock(&sessions_mutex);
-	janus_videoroom_hangup_media_internal(handle);
-	janus_mutex_unlock(&sessions_mutex);
-}
-
 /* Thread to handle incoming messages */
 static void *janus_videoroom_handler(void *data) {
 	JANUS_LOG(LOG_VERB, "Joining VideoRoom handler thread\n");
diff --git a/plugins/janus_voicemail.c b/plugins/janus_voicemail.c
index 0268b44..b982e2c 100644
--- a/plugins/janus_voicemail.c
+++ b/plugins/janus_voicemail.c
@@ -181,6 +181,7 @@ static janus_callbacks *gateway = NULL;
 static GThread *handler_thread;
 static GThread *watchdog;
 static void *janus_voicemail_handler(void *data);
+static void janus_voicemail_hangup_media_internal(janus_plugin_session *handle);
 
 typedef struct janus_voicemail_message {
 	janus_plugin_session *handle;
@@ -439,6 +440,14 @@ const char *janus_voicemail_get_package(void) {
 	return JANUS_VOICEMAIL_PACKAGE;
 }
 
+static janus_voicemail_session *janus_voicemail_lookup_session(janus_plugin_session *handle) {
+	janus_voicemail_session *session = NULL;
+	if (g_hash_table_contains(sessions,handle)) {
+		session = (janus_voicemail_session *)handle->plugin_handle;
+	}
+	return session;
+}
+
 void janus_voicemail_create_session(janus_plugin_session *handle, int *error) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		*error = -1;
@@ -471,18 +480,19 @@ void janus_voicemail_destroy_session(janus_plugin_session *handle, int *error) {
 		*error = -1;
 		return;
 	}	
-	janus_voicemail_session *session = (janus_voicemail_session *)handle->plugin_handle; 
+	janus_mutex_lock(&sessions_mutex);
+	janus_voicemail_session *session = janus_voicemail_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No VoiceMail session associated with this handle...\n");
 		*error = -2;
 		return;
 	}
-	janus_mutex_lock(&sessions_mutex);
 	if(!session->destroyed) {
 		JANUS_LOG(LOG_VERB, "Removing VoiceMail session...\n");
-		g_hash_table_remove(sessions, handle);
-		janus_voicemail_hangup_media(handle);
+		janus_voicemail_hangup_media_internal(handle);
 		session->destroyed = janus_get_monotonic_time();
+		g_hash_table_remove(sessions, handle);
 		/* Cleaning up and removing the session is done in a lazy way */
 		old_sessions = g_list_append(old_sessions, session);
 	}
@@ -495,8 +505,10 @@ json_t *janus_voicemail_query_session(janus_plugin_session *handle) {
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
 		return NULL;
 	}	
-	janus_voicemail_session *session = (janus_voicemail_session *)handle->plugin_handle;
+	janus_mutex_lock(&sessions_mutex);
+	janus_voicemail_session *session = janus_voicemail_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return NULL;
 	}
@@ -509,6 +521,7 @@ json_t *janus_voicemail_query_session(janus_plugin_session *handle) {
 		json_object_set_new(info, "filename", session->filename ? json_string(session->filename) : NULL);
 	}
 	json_object_set_new(info, "destroyed", json_integer(session->destroyed));
+	janus_mutex_unlock(&sessions_mutex);
 	return info;
 }
 
@@ -530,17 +543,22 @@ void janus_voicemail_setup_media(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_voicemail_session *session = (janus_voicemail_session *)handle->plugin_handle;	
+	janus_mutex_lock(&sessions_mutex);
+	janus_voicemail_session *session = janus_voicemail_lookup_session(handle);
 	if(!session) {
+		janus_mutex_unlock(&sessions_mutex);
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
 	}
-	if(session->destroyed)
+	if(session->destroyed) {
+		janus_mutex_unlock(&sessions_mutex);
 		return;
+	}
 	g_atomic_int_set(&session->hangingup, 0);
 	/* Only start recording this peer when we get this event */
 	session->start_time = janus_get_monotonic_time();
 	session->started = TRUE;
+	janus_mutex_unlock(&sessions_mutex);
 	/* Prepare JSON event */
 	json_t *event = json_object();
 	json_object_set_new(event, "voicemail", json_string("event"));
@@ -595,10 +613,16 @@ void janus_voicemail_incoming_rtcp(janus_plugin_session *handle, int video, char
 }
 
 void janus_voicemail_hangup_media(janus_plugin_session *handle) {
+	janus_mutex_lock(&sessions_mutex);
+	janus_voicemail_hangup_media_internal(handle);
+	janus_mutex_unlock(&sessions_mutex);
+}
+
+static void janus_voicemail_hangup_media_internal(janus_plugin_session *handle) {
 	JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
 	if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
 		return;
-	janus_voicemail_session *session = (janus_voicemail_session *)handle->plugin_handle;
+	janus_voicemail_session *session = janus_voicemail_lookup_session(handle);
 	if(!session) {
 		JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
 		return;
@@ -634,11 +658,8 @@ static void *janus_voicemail_handler(void *data) {
 			janus_voicemail_message_free(msg);
 			continue;
 		}
-		janus_voicemail_session *session = NULL;
 		janus_mutex_lock(&sessions_mutex);
-		if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
-			session = (janus_voicemail_session *)msg->handle->plugin_handle;
-		}
+		janus_voicemail_session *session = janus_voicemail_lookup_session(msg->handle);
 		if(!session) {
 			janus_mutex_unlock(&sessions_mutex);
 			JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");

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