diff --git a/ice.c b/ice.c index 6b3e2d84f3..9cddccbbf3 100644 --- a/ice.c +++ b/ice.c @@ -392,6 +392,12 @@ gboolean janus_ice_event_get_combine_media_stats(void) { return janus_ice_event_combine_media_stats; } +/* Number of active PeerConnection (for stats) */ +static volatile gint pc_num = 0; +int janus_ice_get_peerconnection_num(void) { + return g_atomic_int_get(&pc_num); +} + /* RTP/RTCP port range */ static uint16_t rtp_range_min = 0; static uint16_t rtp_range_max = 0; @@ -1584,6 +1590,8 @@ void janus_ice_webrtc_hangup(janus_ice_handle *handle, const char *reason) { #endif g_main_context_wakeup(handle->mainctx); } + if(g_atomic_int_dec_and_test(&handle->has_pc)) + g_atomic_int_dec_and_test(&pc_num); } static void janus_ice_webrtc_free(janus_ice_handle *handle) { @@ -5493,4 +5501,6 @@ void janus_ice_dtls_handshake_done(janus_ice_handle *handle, janus_ice_component janus_events_notify_handlers(JANUS_EVENT_TYPE_WEBRTC, JANUS_EVENT_SUBTYPE_WEBRTC_STATE, session->session_id, handle->handle_id, handle->opaque_id, info); } + g_atomic_int_set(&handle->has_pc, 1); + g_atomic_int_inc(&pc_num); } diff --git a/ice.h b/ice.h index 6dd71f8297..6938721a86 100644 --- a/ice.h +++ b/ice.h @@ -201,6 +201,9 @@ void janus_ice_set_event_stats_period(int period); /*! \brief Method to get the current event handler statistics period (see above) * @returns The current event handler stats period */ int janus_ice_get_event_stats_period(void); +/*! \brief Method to get the number of active PeerConnection (for stats) + * @returns The current number of active PeerConnections */ +int janus_ice_get_peerconnection_num(void); /*! \brief Method to define wether the media stats shall be dispatched in one event (true) or in dedicated single events (false - default) * @param[in] combine_media_stats_to_one_event true to combine media statistics in on event or false to send dedicated events */ @@ -400,6 +403,8 @@ struct janus_ice_handle { janus_mutex mutex; /*! \brief Whether a close_pc was requested recently on the PeerConnection */ volatile gint closepc; + /*! \brief Atomic flag to check whether a PeerConnection was established */ + volatile gint has_pc; /*! \brief Atomic flag to check if this instance has been destroyed */ volatile gint destroyed; /*! \brief Reference counter for this instance */ diff --git a/janus.c b/janus.c index 8c8d8d6bcc..0422e35b1f 100644 --- a/janus.c +++ b/janus.c @@ -634,6 +634,9 @@ static janus_mutex sessions_mutex; static GHashTable *sessions = NULL; static GMainContext *sessions_watchdog_context = NULL; +/* Counters */ +static volatile gint sessions_num = 0; +static volatile gint handles_num = 0; static void janus_ice_handle_dereference(janus_ice_handle *handle) { if(handle) @@ -737,6 +740,20 @@ static gpointer janus_sessions_watchdog(gpointer user_data) { return NULL; } +static gboolean janus_status_sessions(gpointer user_data) { + if(janus_events_is_enabled()) { + json_t *info = json_object(); + json_object_set_new(info, "status", json_string("update")); + json_t *details = json_object(); + json_object_set_new(details, "sessions", json_integer(g_atomic_int_get(&sessions_num))); + json_object_set_new(details, "handles", json_integer(g_atomic_int_get(&handles_num))); + json_object_set_new(details, "peerconnections", json_integer(janus_ice_get_peerconnection_num())); + json_object_set_new(details, "stats-period", json_integer(janus_ice_get_event_stats_period())); + json_object_set_new(info, "info", details); + janus_events_notify_handlers(JANUS_EVENT_TYPE_CORE, JANUS_EVENT_SUBTYPE_CORE_STARTUP, 0, info); + } + return TRUE; +} janus_session *janus_session_create(guint64 session_id) { janus_session *session = NULL; @@ -765,6 +782,7 @@ janus_session *janus_session_create(guint64 session_id) { janus_mutex_init(&session->mutex); janus_mutex_lock(&sessions_mutex); g_hash_table_insert(sessions, janus_uint64_dup(session->session_id), session); + g_atomic_int_inc(&sessions_num); janus_mutex_unlock(&sessions_mutex); return session; } @@ -833,13 +851,15 @@ void janus_session_handles_insert(janus_session *session, janus_ice_handle *hand session->ice_handles = g_hash_table_new_full(g_int64_hash, g_int64_equal, (GDestroyNotify)g_free, (GDestroyNotify)janus_ice_handle_dereference); janus_refcount_increase(&handle->ref); g_hash_table_insert(session->ice_handles, janus_uint64_dup(handle->handle_id), handle); + g_atomic_int_inc(&handles_num); janus_mutex_unlock(&session->mutex); } gint janus_session_handles_remove(janus_session *session, janus_ice_handle *handle) { janus_mutex_lock(&session->mutex); gint error = janus_ice_handle_destroy(session, handle); - g_hash_table_remove(session->ice_handles, &handle->handle_id); + if(g_hash_table_remove(session->ice_handles, &handle->handle_id)) + g_atomic_int_dec_and_test(&handles_num); janus_mutex_unlock(&session->mutex); return error; } @@ -857,6 +877,7 @@ void janus_session_handles_clear(janus_session *session) { continue; janus_ice_handle_destroy(session, handle); g_hash_table_iter_remove(&iter); + g_atomic_int_dec_and_test(&handles_num); } } janus_mutex_unlock(&session->mutex); @@ -1253,7 +1274,8 @@ int janus_process_incoming_request(janus_request *request) { goto jsondone; } janus_mutex_lock(&sessions_mutex); - g_hash_table_remove(sessions, &session->session_id); + if(g_hash_table_remove(sessions, &session->session_id)) + g_atomic_int_dec_and_test(&sessions_num); janus_mutex_unlock(&sessions_mutex); /* Notify the source that the session has been destroyed */ janus_request *source = janus_session_get_request(session); @@ -2762,7 +2784,8 @@ int janus_process_incoming_admin_request(janus_request *request) { /* Session-related */ if(!strcasecmp(message_text, "destroy_session")) { janus_mutex_lock(&sessions_mutex); - g_hash_table_remove(sessions, &session->session_id); + if(g_hash_table_remove(sessions, &session->session_id)) + g_atomic_int_dec_and_test(&sessions_num); janus_mutex_unlock(&sessions_mutex); /* Notify the source that the session has been destroyed */ janus_request *source = janus_session_get_request(session); @@ -5437,6 +5460,11 @@ gint main(int argc, char *argv[]) JANUS_LOG(LOG_FATAL, "Error initializing the Event handlers mechanism...\n"); exit(1); } + /* Send a status event every once in a while */ + GSource *timeout_source = g_timeout_source_new_seconds(15); + g_source_set_callback(timeout_source, janus_status_sessions, sessions_watchdog_context, NULL); + g_source_attach(timeout_source, sessions_watchdog_context); + g_source_unref(timeout_source); } /* Load plugins */