diff options
author | mannol <eniz_vukovic@hotmail.com> | 2015-02-15 22:41:10 +0100 |
---|---|---|
committer | mannol <eniz_vukovic@hotmail.com> | 2015-02-15 22:41:10 +0100 |
commit | 8c245affb1f7dac2baab263ad0c4e19314073d71 (patch) | |
tree | 9dc5d6af65009e6b7cd0012717ab9e7f37d50011 /toxav | |
parent | aad857527cd63b5f79786df0c1aab50f4de87774 (diff) |
Started adjusting msi backend to new api
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/av_test.c | 9 | ||||
-rw-r--r-- | toxav/msi.c | 743 | ||||
-rw-r--r-- | toxav/msi.h | 44 | ||||
-rw-r--r-- | toxav/toxav.c | 1 |
4 files changed, 173 insertions, 624 deletions
diff --git a/toxav/av_test.c b/toxav/av_test.c index 1e5e4ad7..3270f39c 100644 --- a/toxav/av_test.c +++ b/toxav/av_test.c | |||
@@ -252,13 +252,13 @@ int main (int argc, char** argv) | |||
252 | } | 252 | } |
253 | 253 | ||
254 | printf("\nTrying regular call (Audio and Video)...\n"); | 254 | printf("\nTrying regular call (Audio and Video)...\n"); |
255 | // REGULAR_CALL_FLOW(48, 4000); | 255 | REGULAR_CALL_FLOW(48, 4000); |
256 | 256 | ||
257 | printf("\nTrying regular call (Audio only)...\n"); | 257 | printf("\nTrying regular call (Audio only)...\n"); |
258 | // REGULAR_CALL_FLOW(48, 0); | 258 | REGULAR_CALL_FLOW(48, 0); |
259 | 259 | ||
260 | printf("\nTrying regular call (Video only)...\n"); | 260 | printf("\nTrying regular call (Video only)...\n"); |
261 | // REGULAR_CALL_FLOW(0, 4000); | 261 | REGULAR_CALL_FLOW(0, 4000); |
262 | 262 | ||
263 | #undef REGULAR_CALL_FLOW | 263 | #undef REGULAR_CALL_FLOW |
264 | 264 | ||
@@ -328,7 +328,8 @@ int main (int argc, char** argv) | |||
328 | } | 328 | } |
329 | } | 329 | } |
330 | 330 | ||
331 | while (!AliceCC.ended || !BobCC.ended) | 331 | /* Alice will not receive end state */ |
332 | while (!BobCC.ended) | ||
332 | iterate(Bsn, AliceAV, BobAV); | 333 | iterate(Bsn, AliceAV, BobAV); |
333 | 334 | ||
334 | printf("Success!\n"); | 335 | printf("Success!\n"); |
diff --git a/toxav/msi.c b/toxav/msi.c index 3de686cc..706e21d7 100644 --- a/toxav/msi.c +++ b/toxav/msi.c | |||
@@ -48,43 +48,50 @@ | |||
48 | * |id [1 byte]| |size [1 byte]| |data [$size bytes]| |...{repeat}| |0 {end byte}| | 48 | * |id [1 byte]| |size [1 byte]| |data [$size bytes]| |...{repeat}| |0 {end byte}| |
49 | */ | 49 | */ |
50 | 50 | ||
51 | typedef uint8_t MSIRawCSettingsType[23]; | ||
52 | |||
53 | typedef enum { | 51 | typedef enum { |
54 | IDRequest = 1, | 52 | IDRequest = 1, |
55 | IDResponse, | 53 | IDResponse, |
56 | IDReason, | 54 | IDReason, |
57 | IDCallId, | 55 | IDCapabilities, |
58 | IDCSettings, | ||
59 | 56 | ||
60 | } MSIHeaderID; | 57 | } MSIHeaderID; |
61 | 58 | ||
59 | /** | ||
60 | * Headers | ||
61 | */ | ||
62 | typedef enum { | 62 | typedef enum { |
63 | TypeRequest, | 63 | type_request, |
64 | TypeResponse, | 64 | type_response, |
65 | |||
66 | } MSIMessageType; | 65 | } MSIMessageType; |
67 | 66 | ||
68 | typedef enum { | 67 | typedef enum { |
69 | invite, | 68 | requ_invite, |
70 | start, | 69 | requ_start, |
71 | cancel, | 70 | requ_cancel, |
72 | reject, | 71 | requ_reject, |
73 | end, | 72 | requ_end, |
74 | |||
75 | } MSIRequest; | 73 | } MSIRequest; |
76 | 74 | ||
77 | typedef enum { | 75 | typedef enum { |
78 | ringing, | 76 | resp_ringing, |
79 | starting, | 77 | resp_starting, |
80 | ending, | 78 | resp_ending, |
81 | error | 79 | resp_error, |
82 | |||
83 | } MSIResponse; | 80 | } MSIResponse; |
84 | 81 | ||
82 | typedef enum { | ||
83 | res_undisclosed, | ||
84 | } MSIReason; | ||
85 | |||
86 | typedef enum { | ||
87 | cap_saudio, /* sending audio */ | ||
88 | cap_svideo, /* sending video */ | ||
89 | cap_raudio, /* receiving audio */ | ||
90 | cap_rvideo, /* receiving video */ | ||
91 | } MSICapabilities; | ||
85 | 92 | ||
86 | #define GENERIC_HEADER(header, val_type) \ | 93 | #define GENERIC_HEADER(header, val_type) \ |
87 | typedef struct _MSIHeader##header { \ | 94 | typedef struct { \ |
88 | val_type value; \ | 95 | val_type value; \ |
89 | _Bool exists; \ | 96 | _Bool exists; \ |
90 | } MSIHeader##header; | 97 | } MSIHeader##header; |
@@ -92,44 +99,77 @@ _Bool exists; \ | |||
92 | 99 | ||
93 | GENERIC_HEADER ( Request, MSIRequest ) | 100 | GENERIC_HEADER ( Request, MSIRequest ) |
94 | GENERIC_HEADER ( Response, MSIResponse ) | 101 | GENERIC_HEADER ( Response, MSIResponse ) |
95 | GENERIC_HEADER ( CallId, MSICallIDType ) | 102 | GENERIC_HEADER ( Reason, MSIReason ) |
96 | GENERIC_HEADER ( Reason, MSIReasonStrType ) | 103 | GENERIC_HEADER ( Capabilities, MSICapabilities ) |
97 | GENERIC_HEADER ( CSettings, MSIRawCSettingsType ) | ||
98 | |||
99 | |||
100 | typedef struct _MSIMessage { | ||
101 | |||
102 | MSIHeaderRequest request; | ||
103 | MSIHeaderResponse response; | ||
104 | MSIHeaderReason reason; | ||
105 | MSIHeaderCallId callid; | ||
106 | MSIHeaderCSettings csettings; | ||
107 | 104 | ||
108 | int friend_id; | ||
109 | 105 | ||
106 | typedef struct { | ||
107 | MSIHeaderRequest request; | ||
108 | MSIHeaderResponse response; | ||
109 | MSIHeaderReason reason; | ||
110 | MSIHeaderCapabilities capabilities; | ||
110 | } MSIMessage; | 111 | } MSIMessage; |
111 | 112 | ||
112 | 113 | ||
113 | static void invoke_callback(MSISession *s, int32_t c, MSICallbackID i) | 114 | static void invoke_callback(MSISession *s, int32_t c, MSICallbackID i) |
114 | { | 115 | { |
115 | if ( s->callbacks[i].first ) { | 116 | if ( s->callbacks[i] ) { |
116 | LOGGER_DEBUG("Invoking callback function: %d", i); | 117 | LOGGER_DEBUG("Invoking callback function: %d", i); |
118 | s->callbacks[i] ( s->agent_handler, c ); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * Create the message. | ||
124 | */ | ||
125 | static MSIMessage *msi_new_message ( MSIMessageType type, const uint8_t type_value ) | ||
126 | { | ||
127 | MSIMessage *retu = calloc ( sizeof ( MSIMessage ), 1 ); | ||
128 | |||
129 | if ( retu == NULL ) { | ||
130 | LOGGER_WARNING("Allocation failed! Program might misbehave!"); | ||
131 | return NULL; | ||
132 | } | ||
133 | |||
134 | if ( type == type_request ) { | ||
135 | retu->request.exists = 1; | ||
136 | retu->request.value = type_value; | ||
117 | 137 | ||
118 | s->callbacks[i].first( s->agent_handler, c, s->callbacks[i].second ); | 138 | } else { |
139 | retu->response.exists = 1; | ||
140 | retu->response.value = type_value; | ||
119 | } | 141 | } |
142 | |||
143 | return retu; | ||
120 | } | 144 | } |
121 | 145 | ||
146 | |||
122 | /** | 147 | /** |
123 | * Parse raw 'data' received from socket into MSIMessage struct. | 148 | * Parse raw data received from socket into MSIMessage struct. |
124 | * Every message has to have end value of 'end_byte' or _undefined_ behavior | ||
125 | * occures. The best practice is to check the end of the message at the handle_packet. | ||
126 | */ | 149 | */ |
127 | static int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) | 150 | static int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) |
128 | { | 151 | { |
152 | #define PARSE_HEADER(bytes, header, constraint, enum_high_limit) do {\ | ||
153 | if ((constraint -= 3) < 1) { \ | ||
154 | LOGGER_ERROR("Read over length!"); \ | ||
155 | return -1; \ | ||
156 | } \ | ||
157 | \ | ||
158 | if ( bytes[1] != 1 ) { \ | ||
159 | LOGGER_ERROR("Invalid data size!"); \ | ||
160 | return -1; \ | ||
161 | } \ | ||
162 | \ | ||
163 | if ( bytes[2] > enum_high_limit ) { \ | ||
164 | LOGGER_ERROR("Failed enum high limit!"); \ | ||
165 | return -1; \ | ||
166 | } \ | ||
167 | \ | ||
168 | header.value = bytes[2]; \ | ||
169 | header.exists = 1; \ | ||
170 | bytes += 3; \ | ||
171 | } while(0) | ||
129 | 172 | ||
130 | #define FAIL_CONSTRAINT(constraint, wanted) if ((constraint -= wanted) < 1) { LOGGER_ERROR("Read over length!"); return -1; } | ||
131 | #define FAIL_SIZE(byte, valid) if ( byte != valid ) { LOGGER_ERROR("Invalid data size!"); return -1; } | ||
132 | #define FAIL_LIMITS(byte, high) if ( byte > high ) { LOGGER_ERROR("Failed limit!"); return -1; } | ||
133 | 173 | ||
134 | if ( msg == NULL ) { | 174 | if ( msg == NULL ) { |
135 | LOGGER_ERROR("Could not parse message: no storage!"); | 175 | LOGGER_ERROR("Could not parse message: no storage!"); |
@@ -147,49 +187,22 @@ static int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t lengt | |||
147 | while ( *it ) {/* until end byte is hit */ | 187 | while ( *it ) {/* until end byte is hit */ |
148 | switch (*it) { | 188 | switch (*it) { |
149 | case IDRequest: | 189 | case IDRequest: |
150 | FAIL_CONSTRAINT(size_constraint, 3); | 190 | PARSE_HEADER(it, msg->request, size_constraint, requ_end); |
151 | FAIL_SIZE(it[1], 1); | ||
152 | // FAIL_LIMITS(it[2], invite, end); | ||
153 | FAIL_LIMITS(it[2], end); | ||
154 | msg->request.value = it[2]; | ||
155 | it += 3; | ||
156 | msg->request.exists = 1; | ||
157 | break; | 191 | break; |
158 | 192 | ||
159 | case IDResponse: | 193 | case IDResponse: |
160 | FAIL_CONSTRAINT(size_constraint, 3); | 194 | PARSE_HEADER(it, msg->response, size_constraint, resp_error); |
161 | FAIL_SIZE(it[1], 1); | ||
162 | // FAIL_LIMITS(it[2], ringing, error); | ||
163 | FAIL_LIMITS(it[2], error); | ||
164 | msg->response.value = it[2]; | ||
165 | it += 3; | 195 | it += 3; |
166 | msg->response.exists = 1; | ||
167 | break; | 196 | break; |
168 | 197 | ||
169 | case IDCallId: | ||
170 | FAIL_CONSTRAINT(size_constraint, sizeof(MSICallIDType) + 2); | ||
171 | FAIL_SIZE(it[1], sizeof(MSICallIDType)); | ||
172 | memcpy(msg->callid.value, it + 2, sizeof(MSICallIDType)); | ||
173 | it += sizeof(MSICallIDType) + 2; | ||
174 | msg->callid.exists = 1; | ||
175 | break; | ||
176 | |||
177 | case IDReason: | 198 | case IDReason: |
178 | FAIL_CONSTRAINT(size_constraint, sizeof(MSIReasonStrType) + 2); | 199 | PARSE_HEADER(it, msg->reason, size_constraint, res_undisclosed); |
179 | FAIL_SIZE(it[1], sizeof(MSIReasonStrType)); | ||
180 | memcpy(msg->reason.value, it + 2, sizeof(MSIReasonStrType)); | ||
181 | it += sizeof(MSIReasonStrType) + 2; | ||
182 | msg->reason.exists = 1; | ||
183 | break; | 200 | break; |
184 | 201 | ||
185 | case IDCSettings: | 202 | case IDCapabilities: |
186 | FAIL_CONSTRAINT(size_constraint, sizeof(MSIRawCSettingsType) + 2); | 203 | PARSE_HEADER(it, msg->capabilities, size_constraint, requ_end); |
187 | FAIL_SIZE(it[1], sizeof(MSIRawCSettingsType)); | ||
188 | memcpy(msg->csettings.value, it + 2, sizeof(MSIRawCSettingsType)); | ||
189 | it += sizeof(MSIRawCSettingsType) + 2; | ||
190 | msg->csettings.exists = 1; | ||
191 | break; | 204 | break; |
192 | 205 | ||
193 | default: | 206 | default: |
194 | LOGGER_ERROR("Invalid id byte"); | 207 | LOGGER_ERROR("Invalid id byte"); |
195 | return -1; | 208 | return -1; |
@@ -198,37 +211,14 @@ static int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t lengt | |||
198 | } | 211 | } |
199 | 212 | ||
200 | return 0; | 213 | return 0; |
201 | } | ||
202 | |||
203 | /** | ||
204 | * Create the message. | ||
205 | */ | ||
206 | MSIMessage *msi_new_message ( MSIMessageType type, const uint8_t type_value ) | ||
207 | { | ||
208 | MSIMessage *retu = calloc ( sizeof ( MSIMessage ), 1 ); | ||
209 | 214 | ||
210 | if ( retu == NULL ) { | 215 | #undef PARSE_HEADER |
211 | LOGGER_WARNING("Allocation failed! Program might misbehave!"); | ||
212 | return NULL; | ||
213 | } | ||
214 | |||
215 | if ( type == TypeRequest ) { | ||
216 | retu->request.exists = 1; | ||
217 | retu->request.value = type_value; | ||
218 | |||
219 | } else { | ||
220 | retu->response.exists = 1; | ||
221 | retu->response.value = type_value; | ||
222 | } | ||
223 | |||
224 | return retu; | ||
225 | } | 216 | } |
226 | 217 | ||
227 | |||
228 | /** | 218 | /** |
229 | * Parse data from handle_packet. | 219 | * Parse data from handle_packet. |
230 | */ | 220 | */ |
231 | MSIMessage *parse_recv ( const uint8_t *data, uint16_t length ) | 221 | static MSIMessage *parse_in ( const uint8_t *data, uint16_t length ) |
232 | { | 222 | { |
233 | if ( data == NULL ) { | 223 | if ( data == NULL ) { |
234 | LOGGER_WARNING("Tried to parse empty message!"); | 224 | LOGGER_WARNING("Tried to parse empty message!"); |
@@ -255,11 +245,8 @@ MSIMessage *parse_recv ( const uint8_t *data, uint16_t length ) | |||
255 | /** | 245 | /** |
256 | * Speaks for itself. | 246 | * Speaks for itself. |
257 | */ | 247 | */ |
258 | uint8_t *format_output ( uint8_t *dest, | 248 | static uint8_t *prepare_header ( MSIHeaderID id, uint8_t *dest, const void *value, |
259 | MSIHeaderID id, | 249 | uint8_t value_len, uint16_t *length ) |
260 | const void *value, | ||
261 | uint8_t value_len, | ||
262 | uint16_t *length ) | ||
263 | { | 250 | { |
264 | if ( dest == NULL ) { | 251 | if ( dest == NULL ) { |
265 | LOGGER_ERROR("No destination space!"); | 252 | LOGGER_ERROR("No destination space!"); |
@@ -285,9 +272,9 @@ uint8_t *format_output ( uint8_t *dest, | |||
285 | 272 | ||
286 | 273 | ||
287 | /** | 274 | /** |
288 | * Parse MSIMessage to send. | 275 | * Parse MSIMessage to send. Returns size in bytes of the parsed message |
289 | */ | 276 | */ |
290 | uint16_t parse_send ( MSIMessage *msg, uint8_t *dest ) | 277 | static uint16_t parse_out ( MSIMessage *msg, uint8_t *dest ) |
291 | { | 278 | { |
292 | if (msg == NULL) { | 279 | if (msg == NULL) { |
293 | LOGGER_ERROR("No message!"); | 280 | LOGGER_ERROR("No message!"); |
@@ -304,24 +291,21 @@ uint16_t parse_send ( MSIMessage *msg, uint8_t *dest ) | |||
304 | 291 | ||
305 | if (msg->request.exists) { | 292 | if (msg->request.exists) { |
306 | uint8_t cast = msg->request.value; | 293 | uint8_t cast = msg->request.value; |
307 | it = format_output(it, IDRequest, &cast, 1, &size); | 294 | it = prepare_header(IDRequest, it, &cast, 1, &size); |
308 | } | 295 | } |
309 | 296 | ||
310 | if (msg->response.exists) { | 297 | if (msg->response.exists) { |
311 | uint8_t cast = msg->response.value; | 298 | uint8_t cast = msg->response.value; |
312 | it = format_output(it, IDResponse, &cast, 1, &size); | 299 | it = prepare_header(IDResponse, it, &cast, 1, &size); |
313 | } | ||
314 | |||
315 | if (msg->callid.exists) { | ||
316 | it = format_output(it, IDCallId, &msg->callid.value, sizeof(msg->callid.value), &size); | ||
317 | } | 300 | } |
318 | 301 | ||
319 | if (msg->reason.exists) { | 302 | if (msg->reason.exists) { |
320 | it = format_output(it, IDReason, &msg->reason.value, sizeof(msg->reason.value), &size); | 303 | it = prepare_header(IDReason, it, &msg->reason.value, sizeof(msg->reason.value), &size); |
321 | } | 304 | } |
322 | 305 | ||
323 | if (msg->csettings.exists) { | 306 | if (msg->capabilities.exists) { |
324 | it = format_output(it, IDCSettings, &msg->csettings.value, sizeof(msg->csettings.value), &size); | 307 | it = prepare_header(IDCapabilities, it, &msg->capabilities.value, |
308 | sizeof(msg->capabilities.value), &size); | ||
325 | } | 309 | } |
326 | 310 | ||
327 | *it = 0; | 311 | *it = 0; |
@@ -330,267 +314,17 @@ uint16_t parse_send ( MSIMessage *msg, uint8_t *dest ) | |||
330 | return size; | 314 | return size; |
331 | } | 315 | } |
332 | 316 | ||
333 | void msi_msg_set_reason ( MSIMessage *msg, const MSIReasonStrType value ) | 317 | static int send_message ( MSICall *call, MSIMessage *msg, uint32_t to ) |
334 | { | ||
335 | if ( !msg ) return; | ||
336 | |||
337 | msg->reason.exists = 1; | ||
338 | memcpy(msg->reason.value, value, sizeof(MSIReasonStrType)); | ||
339 | } | ||
340 | |||
341 | void msi_msg_set_callid ( MSIMessage *msg, const MSICallIDType value ) | ||
342 | { | ||
343 | if ( !msg ) return; | ||
344 | |||
345 | msg->callid.exists = 1; | ||
346 | memcpy(msg->callid.value, value, sizeof(MSICallIDType)); | ||
347 | } | ||
348 | |||
349 | void msi_msg_set_csettings ( MSIMessage *msg, const MSICSettings *value ) | ||
350 | { | ||
351 | if ( !msg ) return; | ||
352 | |||
353 | msg->csettings.exists = 1; | ||
354 | |||
355 | msg->csettings.value[0] = value->call_type; | ||
356 | uint8_t *iter = msg->csettings.value + 1; | ||
357 | |||
358 | /* Video bitrate */ | ||
359 | uint32_t lval = htonl(value->video_bitrate); | ||
360 | memcpy(iter, &lval, 4); | ||
361 | iter += 4; | ||
362 | |||
363 | /* Video max width */ | ||
364 | uint16_t sval = htons(value->max_video_width); | ||
365 | memcpy(iter, &sval, 2); | ||
366 | iter += 2; | ||
367 | |||
368 | /* Video max height */ | ||
369 | sval = htons(value->max_video_height); | ||
370 | memcpy(iter, &sval, 2); | ||
371 | iter += 2; | ||
372 | |||
373 | /* Audio bitrate */ | ||
374 | lval = htonl(value->audio_bitrate); | ||
375 | memcpy(iter, &lval, 4); | ||
376 | iter += 4; | ||
377 | |||
378 | /* Audio frame duration */ | ||
379 | sval = htons(value->audio_frame_duration); | ||
380 | memcpy(iter, &sval, 2); | ||
381 | iter += 2; | ||
382 | |||
383 | /* Audio sample rate */ | ||
384 | lval = htonl(value->audio_sample_rate); | ||
385 | memcpy(iter, &lval, 4); | ||
386 | iter += 4; | ||
387 | |||
388 | /* Audio channels */ | ||
389 | lval = htonl(value->audio_channels); | ||
390 | memcpy(iter, &lval, 4); | ||
391 | } | ||
392 | |||
393 | void msi_msg_get_csettings ( MSIMessage *msg, MSICSettings *dest ) | ||
394 | { | ||
395 | if ( !msg || !dest || !msg->csettings.exists ) return; | ||
396 | |||
397 | dest->call_type = msg->csettings.value[0]; | ||
398 | uint8_t *iter = msg->csettings.value + 1; | ||
399 | |||
400 | memcpy(&dest->video_bitrate, iter, 4); | ||
401 | iter += 4; | ||
402 | dest->video_bitrate = ntohl(dest->video_bitrate); | ||
403 | |||
404 | memcpy(&dest->max_video_width, iter, 2); | ||
405 | iter += 2; | ||
406 | dest->max_video_width = ntohs(dest->max_video_width); | ||
407 | |||
408 | memcpy(&dest->max_video_height, iter, 2); | ||
409 | iter += 2; | ||
410 | dest->max_video_height = ntohs(dest->max_video_height); | ||
411 | |||
412 | memcpy(&dest->audio_bitrate, iter, 4); | ||
413 | iter += 4; | ||
414 | dest->audio_bitrate = ntohl(dest->audio_bitrate); | ||
415 | |||
416 | memcpy(&dest->audio_frame_duration, iter, 2); | ||
417 | iter += 2; | ||
418 | dest->audio_frame_duration = ntohs(dest->audio_frame_duration); | ||
419 | |||
420 | memcpy(&dest->audio_sample_rate, iter, 4); | ||
421 | iter += 4; | ||
422 | dest->audio_sample_rate = ntohl(dest->audio_sample_rate); | ||
423 | |||
424 | memcpy(&dest->audio_channels, iter, 4); | ||
425 | dest->audio_channels = ntohl(dest->audio_channels); | ||
426 | } | ||
427 | |||
428 | typedef struct _Timer { | ||
429 | void (*func)(struct _Timer *); | ||
430 | uint64_t timeout; | ||
431 | MSISession *session; | ||
432 | int call_idx; | ||
433 | int id; | ||
434 | |||
435 | } Timer; | ||
436 | |||
437 | typedef struct _TimerHandler { | ||
438 | Timer **timers; | ||
439 | |||
440 | uint32_t max_capacity; | ||
441 | uint32_t size; | ||
442 | } TimerHandler; | ||
443 | |||
444 | |||
445 | static int timer_alloc (MSISession *session , void (*func)(Timer *), int call_idx, uint32_t timeout) | ||
446 | { | ||
447 | static int timer_id; | ||
448 | TimerHandler *timer_handler = session->timer_handler; | ||
449 | |||
450 | uint32_t i = 0; | ||
451 | |||
452 | for (; i < timer_handler->max_capacity && timer_handler->timers[i]; i ++); | ||
453 | |||
454 | if (i == timer_handler->max_capacity) { | ||
455 | LOGGER_WARNING("Maximum capacity reached!"); | ||
456 | return -1; | ||
457 | } | ||
458 | |||
459 | Timer *timer = timer_handler->timers[i] = calloc(sizeof(Timer), 1); | ||
460 | |||
461 | if (timer == NULL) { | ||
462 | LOGGER_ERROR("Failed to allocate timer!"); | ||
463 | return -1; | ||
464 | } | ||
465 | |||
466 | timer_handler->size ++; | ||
467 | |||
468 | timer->func = func; | ||
469 | timer->session = session; | ||
470 | timer->call_idx = call_idx; | ||
471 | timer->timeout = timeout + current_time_monotonic(); /* In ms */ | ||
472 | ++timer_id; | ||
473 | timer->id = timer_id; | ||
474 | |||
475 | /* reorder */ | ||
476 | if (i) { | ||
477 | int64_t j = i - 1; | ||
478 | |||
479 | for (; j >= 0 && timeout < timer_handler->timers[j]->timeout; j--) { | ||
480 | Timer *tmp = timer_handler->timers[j]; | ||
481 | timer_handler->timers[j] = timer; | ||
482 | timer_handler->timers[j + 1] = tmp; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | LOGGER_DEBUG("Allocated timer index: %ull timeout: %ull, current size: %ull", i, timeout, timer_handler->size); | ||
487 | return timer->id; | ||
488 | } | ||
489 | |||
490 | static int timer_release ( TimerHandler *timers_container, int id) | ||
491 | { | ||
492 | Timer **timed_events = timers_container->timers; | ||
493 | |||
494 | uint32_t i; | ||
495 | int rc = -1; | ||
496 | |||
497 | for (i = 0; i < timers_container->max_capacity; ++i) { | ||
498 | if (timed_events[i] && timed_events[i]->id == id) { | ||
499 | rc = i; | ||
500 | break; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | if (rc == -1) { | ||
505 | LOGGER_WARNING("No event with id: %d", id); | ||
506 | return -1; | ||
507 | } | ||
508 | |||
509 | free(timed_events[rc]); | ||
510 | |||
511 | timed_events[rc] = NULL; | ||
512 | |||
513 | i = rc + 1; | ||
514 | |||
515 | for (; i < timers_container->max_capacity && timed_events[i]; i ++) { | ||
516 | timed_events[i - 1] = timed_events[i]; | ||
517 | timed_events[i] = NULL; | ||
518 | } | ||
519 | |||
520 | timers_container->size--; | ||
521 | |||
522 | LOGGER_DEBUG("Popped id: %d, current size: %ull ", id, timers_container->size); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | /** | ||
527 | * Generate _random_ alphanumerical string. | ||
528 | */ | ||
529 | static void t_randomstr ( uint8_t *str, uint32_t size ) | ||
530 | { | ||
531 | if (str == NULL) { | ||
532 | LOGGER_DEBUG("Empty destination!"); | ||
533 | return; | ||
534 | } | ||
535 | |||
536 | static const uint8_t _bytes[] = | ||
537 | "0123456789" | ||
538 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
539 | "abcdefghijklmnopqrstuvwxyz"; | ||
540 | |||
541 | uint32_t _it = 0; | ||
542 | |||
543 | for ( ; _it < size; _it++ ) { | ||
544 | str[_it] = _bytes[ random_int() % 61 ]; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | /* TODO: it would be nice to actually have some sane error codes */ | ||
549 | typedef enum { | ||
550 | error_none, | ||
551 | error_deadcall, /* has call id but it's from old call */ | ||
552 | error_id_mismatch, /* non-existing call */ | ||
553 | |||
554 | error_no_callid, /* not having call id */ | ||
555 | error_no_call, /* no call in session */ | ||
556 | error_no_crypto_key, /* no crypto key */ | ||
557 | |||
558 | error_busy | ||
559 | |||
560 | } MSICallError; /* Error codes */ | ||
561 | |||
562 | |||
563 | /** | ||
564 | * Stringify error code. | ||
565 | */ | ||
566 | static const uint8_t *stringify_error ( MSICallError error_code ) | ||
567 | { | 318 | { |
568 | static const uint8_t *strings[] = { | 319 | uint8_t parsed [MSI_MAXMSG_SIZE]; |
569 | ( uint8_t *) "", | 320 | uint16_t length = parse_out ( msg, parsed ); |
570 | ( uint8_t *) "Using dead call", | ||
571 | ( uint8_t *) "Call id not set to any call", | ||
572 | ( uint8_t *) "Call id not available", | ||
573 | ( uint8_t *) "No active call in session", | ||
574 | ( uint8_t *) "No Crypto-key set", | ||
575 | ( uint8_t *) "Callee busy" | ||
576 | }; | ||
577 | |||
578 | return strings[error_code]; | ||
579 | } | ||
580 | |||
581 | static int send_message ( MSISession *session, MSICall *call, MSIMessage *msg, uint32_t to ) | ||
582 | { | ||
583 | msi_msg_set_callid ( msg, call->id ); | ||
584 | |||
585 | uint8_t msg_string_final [MSI_MAXMSG_SIZE]; | ||
586 | uint16_t length = parse_send ( msg, msg_string_final ); | ||
587 | 321 | ||
588 | if (!length) { | 322 | if ( !length ) { |
589 | LOGGER_WARNING("Parsing message failed; nothing sent!"); | 323 | LOGGER_WARNING("Parsing message failed; nothing sent!"); |
590 | return -1; | 324 | return -1; |
591 | } | 325 | } |
592 | 326 | ||
593 | if ( m_msi_packet(session->messenger_handle, to, msg_string_final, length) ) { | 327 | if ( m_msi_packet(call->session->messenger_handle, to, parsed, length) ) { |
594 | LOGGER_DEBUG("Sent message"); | 328 | LOGGER_DEBUG("Sent message"); |
595 | return 0; | 329 | return 0; |
596 | } | 330 | } |
@@ -598,157 +332,42 @@ static int send_message ( MSISession *session, MSICall *call, MSIMessage *msg, u | |||
598 | return -1; | 332 | return -1; |
599 | } | 333 | } |
600 | 334 | ||
601 | static int send_reponse ( MSISession *session, MSICall *call, MSIResponse response, uint32_t to ) | 335 | static int send_reponse ( MSICall *call, MSIResponse response, uint32_t to ) |
602 | { | 336 | { |
603 | MSIMessage *msg = msi_new_message ( TypeResponse, response ); | 337 | MSIMessage *msg = msi_new_message ( type_response, response ); |
604 | int ret = send_message ( session, call, msg, to ); | 338 | int ret = send_message ( call, msg, to ); |
605 | free ( msg ); | 339 | free ( msg ); |
606 | return ret; | 340 | return ret; |
607 | } | 341 | } |
608 | 342 | ||
609 | static int send_error ( MSISession *session, MSICall *call, MSICallError errid, uint32_t to ) | 343 | static int send_error ( MSICall *call, MSIReason reason, uint32_t to ) |
610 | { | 344 | { |
611 | if (!call) { | 345 | if (!call) { |
612 | LOGGER_WARNING("Cannot handle error on 'null' call"); | 346 | LOGGER_WARNING("Cannot handle error on 'null' call"); |
613 | return -1; | 347 | return -1; |
614 | } | 348 | } |
615 | 349 | ||
616 | LOGGER_DEBUG("Sending error: %d on call: %s", errid, call->id); | 350 | LOGGER_DEBUG("Sending error: %d on call: %d", reason, call->call_idx); |
617 | 351 | ||
618 | MSIMessage *msg_error = msi_new_message ( TypeResponse, error ); | 352 | MSIMessage *msg_error = msi_new_message ( type_response, resp_error ); |
619 | 353 | ||
620 | msi_msg_set_reason ( msg_error, stringify_error(errid) ); | 354 | if (!msg_error) |
621 | send_message ( session, call, msg_error, to ); | 355 | return -1; |
356 | |||
357 | msg_error->reason.exists = 1; | ||
358 | msg_error->reason.value = reason; | ||
359 | |||
360 | send_message ( call, msg_error, to ); | ||
622 | free ( msg_error ); | 361 | free ( msg_error ); |
623 | 362 | ||
624 | return 0; | 363 | return 0; |
625 | } | 364 | } |
626 | 365 | ||
627 | /** | ||
628 | * Determine 'bigger' call id | ||
629 | */ | ||
630 | static int call_id_bigger( const uint8_t *first, const uint8_t *second) | ||
631 | { | ||
632 | return (memcmp(first, second, sizeof(MSICallIDType)) < 0); | ||
633 | } | ||
634 | |||
635 | |||
636 | /** | ||
637 | * Set/change peer csettings | ||
638 | */ | ||
639 | static int flush_peer_csettings ( MSICall *call, MSIMessage *msg, int peer_id ) | ||
640 | { | ||
641 | if ( msg->csettings.exists ) { | ||
642 | msi_msg_get_csettings(msg, &call->csettings_peer[peer_id]); | ||
643 | |||
644 | LOGGER_DEBUG("Peer: %d \n" | ||
645 | "Type: %u \n" | ||
646 | "Video bitrate: %u \n" | ||
647 | "Video height: %u \n" | ||
648 | "Video width: %u \n" | ||
649 | "Audio bitrate: %u \n" | ||
650 | "Audio framedur: %u \n" | ||
651 | "Audio sample rate: %u \n" | ||
652 | "Audio channels: %u \n", peer_id, | ||
653 | call->csettings_peer[peer_id].call_type, | ||
654 | call->csettings_peer[peer_id].video_bitrate, | ||
655 | call->csettings_peer[peer_id].max_video_height, | ||
656 | call->csettings_peer[peer_id].max_video_width, | ||
657 | call->csettings_peer[peer_id].audio_bitrate, | ||
658 | call->csettings_peer[peer_id].audio_frame_duration, | ||
659 | call->csettings_peer[peer_id].audio_sample_rate, | ||
660 | call->csettings_peer[peer_id].audio_channels ); | ||
661 | |||
662 | return 0; | ||
663 | } | ||
664 | 366 | ||
665 | LOGGER_WARNING("No csettings header!"); | ||
666 | return -1; | ||
667 | } | ||
668 | |||
669 | |||
670 | /** | ||
671 | * Add peer to peer list. | ||
672 | */ | ||
673 | static void add_peer( MSICall *call, int peer_id ) | ||
674 | { | ||
675 | uint32_t *peers = !call->peers ? peers = calloc(sizeof(uint32_t), 1) : | ||
676 | realloc( call->peers, sizeof(uint32_t) * call->peer_count); | ||
677 | |||
678 | if (!peers) { | ||
679 | LOGGER_WARNING("Allocation failed! Program might misbehave!"); | ||
680 | return; | ||
681 | } | ||
682 | |||
683 | call->peer_count ++; | ||
684 | call->peers = peers; | ||
685 | call->peers[call->peer_count - 1] = peer_id; | ||
686 | |||
687 | LOGGER_DEBUG("Added peer: %d", peer_id); | ||
688 | } | ||
689 | |||
690 | |||
691 | static MSICall *find_call ( MSISession *session, uint8_t *call_id ) | ||
692 | { | ||
693 | if ( call_id == NULL ) return NULL; | ||
694 | |||
695 | int32_t i = 0; | ||
696 | |||
697 | for (; i < session->max_calls; i ++ ) | ||
698 | if ( session->calls[i] && memcmp(session->calls[i]->id, call_id, sizeof(session->calls[i]->id)) == 0 ) { | ||
699 | return session->calls[i]; | ||
700 | } | ||
701 | |||
702 | return NULL; | ||
703 | } | ||
704 | 367 | ||
705 | static MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) | 368 | static MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) |
706 | { | 369 | { |
707 | 370 | ||
708 | if (peers == 0) { | ||
709 | LOGGER_ERROR("No peers!"); | ||
710 | return NULL; | ||
711 | } | ||
712 | |||
713 | int32_t call_idx = 0; | ||
714 | |||
715 | for (; call_idx < session->max_calls; call_idx ++) { | ||
716 | if ( !session->calls[call_idx] ) { | ||
717 | |||
718 | if (!(session->calls[call_idx] = calloc ( sizeof ( MSICall ), 1 ))) { | ||
719 | LOGGER_WARNING("Allocation failed! Program might misbehave!"); | ||
720 | return NULL; | ||
721 | } | ||
722 | |||
723 | break; | ||
724 | } | ||
725 | } | ||
726 | |||
727 | if ( call_idx == session->max_calls ) { | ||
728 | LOGGER_WARNING("Reached maximum amount of calls!"); | ||
729 | return NULL; | ||
730 | } | ||
731 | |||
732 | |||
733 | MSICall *call = session->calls[call_idx]; | ||
734 | |||
735 | call->call_idx = call_idx; | ||
736 | |||
737 | if ( !(call->csettings_peer = calloc ( sizeof ( MSICSettings ), peers )) ) { | ||
738 | LOGGER_WARNING("Allocation failed! Program might misbehave!"); | ||
739 | free(call); | ||
740 | return NULL; | ||
741 | } | ||
742 | |||
743 | call->session = session; | ||
744 | |||
745 | call->request_timer_id = 0; | ||
746 | call->ringing_timer_id = 0; | ||
747 | |||
748 | call->ringing_tout_ms = ringing_timeout; | ||
749 | |||
750 | LOGGER_DEBUG("Started new call with index: %u", call_idx); | ||
751 | return call; | ||
752 | } | 371 | } |
753 | 372 | ||
754 | static int terminate_call ( MSISession *session, MSICall *call ) | 373 | static int terminate_call ( MSISession *session, MSICall *call ) |
@@ -758,11 +377,6 @@ static int terminate_call ( MSISession *session, MSICall *call ) | |||
758 | return -1; | 377 | return -1; |
759 | } | 378 | } |
760 | 379 | ||
761 | /* Check event loop and cancel timed events if there are any | ||
762 | */ | ||
763 | timer_release ( session->timer_handler, call->request_timer_id); | ||
764 | timer_release ( session->timer_handler, call->ringing_timer_id); | ||
765 | |||
766 | session->calls[call->call_idx] = NULL; | 380 | session->calls[call->call_idx] = NULL; |
767 | 381 | ||
768 | LOGGER_DEBUG("Terminated call id: %d", call->call_idx); | 382 | LOGGER_DEBUG("Terminated call id: %d", call->call_idx); |
@@ -805,27 +419,6 @@ static void handle_remote_connection_change(Messenger *messenger, int friend_num | |||
805 | } | 419 | } |
806 | } | 420 | } |
807 | 421 | ||
808 | /** | ||
809 | * Function called at request timeout | ||
810 | */ | ||
811 | static void handle_timeout ( Timer *timer ) | ||
812 | { | ||
813 | /* TODO: Cancel might not arrive there; set up | ||
814 | * timers on these cancels and terminate call on | ||
815 | * their timeout | ||
816 | */ | ||
817 | MSICall *call = timer->session->calls[timer->call_idx]; | ||
818 | |||
819 | |||
820 | if (call) { | ||
821 | LOGGER_DEBUG("[Call: %d] Request timed out!", call->call_idx); | ||
822 | |||
823 | invoke_callback(timer->session, timer->call_idx, msi_OnRequestTimeout); | ||
824 | msi_cancel(timer->session, timer->call_idx, call->peers [0], "Request timed out"); | ||
825 | } | ||
826 | } | ||
827 | |||
828 | |||
829 | /********** Request handlers **********/ | 422 | /********** Request handlers **********/ |
830 | static int handle_recv_invite ( MSISession *session, MSICall *call, MSIMessage *msg ) | 423 | static int handle_recv_invite ( MSISession *session, MSICall *call, MSIMessage *msg ) |
831 | { | 424 | { |
@@ -873,7 +466,7 @@ static int handle_recv_invite ( MSISession *session, MSICall *call, MSIMessage * | |||
873 | } | 466 | } |
874 | 467 | ||
875 | LOGGER_DEBUG("Set new call type: %s", call->csettings_peer[0].call_type == msi_TypeAudio ? "audio" : "video"); | 468 | LOGGER_DEBUG("Set new call type: %s", call->csettings_peer[0].call_type == msi_TypeAudio ? "audio" : "video"); |
876 | send_reponse(session, call, starting, msg->friend_id); | 469 | send_reponse(session, call, resp_starting, msg->friend_id); |
877 | invoke_callback(session, call->call_idx, msi_OnPeerCSChange); | 470 | invoke_callback(session, call->call_idx, msi_OnPeerCSChange); |
878 | return 1; | 471 | return 1; |
879 | } | 472 | } |
@@ -902,7 +495,7 @@ static int handle_recv_invite ( MSISession *session, MSICall *call, MSIMessage * | |||
902 | 495 | ||
903 | add_peer( call, msg->friend_id); | 496 | add_peer( call, msg->friend_id); |
904 | flush_peer_csettings ( call, msg, 0 ); | 497 | flush_peer_csettings ( call, msg, 0 ); |
905 | send_reponse(session, call, ringing, msg->friend_id); | 498 | send_reponse(session, call, resp_ringing, msg->friend_id); |
906 | invoke_callback(session, call->call_idx, msi_OnInvite); | 499 | invoke_callback(session, call->call_idx, msi_OnInvite); |
907 | 500 | ||
908 | return 1; | 501 | return 1; |
@@ -935,7 +528,7 @@ static int handle_recv_reject ( MSISession *session, MSICall *call, MSIMessage * | |||
935 | 528 | ||
936 | invoke_callback(session, call->call_idx, msi_OnReject); | 529 | invoke_callback(session, call->call_idx, msi_OnReject); |
937 | 530 | ||
938 | send_reponse(session, call, ending, msg->friend_id); | 531 | send_reponse(session, call, resp_ending, msg->friend_id); |
939 | terminate_call(session, call); | 532 | terminate_call(session, call); |
940 | 533 | ||
941 | return 1; | 534 | return 1; |
@@ -968,7 +561,7 @@ static int handle_recv_end ( MSISession *session, MSICall *call, MSIMessage *msg | |||
968 | LOGGER_DEBUG("Session: %p Handling 'end' on call: %d", session, call->call_idx); | 561 | LOGGER_DEBUG("Session: %p Handling 'end' on call: %d", session, call->call_idx); |
969 | 562 | ||
970 | invoke_callback(session, call->call_idx, msi_OnEnd); | 563 | invoke_callback(session, call->call_idx, msi_OnEnd); |
971 | send_reponse(session, call, ending, msg->friend_id); | 564 | send_reponse(session, call, resp_ending, msg->friend_id); |
972 | terminate_call ( session, call ); | 565 | terminate_call ( session, call ); |
973 | 566 | ||
974 | return 1; | 567 | return 1; |
@@ -1014,7 +607,7 @@ static int handle_recv_starting ( MSISession *session, MSICall *call, MSIMessage | |||
1014 | 607 | ||
1015 | call->state = msi_CallActive; | 608 | call->state = msi_CallActive; |
1016 | 609 | ||
1017 | MSIMessage *msg_start = msi_new_message ( TypeRequest, start ); | 610 | MSIMessage *msg_start = msi_new_message ( type_request, requ_start ); |
1018 | send_message ( session, call, msg_start, msg->friend_id ); | 611 | send_message ( session, call, msg_start, msg->friend_id ); |
1019 | free ( msg_start ); | 612 | free ( msg_start ); |
1020 | 613 | ||
@@ -1115,7 +708,7 @@ static void msi_handle_packet ( Messenger *messenger, int source, const uint8_t | |||
1115 | return; | 708 | return; |
1116 | } | 709 | } |
1117 | 710 | ||
1118 | msg = parse_recv ( data, length ); | 711 | msg = parse_in ( data, length ); |
1119 | 712 | ||
1120 | if ( !msg ) { | 713 | if ( !msg ) { |
1121 | LOGGER_WARNING("Error parsing message"); | 714 | LOGGER_WARNING("Error parsing message"); |
@@ -1124,58 +717,53 @@ static void msi_handle_packet ( Messenger *messenger, int source, const uint8_t | |||
1124 | LOGGER_DEBUG("Successfully parsed message"); | 717 | LOGGER_DEBUG("Successfully parsed message"); |
1125 | } | 718 | } |
1126 | 719 | ||
1127 | msg->friend_id = source; | ||
1128 | |||
1129 | pthread_mutex_lock(session->mutex); | 720 | pthread_mutex_lock(session->mutex); |
1130 | 721 | ||
1131 | /* Find what call */ | 722 | /* Find what call */ |
1132 | MSICall *call = msg->callid.exists ? find_call(session, msg->callid.value ) : NULL; | 723 | MSICall *call = NULL; |
1133 | 724 | ||
1134 | /* Now handle message */ | 725 | /* Now handle message */ |
1135 | 726 | ||
1136 | if ( msg->request.exists ) { /* Handle request */ | 727 | if ( msg->request.exists ) { /* Handle request */ |
1137 | 728 | ||
1138 | switch (msg->request.value) { | 729 | switch (msg->request.value) { |
1139 | case invite: | 730 | case requ_invite: |
1140 | handle_recv_invite ( session, call, msg ); | 731 | handle_recv_invite ( session, call, msg ); |
1141 | break; | 732 | break; |
1142 | 733 | ||
1143 | case start: | 734 | case requ_start: |
1144 | handle_recv_start ( session, call, msg ); | 735 | handle_recv_start ( session, call, msg ); |
1145 | break; | 736 | break; |
1146 | 737 | ||
1147 | case cancel: | 738 | case requ_cancel: |
1148 | handle_recv_cancel ( session, call, msg ); | 739 | handle_recv_cancel ( session, call, msg ); |
1149 | break; | 740 | break; |
1150 | 741 | ||
1151 | case reject: | 742 | case requ_reject: |
1152 | handle_recv_reject ( session, call, msg ); | 743 | handle_recv_reject ( session, call, msg ); |
1153 | break; | 744 | break; |
1154 | 745 | ||
1155 | case end: | 746 | case requ_end: |
1156 | handle_recv_end ( session, call, msg ); | 747 | handle_recv_end ( session, call, msg ); |
1157 | break; | 748 | break; |
1158 | } | 749 | } |
1159 | 750 | ||
1160 | } else if ( msg->response.exists ) { /* Handle response */ | 751 | } else if ( msg->response.exists ) { /* Handle response */ |
1161 | 752 | ||
1162 | /* Got response so cancel timer */ | ||
1163 | if ( call ) timer_release(session->timer_handler, call->request_timer_id); | ||
1164 | |||
1165 | switch (msg->response.value) { | 753 | switch (msg->response.value) { |
1166 | case ringing: | 754 | case resp_ringing: |
1167 | handle_recv_ringing ( session, call, msg ); | 755 | handle_recv_ringing ( session, call, msg ); |
1168 | break; | 756 | break; |
1169 | 757 | ||
1170 | case starting: | 758 | case resp_starting: |
1171 | handle_recv_starting ( session, call, msg ); | 759 | handle_recv_starting ( session, call, msg ); |
1172 | break; | 760 | break; |
1173 | 761 | ||
1174 | case ending: | 762 | case resp_ending: |
1175 | handle_recv_ending ( session, call, msg ); | 763 | handle_recv_ending ( session, call, msg ); |
1176 | break; | 764 | break; |
1177 | 765 | ||
1178 | case error: | 766 | case resp_error: |
1179 | handle_recv_error ( session, call, msg ); | 767 | handle_recv_error ( session, call, msg ); |
1180 | break; | 768 | break; |
1181 | } | 769 | } |
@@ -1192,24 +780,18 @@ static void msi_handle_packet ( Messenger *messenger, int source, const uint8_t | |||
1192 | 780 | ||
1193 | 781 | ||
1194 | /********** User functions **********/ | 782 | /********** User functions **********/ |
1195 | void msi_register_callback ( MSISession *session, MSICallbackType callback, MSICallbackID id, void *userdata ) | 783 | void msi_register_callback ( MSISession *session, MSICallbackType callback, MSICallbackID id) |
1196 | { | 784 | { |
1197 | session->callbacks[id].first = callback; | 785 | session->callbacks[id] = callback; |
1198 | session->callbacks[id].second = userdata; | ||
1199 | } | 786 | } |
1200 | 787 | ||
1201 | 788 | MSISession *msi_new ( Messenger *messenger ) | |
1202 | MSISession *msi_new ( Messenger *messenger, int32_t max_calls ) | ||
1203 | { | 789 | { |
1204 | if (messenger == NULL) { | 790 | if (messenger == NULL) { |
1205 | LOGGER_ERROR("Could not init session on empty messenger!"); | 791 | LOGGER_ERROR("Could not init session on empty messenger!"); |
1206 | return NULL; | 792 | return NULL; |
1207 | } | 793 | } |
1208 | 794 | ||
1209 | if ( !max_calls ) { | ||
1210 | LOGGER_WARNING("Invalid max call treshold!"); | ||
1211 | return NULL; | ||
1212 | } | ||
1213 | 795 | ||
1214 | MSISession *retu = calloc ( sizeof ( MSISession ), 1 ); | 796 | MSISession *retu = calloc ( sizeof ( MSISession ), 1 ); |
1215 | 797 | ||
@@ -1218,43 +800,19 @@ MSISession *msi_new ( Messenger *messenger, int32_t max_calls ) | |||
1218 | return NULL; | 800 | return NULL; |
1219 | } | 801 | } |
1220 | 802 | ||
1221 | if (!(retu->calls = calloc( sizeof (MSICall *), max_calls ))) { | ||
1222 | LOGGER_ERROR("Allocation failed! Program might misbehave!"); | ||
1223 | goto error; | ||
1224 | } | ||
1225 | |||
1226 | retu->timer_handler = calloc(1, sizeof(TimerHandler)); | ||
1227 | |||
1228 | if (retu->timer_handler == NULL) { | ||
1229 | LOGGER_ERROR("Allocation failed! Program might misbehave!"); | ||
1230 | goto error; | ||
1231 | } | ||
1232 | |||
1233 | /* Allocate space for timers */ | ||
1234 | ((TimerHandler *)retu->timer_handler)->max_capacity = max_calls * 10; | ||
1235 | |||
1236 | if (!(((TimerHandler *)retu->timer_handler)->timers = calloc(max_calls * 10, sizeof(Timer *)))) { | ||
1237 | LOGGER_ERROR("Allocation failed! Program might misbehave!"); | ||
1238 | goto error; | ||
1239 | } | ||
1240 | |||
1241 | if (create_recursive_mutex(retu->mutex) != 0) { | 803 | if (create_recursive_mutex(retu->mutex) != 0) { |
1242 | LOGGER_ERROR("Failed to init mutex! Program might misbehave"); | 804 | LOGGER_ERROR("Failed to init mutex! Program might misbehave"); |
1243 | goto error; | 805 | goto error; |
1244 | } | 806 | } |
1245 | 807 | ||
1246 | retu->messenger_handle = messenger; | 808 | retu->messenger_handle = messenger; |
1247 | retu->agent_handler = NULL; | ||
1248 | retu->max_calls = max_calls; | ||
1249 | retu->frequ = 10000; /* default value? */ | ||
1250 | retu->call_timeout = 30000; /* default value? */ | ||
1251 | 809 | ||
1252 | m_callback_msi_packet(messenger, msi_handle_packet, retu ); | 810 | m_callback_msi_packet(messenger, msi_handle_packet, retu ); |
1253 | 811 | ||
1254 | /* This is called when remote terminates session */ | 812 | /* This is called when remote terminates session */ |
1255 | m_callback_connectionstatus_internal_av(messenger, handle_remote_connection_change, retu); | 813 | m_callback_connectionstatus_internal_av(messenger, handle_remote_connection_change, retu); |
1256 | 814 | ||
1257 | LOGGER_DEBUG("New msi session: %p max calls: %u", retu, max_calls); | 815 | LOGGER_DEBUG("New msi session: %p ", retu); |
1258 | return retu; | 816 | return retu; |
1259 | 817 | ||
1260 | error: | 818 | error: |
@@ -1269,7 +827,6 @@ error: | |||
1269 | return NULL; | 827 | return NULL; |
1270 | } | 828 | } |
1271 | 829 | ||
1272 | |||
1273 | int msi_kill ( MSISession *session ) | 830 | int msi_kill ( MSISession *session ) |
1274 | { | 831 | { |
1275 | if (session == NULL) { | 832 | if (session == NULL) { |
@@ -1338,7 +895,7 @@ int msi_invite ( MSISession *session, | |||
1338 | 895 | ||
1339 | call->csettings_local = *csettings; | 896 | call->csettings_local = *csettings; |
1340 | 897 | ||
1341 | MSIMessage *msg_invite = msi_new_message ( TypeRequest, invite ); | 898 | MSIMessage *msg_invite = msi_new_message ( type_request, requ_invite ); |
1342 | 899 | ||
1343 | msi_msg_set_csettings(msg_invite, csettings); | 900 | msi_msg_set_csettings(msg_invite, csettings); |
1344 | send_message ( session, call, msg_invite, friend_id ); | 901 | send_message ( session, call, msg_invite, friend_id ); |
@@ -1372,7 +929,7 @@ int msi_hangup ( MSISession *session, int32_t call_index ) | |||
1372 | return msi_ErrorInvalidState; | 929 | return msi_ErrorInvalidState; |
1373 | } | 930 | } |
1374 | 931 | ||
1375 | MSIMessage *msg_end = msi_new_message ( TypeRequest, end ); | 932 | MSIMessage *msg_end = msi_new_message ( type_request, requ_end ); |
1376 | 933 | ||
1377 | /* hangup for each peer */ | 934 | /* hangup for each peer */ |
1378 | int it = 0; | 935 | int it = 0; |
@@ -1408,7 +965,7 @@ int msi_answer ( MSISession *session, int32_t call_index, const MSICSettings *cs | |||
1408 | return msi_ErrorInvalidState; | 965 | return msi_ErrorInvalidState; |
1409 | } | 966 | } |
1410 | 967 | ||
1411 | MSIMessage *msg_starting = msi_new_message ( TypeResponse, starting ); | 968 | MSIMessage *msg_starting = msi_new_message ( type_response, resp_starting ); |
1412 | 969 | ||
1413 | session->calls[call_index]->csettings_local = *csettings; | 970 | session->calls[call_index]->csettings_local = *csettings; |
1414 | 971 | ||
@@ -1440,7 +997,7 @@ int msi_cancel ( MSISession *session, int32_t call_index, uint32_t peer, const c | |||
1440 | return msi_ErrorInvalidState; | 997 | return msi_ErrorInvalidState; |
1441 | } | 998 | } |
1442 | 999 | ||
1443 | MSIMessage *msg_cancel = msi_new_message ( TypeRequest, cancel ); | 1000 | MSIMessage *msg_cancel = msi_new_message ( type_request, requ_cancel ); |
1444 | 1001 | ||
1445 | /* FIXME */ | 1002 | /* FIXME */ |
1446 | #if 0 | 1003 | #if 0 |
@@ -1483,7 +1040,7 @@ int msi_reject ( MSISession *session, int32_t call_index, const char *reason ) | |||
1483 | return msi_ErrorInvalidState; | 1040 | return msi_ErrorInvalidState; |
1484 | } | 1041 | } |
1485 | 1042 | ||
1486 | MSIMessage *msg_reject = msi_new_message ( TypeRequest, reject ); | 1043 | MSIMessage *msg_reject = msi_new_message ( type_request, requ_reject ); |
1487 | 1044 | ||
1488 | /* FIXME */ | 1045 | /* FIXME */ |
1489 | #if 0 | 1046 | #if 0 |
@@ -1568,7 +1125,7 @@ int msi_change_csettings(MSISession *session, int32_t call_index, const MSICSett | |||
1568 | 1125 | ||
1569 | *local = *csettings; | 1126 | *local = *csettings; |
1570 | 1127 | ||
1571 | MSIMessage *msg_invite = msi_new_message ( TypeRequest, invite ); | 1128 | MSIMessage *msg_invite = msi_new_message ( type_request, requ_invite ); |
1572 | 1129 | ||
1573 | msi_msg_set_csettings ( msg_invite, local ); | 1130 | msi_msg_set_csettings ( msg_invite, local ); |
1574 | send_message ( session, call, msg_invite, call->peers[0] ); | 1131 | send_message ( session, call, msg_invite, call->peers[0] ); |
diff --git a/toxav/msi.h b/toxav/msi.h index bdd72e49..c71c69dd 100644 --- a/toxav/msi.h +++ b/toxav/msi.h | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | typedef uint8_t MSICallIDType[12]; | 31 | typedef uint8_t MSICallIDType[12]; |
32 | typedef uint8_t MSIReasonStrType[255]; | 32 | typedef uint8_t MSIReasonStrType[255]; |
33 | typedef void ( *MSICallbackType ) ( void *agent, int32_t call_idx, void *arg ); | 33 | typedef void ( *MSICallbackType ) ( void *agent, int32_t call_idx); |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * Call type identifier. Also used as rtp callback prefix. | 36 | * Call type identifier. Also used as rtp callback prefix. |
@@ -70,6 +70,15 @@ typedef struct { | |||
70 | uint32_t audio_channels; | 70 | uint32_t audio_channels; |
71 | } MSICSettings; | 71 | } MSICSettings; |
72 | 72 | ||
73 | /** | ||
74 | * Active capabilities masks | ||
75 | */ | ||
76 | typedef enum { | ||
77 | msi_SendingAudio = 1, | ||
78 | msi_SendingVideo = 2, | ||
79 | msi_RecvingAudio = 4, | ||
80 | msi_RecvingVideo = 8, | ||
81 | } MSICapMask; | ||
73 | 82 | ||
74 | /** | 83 | /** |
75 | * Callbacks ids that handle the states | 84 | * Callbacks ids that handle the states |
@@ -100,25 +109,13 @@ typedef enum { | |||
100 | /** | 109 | /** |
101 | * The call struct. | 110 | * The call struct. |
102 | */ | 111 | */ |
103 | typedef struct { /* Call info structure */ | 112 | typedef struct { |
104 | struct MSISession_s *session; /* Session pointer */ | 113 | struct MSISession_s *session; /* Session pointer */ |
105 | 114 | ||
106 | MSICallState state; | 115 | MSICallState state; |
107 | 116 | uint8_t caps; /* Active capabilities */ | |
108 | MSICSettings csettings_local; /* Local call settings */ | 117 | |
109 | MSICSettings *csettings_peer; /* Peers call settings */ | 118 | uint32_t friend_id; /* Index of this call in MSISession */ |
110 | |||
111 | MSICallIDType id; /* Random value identifying the call */ | ||
112 | |||
113 | int ringing_tout_ms; /* Ringing timeout in ms */ | ||
114 | |||
115 | int request_timer_id; /* Timer id for outgoing request/action */ | ||
116 | int ringing_timer_id; /* Timer id for ringing timeout */ | ||
117 | |||
118 | uint32_t *peers; | ||
119 | uint16_t peer_count; | ||
120 | |||
121 | int32_t call_idx; /* Index of this call in MSISession */ | ||
122 | } MSICall; | 119 | } MSICall; |
123 | 120 | ||
124 | 121 | ||
@@ -126,21 +123,14 @@ typedef struct { /* Call info structure */ | |||
126 | * Control session struct | 123 | * Control session struct |
127 | */ | 124 | */ |
128 | typedef struct MSISession_s { | 125 | typedef struct MSISession_s { |
129 | |||
130 | /* Call handlers */ | 126 | /* Call handlers */ |
131 | MSICall **calls; | 127 | MSICall **calls; |
132 | int32_t max_calls; | ||
133 | 128 | ||
134 | void *agent_handler; | 129 | void *agent_handler; |
135 | Messenger *messenger_handle; | 130 | Messenger *messenger_handle; |
136 | 131 | ||
137 | uint32_t frequ; | ||
138 | uint32_t call_timeout; /* Time of the timeout for some action to end; 0 if infinite */ | ||
139 | |||
140 | pthread_mutex_t mutex[1]; | 132 | pthread_mutex_t mutex[1]; |
141 | 133 | MSICallbackType callbacks[10]; | |
142 | void *timer_handler; | ||
143 | PAIR(MSICallbackType, void *) callbacks[10]; | ||
144 | } MSISession; | 134 | } MSISession; |
145 | 135 | ||
146 | /** | 136 | /** |
@@ -156,7 +146,7 @@ int msi_kill ( MSISession *session ); | |||
156 | /** | 146 | /** |
157 | * Callback setter. | 147 | * Callback setter. |
158 | */ | 148 | */ |
159 | void msi_register_callback(MSISession *session, MSICallbackType callback, MSICallbackID id, void *userdata); | 149 | void msi_register_callback(MSISession *session, MSICallbackType callback, MSICallbackID id); |
160 | 150 | ||
161 | /** | 151 | /** |
162 | * Send invite request to friend_id. | 152 | * Send invite request to friend_id. |
diff --git a/toxav/toxav.c b/toxav/toxav.c index d71bbd6d..b594cc29 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -322,6 +322,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
322 | } else if (av->msi->calls[call->call_idx]->state == msi_CallRequesting) { | 322 | } else if (av->msi->calls[call->call_idx]->state == msi_CallRequesting) { |
323 | /* Cancel the call */ | 323 | /* Cancel the call */ |
324 | msi_cancel(av->msi, call->call_idx, 0, NULL); | 324 | msi_cancel(av->msi, call->call_idx, 0, NULL); |
325 | i_toxav_remove_call(av, friend_number); | ||
325 | } | 326 | } |
326 | } break; | 327 | } break; |
327 | 328 | ||