Statistics
| Branch: | Revision:

janus-gateway / events.c @ d97e0296

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

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

    
132
        /* Enqueue the event */
133
        g_async_queue_push(events, event);
134
}
135

    
136
void *janus_events_thread(void *data) {
137
        JANUS_LOG(LOG_VERB, "Joining Events handler thread\n");
138
        json_t *event = NULL;
139

    
140
        while(eventsenabled) {
141
                /* Any event in queue? */
142
                event = g_async_queue_pop(events);
143
                if(event == NULL)
144
                        continue;
145
                if(event == &exit_event)
146
                        break;
147

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

    
164
                /* Unref the final event reference, interested handlers will have their own reference */
165
                json_decref(event);
166
        }
167

    
168
        JANUS_LOG(LOG_VERB, "Leaving EchoTest handler thread\n");
169
        return NULL;
170
}