Statistics
| Branch: | Revision:

janus-gateway / events.c @ 84c1291c

History | View | Annotate | Download (5.79 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
                json_object_set_new(event, "session_id", json_integer(session_id));
65
        json_t *body = NULL;
66
        if(type != JANUS_EVENT_TYPE_WEBRTC && type != JANUS_EVENT_TYPE_CORE)
67
                body = json_object();
68

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

    
138
        /* Enqueue the event */
139
        g_async_queue_push(events, event);
140
}
141

    
142
void *janus_events_thread(void *data) {
143
        JANUS_LOG(LOG_VERB, "Joining Events handler thread\n");
144
        json_t *event = NULL;
145

    
146
        while(eventsenabled) {
147
                /* Any event in queue? */
148
                event = g_async_queue_pop(events);
149
                if(event == NULL)
150
                        continue;
151
                if(event == &exit_event)
152
                        break;
153

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

    
170
                /* Unref the final event reference, interested handlers will have their own reference */
171
                json_decref(event);
172
        }
173

    
174
        JANUS_LOG(LOG_VERB, "Leaving EchoTest handler thread\n");
175
        return NULL;
176
}