Statistics
| Branch: | Revision:

janus-gateway / events.c @ eba63a19

History | View | Annotate | Download (6.12 KB)

1
/*! \file    events.c
2
 * \author   Lorenzo Miniero <lorenzo@meetecho.com>
3
 * \copyright GNU General Public License v3
4
 * \brief    Event handler notifications
5
 * \details  Event handler plugins can receive events from the Janus core
6
 * and other plugins, in order to handle them somehow. This methods
7
 * provide helpers to notify events to such handlers. 
8
 * 
9
 * \ingroup core
10
 * \ref core
11
 */
12
 
13
#include <stdarg.h>
14

    
15
#include "events.h"
16
#include "utils.h"
17

    
18
static gboolean eventsenabled = FALSE;
19
static GHashTable *eventhandlers = NULL;
20

    
21
static GAsyncQueue *events = NULL;
22
static json_t exit_event;
23

    
24
static GThread *events_thread;
25
void *janus_events_thread(void *data);
26

    
27
int janus_events_init(gboolean enabled, GHashTable *handlers) {
28
        /* We setup a thread for passing events to the handlers */
29
        GError *error = NULL;
30
        events_thread = g_thread_try_new("janus events thread", janus_events_thread, NULL, &error);
31
        if(error != NULL) {
32
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the Events handler thread...\n", error->code, error->message ? error->message : "??");
33
                return -1;
34
        }
35
        events = g_async_queue_new();
36
        eventhandlers = handlers;
37
        eventsenabled = enabled;
38
        return 0;
39
}
40

    
41
void janus_events_deinit(void) {
42
        eventsenabled = FALSE;
43

    
44
        g_async_queue_push(events, &exit_event);
45
        if(events_thread != NULL) {
46
                g_thread_join(events_thread);
47
                events_thread = NULL;
48
        }
49
}
50

    
51
gboolean janus_events_is_enabled(void) {
52
        return eventsenabled;
53
}
54

    
55
void janus_events_notify_handlers(int type, guint64 session_id, ...) {
56
        if(!eventsenabled || eventhandlers == NULL || g_hash_table_size(eventhandlers) == 0)
57
                return;
58

    
59
        /* Prepare the event to notify as a Jansson json_t object */
60
        json_t *event = json_object();
61
        json_object_set_new(event, "type", json_integer(type));
62
        json_object_set_new(event, "timestamp", json_integer(janus_get_monotonic_time()));
63
        if(type != JANUS_EVENT_TYPE_CORE) {                        /* Core events don't have a session ID */
64
                if(session_id == 0 && (type == JANUS_EVENT_TYPE_PLUGIN || type == JANUS_EVENT_TYPE_TRANSPORT)) {
65
                        /* ... but plugin/transport events may not have one either */
66
                } else {
67
                        json_object_set_new(event, "session_id", json_integer(session_id));
68
                }
69
        }
70
        json_t *body = NULL;
71
        if(type != JANUS_EVENT_TYPE_MEDIA && type != JANUS_EVENT_TYPE_WEBRTC && type != JANUS_EVENT_TYPE_CORE)
72
                body = json_object();
73

    
74
        /* Each type may require different arguments */
75
        va_list args;
76
        va_start(args, session_id);
77
        switch(type) {
78
                case JANUS_EVENT_TYPE_SESSION: {
79
                        /* For sessions, there's just a generic event name (what happened) */
80
                        char *name = va_arg(args, char *);
81
                        json_object_set_new(body, "name", json_string(name));
82
                        break;
83
                }
84
                case JANUS_EVENT_TYPE_HANDLE: {
85
                        /* For handles, there's the handle ID, a generic event name (what happened)
86
                         * and the plugin package name this handle is (or was) attached to */
87
                        guint64 handle_id = va_arg(args, guint64);
88
                        json_object_set_new(event, "handle_id", json_integer(handle_id));
89
                        char *name = va_arg(args, char *);
90
                        json_object_set_new(body, "name", json_string(name));
91
                        char *plugin = va_arg(args, char *);
92
                        json_object_set_new(body, "plugin", json_string(plugin));
93
                        break;
94
                }
95
                case JANUS_EVENT_TYPE_JSEP: {
96
                        /* For JSEP-related events, there's the handle ID, whether the SDP is local or remote, the JSEP type and the SDP itself */
97
                        guint64 handle_id = va_arg(args, guint64);
98
                        json_object_set_new(event, "handle_id", json_integer(handle_id));
99
                        char *owner = va_arg(args, char *);
100
                        json_object_set_new(body, "owner", json_string(owner));
101
                        json_t *jsep = json_object();
102
                        char *sdp_type = va_arg(args, char *);
103
                        json_object_set_new(jsep, "type", json_string(sdp_type));
104
                        char *sdp = va_arg(args, char *);
105
                        json_object_set_new(jsep, "sdp", json_string(sdp));
106
                        json_object_set_new(body, "jsep", jsep);
107
                        break;
108
                }
109
                case JANUS_EVENT_TYPE_WEBRTC:
110
                case JANUS_EVENT_TYPE_MEDIA: {
111
                        /* For WebRTC and media-related events, there's the handle ID and a json_t object with info on what happened */
112
                        guint64 handle_id = va_arg(args, guint64);
113
                        json_object_set_new(event, "handle_id", json_integer(handle_id));
114
                        /* The body is what we get from the event */
115
                        body = va_arg(args, json_t *);
116
                        break;
117
                }
118
                case JANUS_EVENT_TYPE_PLUGIN:
119
                case JANUS_EVENT_TYPE_TRANSPORT: {
120
                        /* For plugin-originated events, there's the handle ID, the plugin name, and a generic, plugin specific, json_t object */
121
                        guint64 handle_id = va_arg(args, guint64);
122
                        if(handle_id > 0)        /* Plugins and transports may not specify a session and handle ID for out of context events */
123
                                json_object_set_new(event, "handle_id", json_integer(handle_id));
124
                        char *name = va_arg(args, char *);
125
                        json_object_set_new(body, "plugin", json_string(name));
126
                        json_t *data = va_arg(args, json_t *);
127
                        json_object_set(body, "data", data);
128
                        break;
129
                }
130
                case JANUS_EVENT_TYPE_CORE: {
131
                        /* For core-related events, there's a json_t object with info on what happened */
132
                        body = va_arg(args, json_t *);
133
                        break;
134
                }
135
                default:
136
                        JANUS_LOG(LOG_WARN, "Unknown event type '%d'\n", type);
137
                        json_decref(event);
138
                        json_decref(body);
139
                        return;
140
        }
141
        json_object_set_new(event, "event", body);
142
        va_end(args);
143

    
144
        /* Enqueue the event */
145
        g_async_queue_push(events, event);
146
}
147

    
148
void *janus_events_thread(void *data) {
149
        JANUS_LOG(LOG_VERB, "Joining Events handler thread\n");
150
        json_t *event = NULL;
151

    
152
        while(eventsenabled) {
153
                /* Any event in queue? */
154
                event = g_async_queue_pop(events);
155
                if(event == NULL)
156
                        continue;
157
                if(event == &exit_event)
158
                        break;
159

    
160
                /* Notify all interested handlers, increasing the event reference to make sure it's not lost because of errors */
161
                int type = json_integer_value(json_object_get(event, "type"));
162
                GHashTableIter iter;
163
                gpointer value;
164
                g_hash_table_iter_init(&iter, eventhandlers);
165
                json_incref(event);
166
                while(g_hash_table_iter_next(&iter, NULL, &value)) {
167
                        janus_eventhandler *e = value;
168
                        if(e == NULL)
169
                                continue;
170
                        if(!janus_flags_is_set(&e->events_mask, type))
171
                                continue;
172
                        e->incoming_event(event);
173
                }
174
                json_decref(event);
175

    
176
                /* Unref the final event reference, interested handlers will have their own reference */
177
                json_decref(event);
178
        }
179

    
180
        JANUS_LOG(LOG_VERB, "Leaving EchoTest handler thread\n");
181
        return NULL;
182
}