|
|
|
@ -12,45 +12,64 @@ |
|
|
|
#include "ice.h" |
|
|
|
|
|
|
|
|
|
|
|
TYPED_GHASHTABLE(janus_handles_set, uint64_t, void, g_int64_hash, g_int64_equal, NULL, NULL) |
|
|
|
TYPED_GHASHTABLE(janus_websockets_ht, struct websocket_conn, struct websocket_conn, |
|
|
|
g_direct_hash, g_direct_equal, NULL, NULL) |
|
|
|
|
|
|
|
struct janus_session { // "login" session |
|
|
|
struct obj obj; |
|
|
|
uint64_t id; |
|
|
|
mutex_t lock; |
|
|
|
time_t last_act; |
|
|
|
GHashTable *websockets; // controlling transports, websocket_conn -> websocket_conn |
|
|
|
GHashTable *handles; // handle ID -> 0x1. handle ID owned by janus_handles |
|
|
|
janus_websockets_ht websockets; // controlling transports, websocket_conn -> websocket_conn |
|
|
|
janus_handles_set handles; // handle ID -> 0x1. handle ID owned by janus_handles |
|
|
|
}; |
|
|
|
|
|
|
|
TYPED_GHASHTABLE(janus_sessions_ht, uint64_t, struct janus_session, g_int64_hash, g_int64_equal, NULL, NULL) |
|
|
|
|
|
|
|
|
|
|
|
struct janus_handle { // corresponds to a conference participant |
|
|
|
uint64_t id; |
|
|
|
struct janus_session *session; // holds a reference |
|
|
|
uint64_t room; |
|
|
|
}; |
|
|
|
|
|
|
|
TYPED_GHASHTABLE(janus_handles_ht, uint64_t, struct janus_handle, g_int64_hash, g_int64_equal, NULL, NULL) |
|
|
|
|
|
|
|
|
|
|
|
TYPED_GHASHTABLE(janus_feeds_ht, uint64_t, uint64_t, g_int64_hash, g_int64_equal, g_free, g_free) |
|
|
|
|
|
|
|
struct janus_room { |
|
|
|
uint64_t id; |
|
|
|
str call_id; |
|
|
|
int num_publishers; |
|
|
|
uint64_t handle_id; // controlling handle which created the room |
|
|
|
GHashTable *publishers; // handle ID -> feed ID |
|
|
|
GHashTable *subscribers; // handle ID -> subscribed feed ID |
|
|
|
GHashTable *feeds; // feed ID -> handle ID |
|
|
|
janus_feeds_ht publishers; // handle ID -> feed ID |
|
|
|
janus_feeds_ht subscribers; // handle ID -> subscribed feed ID |
|
|
|
janus_feeds_ht feeds; // feed ID -> handle ID |
|
|
|
}; |
|
|
|
|
|
|
|
TYPED_GHASHTABLE(janus_rooms_ht, uint64_t, struct janus_room, g_int64_hash, g_int64_equal, NULL, NULL) |
|
|
|
|
|
|
|
|
|
|
|
TYPED_GHASHTABLE(janus_tokens_ht, char, time_t, g_str_hash, g_str_equal, g_free, g_free) |
|
|
|
|
|
|
|
|
|
|
|
static mutex_t janus_lock; |
|
|
|
static GHashTable *janus_tokens; // auth tokens, currently mostly unused |
|
|
|
static GHashTable *janus_sessions; // session ID -> session. holds a session reference |
|
|
|
static GHashTable *janus_handles; // handle ID -> handle |
|
|
|
static GHashTable *janus_rooms; // room ID -> room |
|
|
|
static janus_tokens_ht janus_tokens; // auth tokens, currently mostly unused |
|
|
|
static janus_sessions_ht janus_sessions; // session ID -> session. holds a session reference |
|
|
|
static janus_handles_ht janus_handles; // handle ID -> handle |
|
|
|
static janus_rooms_ht janus_rooms; // room ID -> room |
|
|
|
|
|
|
|
|
|
|
|
static void __janus_session_free(void *p) { |
|
|
|
struct janus_session *s = p; |
|
|
|
if (g_hash_table_size(s->websockets) != 0) |
|
|
|
ilog(LOG_WARN, "Janus session is leaking %i WS references", g_hash_table_size(s->websockets)); |
|
|
|
g_hash_table_destroy(s->websockets); |
|
|
|
if (g_hash_table_size(s->handles) != 0) |
|
|
|
ilog(LOG_WARN, "Janus session is leaking %i handle references", g_hash_table_size(s->handles)); |
|
|
|
g_hash_table_destroy(s->handles); |
|
|
|
if (t_hash_table_size(s->websockets) != 0) |
|
|
|
ilog(LOG_WARN, "Janus session is leaking %i WS references", t_hash_table_size(s->websockets)); |
|
|
|
t_hash_table_size(s->websockets); |
|
|
|
if (t_hash_table_size(s->handles) != 0) |
|
|
|
ilog(LOG_WARN, "Janus session is leaking %i handle references", t_hash_table_size(s->handles)); |
|
|
|
t_hash_table_size(s->handles); |
|
|
|
mutex_destroy(&s->lock); |
|
|
|
} |
|
|
|
|
|
|
|
@ -58,7 +77,7 @@ static void __janus_session_free(void *p) { |
|
|
|
// XXX we have several hash tables that hold references to objs - unify all these |
|
|
|
static struct janus_session *janus_get_session(uint64_t id) { |
|
|
|
mutex_lock(&janus_lock); |
|
|
|
struct janus_session *ret = g_hash_table_lookup(janus_sessions, &id); |
|
|
|
struct janus_session *ret = t_hash_table_lookup(janus_sessions, &id); |
|
|
|
if (ret) |
|
|
|
obj_hold(ret); |
|
|
|
mutex_unlock(&janus_lock); |
|
|
|
@ -127,12 +146,11 @@ static void janus_send_json_sync_response(struct websocket_message *wm, JsonBuil |
|
|
|
static void janus_send_json_async(struct janus_session *session, JsonBuilder *builder) { |
|
|
|
char *result = glib_json_print(builder); |
|
|
|
|
|
|
|
GHashTableIter iter; |
|
|
|
gpointer value; |
|
|
|
g_hash_table_iter_init(&iter, session->websockets); |
|
|
|
janus_websockets_ht_iter iter; |
|
|
|
t_hash_table_iter_init(&iter, session->websockets); |
|
|
|
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &value)) { |
|
|
|
struct websocket_conn *wc = value; |
|
|
|
struct websocket_conn *wc; |
|
|
|
while (t_hash_table_iter_next(&iter, NULL, &wc)) { |
|
|
|
// lock order constraint: janus_session lock first, websocket_conn lock second |
|
|
|
websocket_write_text(wc, result, true); |
|
|
|
} |
|
|
|
@ -182,9 +200,9 @@ static const char *janus_videoroom_create(struct janus_session *session, struct |
|
|
|
room->num_publishers = 3; |
|
|
|
room->handle_id = handle->id; // controlling handle |
|
|
|
// XXX optimise for 64-bit archs |
|
|
|
room->publishers = g_hash_table_new_full(g_int64_hash, g_int64_equal, g_free, g_free); |
|
|
|
room->subscribers = g_hash_table_new_full(g_int64_hash, g_int64_equal, g_free, g_free); |
|
|
|
room->feeds = g_hash_table_new_full(g_int64_hash, g_int64_equal, g_free, g_free); |
|
|
|
room->publishers = janus_feeds_ht_new(); |
|
|
|
room->subscribers = janus_feeds_ht_new(); |
|
|
|
room->feeds = janus_feeds_ht_new(); |
|
|
|
|
|
|
|
uint64_t room_id = 0; |
|
|
|
if (json_reader_read_member(reader, "room")) { |
|
|
|
@ -196,7 +214,7 @@ static const char *janus_videoroom_create(struct janus_session *session, struct |
|
|
|
|
|
|
|
if (room_id) { |
|
|
|
*retcode = 512; |
|
|
|
if (g_hash_table_lookup(janus_rooms, &room_id)) |
|
|
|
if (t_hash_table_lookup(janus_rooms, &room_id)) |
|
|
|
return "Requested room already exists"; |
|
|
|
} |
|
|
|
|
|
|
|
@ -204,7 +222,7 @@ static const char *janus_videoroom_create(struct janus_session *session, struct |
|
|
|
if (!room_id) |
|
|
|
room_id = janus_random(); |
|
|
|
room->id = room_id; |
|
|
|
if (g_hash_table_lookup(janus_rooms, &room->id)) |
|
|
|
if (t_hash_table_lookup(janus_rooms, &room->id)) |
|
|
|
continue; |
|
|
|
room->call_id.s = janus_call_id(room_id); |
|
|
|
room->call_id.len = strlen(room->call_id.s); |
|
|
|
@ -217,7 +235,7 @@ static const char *janus_videoroom_create(struct janus_session *session, struct |
|
|
|
} |
|
|
|
if (!call->created_from) |
|
|
|
call->created_from = "janus"; |
|
|
|
g_hash_table_insert(janus_rooms, &room->id, room); |
|
|
|
t_hash_table_insert(janus_rooms, &room->id, room); |
|
|
|
rwlock_unlock_w(&call->master_lock); |
|
|
|
obj_put(call); |
|
|
|
break; |
|
|
|
@ -247,7 +265,7 @@ static const char *janus_videoroom_exists(struct janus_session *session, |
|
|
|
bool exists = false; |
|
|
|
|
|
|
|
if (room_id) |
|
|
|
room = g_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
room = t_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
if (room) { |
|
|
|
struct call *call = call_get(&room->call_id); |
|
|
|
if (call) { |
|
|
|
@ -275,7 +293,7 @@ static const char *janus_videoroom_destroy(struct janus_session *session, |
|
|
|
struct janus_room *room = NULL; |
|
|
|
|
|
|
|
if (room_id) |
|
|
|
g_hash_table_steal_extended(janus_rooms, &room_id, NULL, (void **) &room); |
|
|
|
t_hash_table_steal_extended(janus_rooms, &room_id, NULL, &room); |
|
|
|
*retcode = 426; |
|
|
|
if (!room) |
|
|
|
return "No such room"; |
|
|
|
@ -291,9 +309,9 @@ static const char *janus_videoroom_destroy(struct janus_session *session, |
|
|
|
} |
|
|
|
|
|
|
|
g_free(room->call_id.s); |
|
|
|
g_hash_table_destroy(room->publishers); |
|
|
|
g_hash_table_destroy(room->subscribers); |
|
|
|
g_hash_table_destroy(room->feeds); |
|
|
|
t_hash_table_size(room->publishers); |
|
|
|
t_hash_table_size(room->subscribers); |
|
|
|
t_hash_table_size(room->feeds); |
|
|
|
g_slice_free1(sizeof(*room), room); |
|
|
|
|
|
|
|
//XXX notify? |
|
|
|
@ -380,17 +398,15 @@ static void janus_publishers_list(JsonBuilder *builder, struct call *call, struc |
|
|
|
{ |
|
|
|
json_builder_begin_array(builder); // [ |
|
|
|
|
|
|
|
GHashTableIter iter; |
|
|
|
gpointer key, value; |
|
|
|
g_hash_table_iter_init(&iter, room->publishers); |
|
|
|
janus_feeds_ht_iter iter; |
|
|
|
t_hash_table_iter_init(&iter, room->publishers); |
|
|
|
|
|
|
|
while (g_hash_table_iter_next(&iter, &key, &value)) { |
|
|
|
uint64_t *feed_id_ptr = value; |
|
|
|
uint64_t *feed_id_ptr, *handle_id_ptr; |
|
|
|
while (t_hash_table_iter_next(&iter, &handle_id_ptr, &feed_id_ptr)) { |
|
|
|
if (*feed_id_ptr == feed_id) // skip self |
|
|
|
continue; |
|
|
|
|
|
|
|
// get monologue |
|
|
|
uint64_t *handle_id_ptr = key; |
|
|
|
struct call_monologue *ml = janus_get_monologue(*handle_id_ptr, call, call_get_monologue); |
|
|
|
if (!ml) |
|
|
|
continue; |
|
|
|
@ -414,14 +430,14 @@ static const char *janus_videoroom_join_sub(struct janus_handle *handle, struct |
|
|
|
{ |
|
|
|
// does the feed actually exist? get the feed handle |
|
|
|
*retcode = 512; |
|
|
|
uint64_t *feed_handle = g_hash_table_lookup(room->feeds, &feed_id); |
|
|
|
uint64_t *feed_handle = t_hash_table_lookup(room->feeds, &feed_id); |
|
|
|
if (!feed_handle) |
|
|
|
return "No such feed exists"; |
|
|
|
if (!g_hash_table_lookup(room->publishers, feed_handle)) |
|
|
|
if (!t_hash_table_lookup(room->publishers, feed_handle)) |
|
|
|
return "No such feed handle exists"; |
|
|
|
|
|
|
|
// handle ID points to the subscribed feed |
|
|
|
g_hash_table_insert(room->subscribers, uint64_dup(handle->id), uint64_dup(feed_id)); |
|
|
|
t_hash_table_insert(room->subscribers, uint64_dup(handle->id), uint64_dup(feed_id)); |
|
|
|
|
|
|
|
// add the subscription |
|
|
|
struct call_monologue *source_ml = janus_get_monologue(*feed_handle, call, call_get_monologue); |
|
|
|
@ -490,7 +506,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan |
|
|
|
|
|
|
|
struct janus_room *room = NULL; |
|
|
|
if (room_id) |
|
|
|
room = g_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
room = t_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
*retcode = 426; |
|
|
|
if (!room) |
|
|
|
return "No such room"; |
|
|
|
@ -502,9 +518,9 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan |
|
|
|
return "No such room"; |
|
|
|
|
|
|
|
*retcode = 436; |
|
|
|
if (!is_pub && g_hash_table_lookup(room->subscribers, &handle->id)) |
|
|
|
if (!is_pub && t_hash_table_lookup(room->subscribers, &handle->id)) |
|
|
|
return "User already exists in the room as a subscriber"; |
|
|
|
if (is_pub && g_hash_table_lookup(room->publishers, &handle->id)) |
|
|
|
if (is_pub && t_hash_table_lookup(room->publishers, &handle->id)) |
|
|
|
return "User already exists in the room as a publisher"; |
|
|
|
|
|
|
|
uint64_t feed_id = 0; // set for single feed IDs, otherwise remains 0 |
|
|
|
@ -516,7 +532,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan |
|
|
|
feed_id = jr_str_int(reader); |
|
|
|
if (!feed_id) |
|
|
|
return "Invalid feed ID requested"; |
|
|
|
if (g_hash_table_lookup(room->feeds, &feed_id)) |
|
|
|
if (t_hash_table_lookup(room->feeds, &feed_id)) |
|
|
|
return "Feed already exists"; |
|
|
|
} |
|
|
|
json_reader_end_member(reader); |
|
|
|
@ -524,14 +540,14 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan |
|
|
|
// random feed ID? |
|
|
|
while (!feed_id) { |
|
|
|
feed_id = janus_random(); |
|
|
|
if (feed_id && g_hash_table_lookup(room->feeds, &feed_id)) |
|
|
|
if (feed_id && t_hash_table_lookup(room->feeds, &feed_id)) |
|
|
|
feed_id = 0; |
|
|
|
} |
|
|
|
|
|
|
|
// feed ID points to the handle |
|
|
|
g_hash_table_insert(room->feeds, uint64_dup(feed_id), uint64_dup(handle->id)); |
|
|
|
t_hash_table_insert(room->feeds, uint64_dup(feed_id), uint64_dup(handle->id)); |
|
|
|
// handle ID points to the feed |
|
|
|
g_hash_table_insert(room->publishers, uint64_dup(handle->id), uint64_dup(feed_id)); |
|
|
|
t_hash_table_insert(room->publishers, uint64_dup(handle->id), uint64_dup(feed_id)); |
|
|
|
} |
|
|
|
else { |
|
|
|
// subscriber |
|
|
|
@ -732,21 +748,20 @@ static void janus_notify_publishers(uint64_t room_id, uint64_t except, void *ptr |
|
|
|
void (*callback)(JsonBuilder *event, void *ptr, uint64_t u64, struct janus_room *room, |
|
|
|
uint64_t publisher_feed)) |
|
|
|
{ |
|
|
|
struct janus_room *room = g_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
struct janus_room *room = t_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
if (!room) |
|
|
|
return; |
|
|
|
|
|
|
|
GHashTableIter iter; |
|
|
|
gpointer key, value; |
|
|
|
g_hash_table_iter_init(&iter, room->publishers); |
|
|
|
janus_feeds_ht_iter iter; |
|
|
|
t_hash_table_iter_init(&iter, room->publishers); |
|
|
|
|
|
|
|
while (g_hash_table_iter_next(&iter, &key, &value)) { |
|
|
|
uint64_t *handle_id = key; |
|
|
|
uint64_t *handle_id, *feed_id; |
|
|
|
while (t_hash_table_iter_next(&iter, &handle_id, &feed_id)) { |
|
|
|
if (*handle_id == except) |
|
|
|
continue; |
|
|
|
|
|
|
|
// look up the handle and determine which session it belongs to |
|
|
|
struct janus_handle *handle = g_hash_table_lookup(janus_handles, handle_id); |
|
|
|
struct janus_handle *handle = t_hash_table_lookup(janus_handles, handle_id); |
|
|
|
if (!handle) |
|
|
|
continue; |
|
|
|
if (!handle->session) |
|
|
|
@ -754,8 +769,6 @@ static void janus_notify_publishers(uint64_t room_id, uint64_t except, void *ptr |
|
|
|
|
|
|
|
// send to the handle's session |
|
|
|
|
|
|
|
uint64_t *feed_id = value; |
|
|
|
|
|
|
|
JsonBuilder *event = json_builder_new(); |
|
|
|
json_builder_begin_object(event); // { |
|
|
|
json_builder_set_member_name(event, "janus"); |
|
|
|
@ -823,7 +836,7 @@ static const char *janus_videoroom_configure(struct websocket_message *wm, struc |
|
|
|
|
|
|
|
AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); |
|
|
|
|
|
|
|
struct janus_room *room = g_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
struct janus_room *room = t_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
*retcode = 426; |
|
|
|
if (!room) |
|
|
|
return "No such room"; |
|
|
|
@ -832,7 +845,7 @@ static const char *janus_videoroom_configure(struct websocket_message *wm, struc |
|
|
|
if (!call) |
|
|
|
return "No such room"; |
|
|
|
*retcode = 512; |
|
|
|
if (!g_hash_table_lookup(room->publishers, &handle->id)) |
|
|
|
if (!t_hash_table_lookup(room->publishers, &handle->id)) |
|
|
|
return "Not a publisher"; |
|
|
|
|
|
|
|
struct call_monologue *ml = NULL; |
|
|
|
@ -959,7 +972,7 @@ static const char *janus_videoroom_start(struct websocket_message *wm, struct ja |
|
|
|
|
|
|
|
AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); |
|
|
|
|
|
|
|
struct janus_room *room = g_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
struct janus_room *room = t_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
*retcode = 426; |
|
|
|
if (!room) |
|
|
|
return "No such room"; |
|
|
|
@ -967,12 +980,12 @@ static const char *janus_videoroom_start(struct websocket_message *wm, struct ja |
|
|
|
if (!call) |
|
|
|
return "No such room"; |
|
|
|
*retcode = 456; |
|
|
|
uint64_t *feed_id = g_hash_table_lookup(room->subscribers, &handle->id); |
|
|
|
uint64_t *feed_id = t_hash_table_lookup(room->subscribers, &handle->id); |
|
|
|
if (!feed_id) |
|
|
|
return "Not a subscriber"; |
|
|
|
|
|
|
|
*retcode = 512; |
|
|
|
uint64_t *feed_handle = g_hash_table_lookup(room->feeds, feed_id); |
|
|
|
uint64_t *feed_handle = t_hash_table_lookup(room->feeds, feed_id); |
|
|
|
if (!feed_handle) |
|
|
|
return "No such feed exists"; |
|
|
|
|
|
|
|
@ -1018,7 +1031,7 @@ static const char *janus_videoroom_unpublish(struct websocket_message *wm, struc |
|
|
|
|
|
|
|
struct janus_room *room = NULL; |
|
|
|
if (room_id) |
|
|
|
room = g_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
room = t_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
*retcode = 426; |
|
|
|
if (!room) |
|
|
|
return "No such room"; |
|
|
|
@ -1028,7 +1041,7 @@ static const char *janus_videoroom_unpublish(struct websocket_message *wm, struc |
|
|
|
if (!call) |
|
|
|
return "No such room"; |
|
|
|
|
|
|
|
uint64_t *feed_id = g_hash_table_lookup(room->publishers, &handle->id); |
|
|
|
uint64_t *feed_id = t_hash_table_lookup(room->publishers, &handle->id); |
|
|
|
*retcode = 512; |
|
|
|
if (!feed_id) |
|
|
|
return "Not a publisher"; |
|
|
|
@ -1144,7 +1157,7 @@ static const char *janus_add_token(JsonReader *reader, JsonBuilder *builder, boo |
|
|
|
time_t *now = g_malloc(sizeof(*now)); |
|
|
|
*now = rtpe_now.tv_sec; |
|
|
|
mutex_lock(&janus_lock); |
|
|
|
g_hash_table_replace(janus_tokens, g_strdup(token), now); |
|
|
|
t_hash_table_replace(janus_tokens, g_strdup(token), now); |
|
|
|
mutex_unlock(&janus_lock); |
|
|
|
|
|
|
|
json_builder_set_member_name(builder, "data"); |
|
|
|
@ -1172,21 +1185,21 @@ static const char *janus_create(JsonReader *reader, JsonBuilder *builder, struct |
|
|
|
mutex_init(&session->lock); |
|
|
|
mutex_lock(&session->lock); // not really necessary but Coverity complains |
|
|
|
session->last_act = rtpe_now.tv_sec; |
|
|
|
session->websockets = g_hash_table_new(g_direct_hash, g_direct_equal); |
|
|
|
session->handles = g_hash_table_new(g_int64_hash, g_int64_equal); |
|
|
|
session->websockets = janus_websockets_ht_new(); |
|
|
|
session->handles = janus_handles_set_new(); |
|
|
|
|
|
|
|
g_hash_table_insert(session->websockets, wm->wc, wm->wc); |
|
|
|
t_hash_table_insert(session->websockets, wm->wc, wm->wc); |
|
|
|
|
|
|
|
do { |
|
|
|
while (!session_id) |
|
|
|
session_id = janus_random(); |
|
|
|
|
|
|
|
mutex_lock(&janus_lock); |
|
|
|
if (g_hash_table_lookup(janus_sessions, &session_id)) |
|
|
|
if (t_hash_table_lookup(janus_sessions, &session_id)) |
|
|
|
session_id = 0; // pick a random one |
|
|
|
else { |
|
|
|
session->id = session_id; |
|
|
|
g_hash_table_insert(janus_sessions, &session->id, obj_get(session)); |
|
|
|
t_hash_table_insert(janus_sessions, &session->id, obj_get(session)); |
|
|
|
} |
|
|
|
mutex_unlock(&janus_lock); |
|
|
|
} |
|
|
|
@ -1209,7 +1222,7 @@ static const char *janus_create(JsonReader *reader, JsonBuilder *builder, struct |
|
|
|
|
|
|
|
void janus_detach_websocket(struct janus_session *session, struct websocket_conn *wc) { |
|
|
|
LOCK(&session->lock); |
|
|
|
g_hash_table_remove(session->websockets, wc); |
|
|
|
t_hash_table_remove(session->websockets, wc); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -1308,16 +1321,16 @@ static const char *janus_attach(JsonReader *reader, JsonBuilder *builder, struct |
|
|
|
uint64_t handle_id = 0; |
|
|
|
while (1) { |
|
|
|
handle_id = handle->id = janus_random(); |
|
|
|
if (g_hash_table_lookup(janus_handles, &handle->id)) |
|
|
|
if (t_hash_table_lookup(janus_handles, &handle->id)) |
|
|
|
continue; |
|
|
|
g_hash_table_insert(janus_handles, &handle->id, handle); |
|
|
|
t_hash_table_insert(janus_handles, &handle->id, handle); |
|
|
|
break; |
|
|
|
} |
|
|
|
mutex_unlock(&janus_lock); |
|
|
|
|
|
|
|
mutex_lock(&session->lock); |
|
|
|
assert(g_hash_table_lookup(session->handles, &handle_id) == NULL); |
|
|
|
g_hash_table_insert(session->handles, &handle->id, (void *) 0x1); |
|
|
|
assert(t_hash_table_lookup(session->handles, &handle_id) == NULL); |
|
|
|
t_hash_table_insert(session->handles, &handle->id, (void *) 0x1); |
|
|
|
mutex_unlock(&session->lock); |
|
|
|
|
|
|
|
json_builder_set_member_name(builder, "data"); |
|
|
|
@ -1342,11 +1355,11 @@ static void janus_destroy_handle(struct janus_handle *handle) { |
|
|
|
if (!room_id) |
|
|
|
return; |
|
|
|
|
|
|
|
struct janus_room *room = g_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
struct janus_room *room = t_hash_table_lookup(janus_rooms, &room_id); |
|
|
|
if (!room) |
|
|
|
return; |
|
|
|
|
|
|
|
uint64_t *feed = g_hash_table_lookup(room->publishers, &handle_id); |
|
|
|
uint64_t *feed = t_hash_table_lookup(room->publishers, &handle_id); |
|
|
|
if (feed) { |
|
|
|
// was a publisher - send notifies |
|
|
|
janus_notify_publishers(room_id, handle_id, NULL, *feed, janus_notify_publishers_unpublished); |
|
|
|
@ -1363,11 +1376,11 @@ static void janus_destroy_handle(struct janus_handle *handle) { |
|
|
|
obj_put(call); |
|
|
|
} |
|
|
|
|
|
|
|
g_hash_table_remove(room->publishers, &handle_id); |
|
|
|
t_hash_table_remove(room->publishers, &handle_id); |
|
|
|
feed = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (g_hash_table_remove(room->subscribers, &handle_id)) { |
|
|
|
if (t_hash_table_remove(room->subscribers, &handle_id)) { |
|
|
|
// was a subscriber |
|
|
|
struct call *call = call_get(&room->call_id); |
|
|
|
if (call) { |
|
|
|
@ -1399,7 +1412,7 @@ static const char *janus_detach(struct websocket_message *wm, JsonReader *reader |
|
|
|
{ |
|
|
|
LOCK(&session->lock); |
|
|
|
|
|
|
|
bool exists = g_hash_table_remove(session->handles, &handle_id); |
|
|
|
bool exists = t_hash_table_remove(session->handles, &handle_id); |
|
|
|
|
|
|
|
*retcode = 463; |
|
|
|
if (!exists) |
|
|
|
@ -1409,13 +1422,13 @@ static const char *janus_detach(struct websocket_message *wm, JsonReader *reader |
|
|
|
LOCK(&janus_lock); |
|
|
|
|
|
|
|
struct janus_handle *handle = NULL; |
|
|
|
g_hash_table_steal_extended(janus_handles, &handle_id, NULL, (void **) &handle); |
|
|
|
t_hash_table_steal_extended(janus_handles, &handle_id, NULL, &handle); |
|
|
|
|
|
|
|
*retcode = 463; |
|
|
|
if (!handle) |
|
|
|
return "Could not detach handle from plugin"; |
|
|
|
if (handle->session != session) { |
|
|
|
g_hash_table_insert(janus_handles, &handle->id, handle); |
|
|
|
t_hash_table_insert(janus_handles, &handle->id, handle); |
|
|
|
return "Invalid session/handle association"; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1427,13 +1440,12 @@ static const char *janus_detach(struct websocket_message *wm, JsonReader *reader |
|
|
|
|
|
|
|
// janus_lock must be held |
|
|
|
static void janus_session_cleanup(struct janus_session *session) { |
|
|
|
GHashTableIter iter; |
|
|
|
g_hash_table_iter_init(&iter, session->handles); |
|
|
|
gpointer key; |
|
|
|
while (g_hash_table_iter_next(&iter, &key, NULL)) { |
|
|
|
uint64_t *handle_id = key; |
|
|
|
janus_handles_set_iter iter; |
|
|
|
t_hash_table_iter_init(&iter, session->handles); |
|
|
|
uint64_t *handle_id; |
|
|
|
while (t_hash_table_iter_next(&iter, &handle_id, NULL)) { |
|
|
|
struct janus_handle *handle = NULL; |
|
|
|
g_hash_table_steal_extended(janus_handles, handle_id, NULL, (void **) &handle); |
|
|
|
t_hash_table_steal_extended(janus_handles, handle_id, NULL, &handle); |
|
|
|
if (!handle) // bug? |
|
|
|
continue; |
|
|
|
janus_destroy_handle(handle); |
|
|
|
@ -1452,7 +1464,7 @@ static const char *janus_destroy(struct websocket_message *wm, JsonReader *reade |
|
|
|
LOCK(&janus_lock); |
|
|
|
|
|
|
|
struct janus_session *ht_session = NULL; |
|
|
|
g_hash_table_steal_extended(janus_sessions, &session->id, NULL, (void **) &ht_session); |
|
|
|
t_hash_table_steal_extended(janus_sessions, &session->id, NULL, &ht_session); |
|
|
|
if (ht_session != session) |
|
|
|
return "Sesssion ID not found"; // already removed/destroyed |
|
|
|
|
|
|
|
@ -1506,7 +1518,7 @@ static const char *janus_message(struct websocket_message *wm, JsonReader *reade |
|
|
|
|
|
|
|
LOCK(&janus_lock); |
|
|
|
|
|
|
|
struct janus_handle *handle = g_hash_table_lookup(janus_handles, &handle_id); |
|
|
|
struct janus_handle *handle = t_hash_table_lookup(janus_handles, &handle_id); |
|
|
|
|
|
|
|
const char *err = NULL; |
|
|
|
if (!handle || handle->session != session) { |
|
|
|
@ -1595,14 +1607,14 @@ static const char *janus_trickle(JsonReader *reader, struct janus_session *sessi |
|
|
|
{ |
|
|
|
LOCK(&janus_lock); |
|
|
|
|
|
|
|
struct janus_handle *handle = g_hash_table_lookup(janus_handles, &handle_id); |
|
|
|
struct janus_handle *handle = t_hash_table_lookup(janus_handles, &handle_id); |
|
|
|
|
|
|
|
if (!handle || !handle->room || handle->session != session) |
|
|
|
return "Unhandled request method"; |
|
|
|
|
|
|
|
call_id = janus_call_id(handle->room); |
|
|
|
|
|
|
|
struct janus_room *room = g_hash_table_lookup(janus_rooms, &handle->room); |
|
|
|
struct janus_room *room = t_hash_table_lookup(janus_rooms, &handle->room); |
|
|
|
|
|
|
|
if (room) |
|
|
|
call = call_get(&room->call_id); |
|
|
|
@ -1953,16 +1965,16 @@ done: |
|
|
|
|
|
|
|
void janus_init(void) { |
|
|
|
mutex_init(&janus_lock); |
|
|
|
janus_tokens = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); |
|
|
|
janus_sessions = g_hash_table_new(g_int64_hash, g_int64_equal); |
|
|
|
janus_handles = g_hash_table_new(g_int64_hash, g_int64_equal); |
|
|
|
janus_rooms = g_hash_table_new(g_int64_hash, g_int64_equal); |
|
|
|
janus_tokens = janus_tokens_ht_new(); |
|
|
|
janus_sessions = janus_sessions_ht_new(); |
|
|
|
janus_handles = janus_handles_ht_new(); |
|
|
|
janus_rooms = janus_rooms_ht_new(); |
|
|
|
// XXX timer thread to clean up orphaned sessions |
|
|
|
} |
|
|
|
void janus_free(void) { |
|
|
|
mutex_destroy(&janus_lock); |
|
|
|
g_hash_table_destroy(janus_tokens); |
|
|
|
g_hash_table_destroy(janus_sessions); |
|
|
|
g_hash_table_destroy(janus_handles); |
|
|
|
g_hash_table_destroy(janus_rooms); |
|
|
|
t_hash_table_destroy(janus_tokens); |
|
|
|
t_hash_table_destroy(janus_sessions); |
|
|
|
t_hash_table_destroy(janus_handles); |
|
|
|
t_hash_table_destroy(janus_rooms); |
|
|
|
} |