1 /**
2  * @file src/event.c  Baresip event handling
3  *
4  * Copyright (C) 2017 Creytiv.com
5  */
6 
7 #include <re.h>
8 #include <baresip.h>
9 #include "core.h"
10 
11 
event_class_name(enum ua_event ev)12 static const char *event_class_name(enum ua_event ev)
13 {
14 	switch (ev) {
15 
16 	case UA_EVENT_REGISTERING:
17 	case UA_EVENT_REGISTER_OK:
18 	case UA_EVENT_REGISTER_FAIL:
19 	case UA_EVENT_UNREGISTERING:
20 		return "register";
21 
22 	case UA_EVENT_SHUTDOWN:
23 	case UA_EVENT_EXIT:
24 		return "application";
25 
26 	case UA_EVENT_CALL_INCOMING:
27 	case UA_EVENT_CALL_RINGING:
28 	case UA_EVENT_CALL_PROGRESS:
29 	case UA_EVENT_CALL_ESTABLISHED:
30 	case UA_EVENT_CALL_CLOSED:
31 	case UA_EVENT_CALL_TRANSFER_FAILED:
32 	case UA_EVENT_CALL_DTMF_START:
33 	case UA_EVENT_CALL_DTMF_END:
34 	case UA_EVENT_CALL_RTCP:
35 		return "call";
36 
37 	default:
38 		return "other";
39 	}
40 }
41 
42 
add_rtcp_stats(struct odict * od_parent,const struct rtcp_stats * rs)43 static int add_rtcp_stats(struct odict *od_parent, const struct rtcp_stats *rs)
44 {
45 	struct odict *od = NULL, *tx = NULL, *rx = NULL;
46 	int err = 0;
47 
48 	if (!od_parent || !rs)
49 		return EINVAL;
50 
51 	err  = odict_alloc(&od, 8);
52 	err |= odict_alloc(&tx, 8);
53 	err |= odict_alloc(&rx, 8);
54 	if (err)
55 		goto out;
56 
57 	err  = odict_entry_add(tx, "sent", ODICT_INT, (int64_t)rs->tx.sent);
58 	err |= odict_entry_add(tx, "lost", ODICT_INT, (int64_t)rs->tx.lost);
59 	err |= odict_entry_add(tx, "jit", ODICT_INT, (int64_t)rs->tx.jit);
60 	if (err)
61 		goto out;
62 
63 	err  = odict_entry_add(rx, "sent", ODICT_INT, (int64_t)rs->rx.sent);
64 	err |= odict_entry_add(rx, "lost", ODICT_INT, (int64_t)rs->rx.lost);
65 	err |= odict_entry_add(rx, "jit", ODICT_INT, (int64_t)rs->rx.jit);
66 	if (err)
67 		goto out;
68 
69 	err  = odict_entry_add(od, "tx", ODICT_OBJECT, tx);
70 	err |= odict_entry_add(od, "rx", ODICT_OBJECT, rx);
71 	err |= odict_entry_add(od, "rtt", ODICT_INT, (int64_t)rs->rtt);
72 	if (err)
73 		goto out;
74 
75 	/* add object to the parent */
76 	err = odict_entry_add(od_parent, "rtcp_stats", ODICT_OBJECT, od);
77 	if (err)
78 		goto out;
79 
80  out:
81 	mem_deref(od);
82 	mem_deref(tx);
83 	mem_deref(rx);
84 
85 	return err;
86 }
87 
88 
event_encode_dict(struct odict * od,struct ua * ua,enum ua_event ev,struct call * call,const char * prm)89 int event_encode_dict(struct odict *od, struct ua *ua, enum ua_event ev,
90 		      struct call *call, const char *prm)
91 {
92 	const char *event_str = uag_event_str(ev);
93 	int err = 0;
94 
95 	if (!od)
96 		return EINVAL;
97 
98 	err |= odict_entry_add(od, "type", ODICT_STRING, event_str);
99 	err |= odict_entry_add(od, "class",
100 			       ODICT_STRING, event_class_name(ev));
101 
102 	if (ua) {
103 		err |= odict_entry_add(od, "accountaor",
104 				       ODICT_STRING, ua_aor(ua));
105 	}
106 
107 	if (err)
108 		goto out;
109 
110 	if (call) {
111 
112 		const char *dir;
113 
114 		dir = call_is_outgoing(call) ? "outgoing" : "incoming";
115 
116 		err |= odict_entry_add(od, "direction", ODICT_STRING, dir);
117 		err |= odict_entry_add(od, "peeruri",
118 				       ODICT_STRING, call_peeruri(call));
119 		err |= odict_entry_add(od, "id", ODICT_STRING, call_id(call));
120 		if (err)
121 			goto out;
122 	}
123 
124 	if (str_isset(prm)) {
125 		err = odict_entry_add(od, "param", ODICT_STRING, prm);
126 		if (err)
127 			goto out;
128 	}
129 
130 	if (ev == UA_EVENT_CALL_RTCP) {
131 		struct stream *strm = NULL;
132 
133 		if (0 == str_casecmp(prm, "audio"))
134 			strm = audio_strm(call_audio(call));
135 #ifdef USE_VIDEO
136 		else if (0 == str_casecmp(prm, "video"))
137 			strm = video_strm(call_video(call));
138 #endif
139 
140 		err = add_rtcp_stats(od, stream_rtcp_stats(strm));
141 		if (err)
142 			goto out;
143 	}
144 
145  out:
146 
147 	return err;
148 }
149 
150 
151 /**
152  * Get the name of the User-Agent event
153  *
154  * @param ev User-Agent event
155  *
156  * @return Name of the event
157  */
uag_event_str(enum ua_event ev)158 const char *uag_event_str(enum ua_event ev)
159 {
160 	switch (ev) {
161 
162 	case UA_EVENT_REGISTERING:          return "REGISTERING";
163 	case UA_EVENT_REGISTER_OK:          return "REGISTER_OK";
164 	case UA_EVENT_REGISTER_FAIL:        return "REGISTER_FAIL";
165 	case UA_EVENT_UNREGISTERING:        return "UNREGISTERING";
166 	case UA_EVENT_SHUTDOWN:             return "SHUTDOWN";
167 	case UA_EVENT_EXIT:                 return "EXIT";
168 	case UA_EVENT_CALL_INCOMING:        return "CALL_INCOMING";
169 	case UA_EVENT_CALL_RINGING:         return "CALL_RINGING";
170 	case UA_EVENT_CALL_PROGRESS:        return "CALL_PROGRESS";
171 	case UA_EVENT_CALL_ESTABLISHED:     return "CALL_ESTABLISHED";
172 	case UA_EVENT_CALL_CLOSED:          return "CALL_CLOSED";
173 	case UA_EVENT_CALL_TRANSFER_FAILED: return "TRANSFER_FAILED";
174 	case UA_EVENT_CALL_DTMF_START:      return "CALL_DTMF_START";
175 	case UA_EVENT_CALL_DTMF_END:        return "CALL_DTMF_END";
176 	case UA_EVENT_CALL_RTCP:            return "CALL_RTCP";
177 	default: return "?";
178 	}
179 }
180