1 /*
2 * Copyright 2008-2014 Arsen Chaloyan
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * $Id: mrcp_server_session.c 2237 2014-11-12 01:48:46Z achaloyan@gmail.com $
17 */
18
19 #include "mrcp_server.h"
20 #include "mrcp_server_session.h"
21 #include "mrcp_resource.h"
22 #include "mrcp_resource_factory.h"
23 #include "mrcp_engine_iface.h"
24 #include "mrcp_sig_agent.h"
25 #include "mrcp_server_connection.h"
26 #include "mrcp_session_descriptor.h"
27 #include "mrcp_control_descriptor.h"
28 #include "mrcp_state_machine.h"
29 #include "mrcp_message.h"
30 #include "mpf_termination_factory.h"
31 #include "mpf_stream.h"
32 #include "apt_consumer_task.h"
33 #include "apt_log.h"
34
35 /** Macro to log session name and identifier */
36 #define MRCP_SESSION_NAMESID(session) \
37 session->base.name, MRCP_SESSION_SID(&session->base)
38
39 #define MRCP_SESSION_ID_HEX_STRING_LENGTH 16
40
41 struct mrcp_channel_t {
42 /** Memory pool */
43 apr_pool_t *pool;
44 /** MRCP resource */
45 mrcp_resource_t *resource;
46 /** MRCP session entire channel belongs to */
47 mrcp_session_t *session;
48 /** MRCP control channel */
49 mrcp_control_channel_t *control_channel;
50 /** MRCP engine channel */
51 mrcp_engine_channel_t *engine_channel;
52 /** MRCP resource state machine */
53 mrcp_state_machine_t *state_machine;
54 /** media descriptor id (position in session descriptor) */
55 apr_size_t id;
56 /** array of cmid attributes (used for resource grouping) */
57 apr_array_header_t *cmid_arr;
58 /** waiting state of control media */
59 apt_bool_t waiting_for_channel;
60 /** waiting state of media termination */
61 apt_bool_t waiting_for_termination;
62 };
63
64 typedef struct mrcp_termination_slot_t mrcp_termination_slot_t;
65
66 struct mrcp_termination_slot_t {
67 /** RTP termination */
68 mpf_termination_t *termination;
69 /** media descriptor id (position in SDP message) */
70 apr_size_t id;
71 /** media id (used for resource grouping) */
72 apr_size_t mid;
73 /** Array of associated MRCP channels (mrcp_channel_t*) */
74 apr_array_header_t *channels;
75
76 /** waiting state */
77 apt_bool_t waiting;
78 };
79
80 extern const mrcp_engine_channel_event_vtable_t engine_channel_vtable;
81
82 void mrcp_server_session_add(mrcp_server_session_t *session);
83 void mrcp_server_session_remove(mrcp_server_session_t *session);
84
85 static apt_bool_t mrcp_server_signaling_message_dispatch(mrcp_server_session_t *session, mrcp_signaling_message_t *signaling_message);
86
87 static apt_bool_t mrcp_server_resource_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor);
88 static apt_bool_t mrcp_server_control_media_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor);
89 static apt_bool_t mrcp_server_av_media_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor);
90
91 static apt_bool_t mrcp_server_engine_channels_update(mrcp_server_session_t *session);
92 static apt_bool_t mrcp_server_session_answer_send(mrcp_server_session_t *session);
93 static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *session);
94 static apt_bool_t mrcp_server_session_terminate_send(mrcp_server_session_t *session);
95
96 static mrcp_channel_t* mrcp_server_channel_find(mrcp_server_session_t *session, const apt_str_t *resource_name);
97
98 static apt_bool_t state_machine_on_message_dispatch(mrcp_state_machine_t *state_machine, mrcp_message_t *message);
99 static apt_bool_t state_machine_on_deactivate(mrcp_state_machine_t *state_machine);
100
101
mrcp_server_session_create()102 mrcp_server_session_t* mrcp_server_session_create()
103 {
104 mrcp_server_session_t *session = (mrcp_server_session_t*) mrcp_session_create(sizeof(mrcp_server_session_t)-sizeof(mrcp_session_t));
105 session->context = NULL;
106 session->terminations = apr_array_make(session->base.pool,2,sizeof(mrcp_termination_slot_t));
107 session->channels = apr_array_make(session->base.pool,2,sizeof(mrcp_channel_t*));
108 session->active_request = NULL;
109 session->request_queue = apt_list_create(session->base.pool);
110 session->offer = NULL;
111 session->answer = NULL;
112 session->mpf_task_msg = NULL;
113 session->subrequest_count = 0;
114 session->state = SESSION_STATE_NONE;
115 session->base.name = apr_psprintf(session->base.pool,"0x%pp",session);
116 return session;
117 }
118
mrcp_session_version_get(mrcp_server_session_t * session)119 static APR_INLINE mrcp_version_e mrcp_session_version_get(mrcp_server_session_t *session)
120 {
121 return session->profile->mrcp_version;
122 }
123
mrcp_server_engine_channel_create(mrcp_server_session_t * session,mrcp_channel_t * channel,const apt_str_t * resource_name)124 static mrcp_engine_channel_t* mrcp_server_engine_channel_create(
125 mrcp_server_session_t *session,
126 mrcp_channel_t *channel,
127 const apt_str_t *resource_name)
128 {
129 mrcp_engine_t *engine = apr_hash_get(
130 session->profile->engine_table,
131 resource_name->buf,
132 resource_name->length);
133 if(!engine) {
134 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find MRCP Engine "APT_NAMESID_FMT" [%s]",
135 MRCP_SESSION_NAMESID(session),
136 resource_name->buf);
137 return NULL;
138 }
139
140 channel->state_machine = engine->create_state_machine(
141 channel,
142 mrcp_session_version_get(session),
143 channel->pool);
144 if(channel->state_machine) {
145 channel->state_machine->on_dispatch = state_machine_on_message_dispatch;
146 channel->state_machine->on_deactivate = state_machine_on_deactivate;
147 }
148
149 return mrcp_engine_channel_virtual_create(engine,mrcp_session_version_get(session),session->base.pool);
150 }
151
mrcp_server_channel_create(mrcp_server_session_t * session,const apt_str_t * resource_name,apr_size_t id,apr_array_header_t * cmid_arr)152 static mrcp_channel_t* mrcp_server_channel_create(mrcp_server_session_t *session, const apt_str_t *resource_name, apr_size_t id, apr_array_header_t *cmid_arr)
153 {
154 mrcp_channel_t *channel;
155 apr_pool_t *pool = session->base.pool;
156
157 channel = apr_palloc(pool,sizeof(mrcp_channel_t));
158 channel->pool = pool;
159 channel->session = &session->base;
160 channel->resource = NULL;
161 channel->control_channel = NULL;
162 channel->state_machine = NULL;
163 channel->engine_channel = NULL;
164 channel->id = id;
165 channel->cmid_arr = cmid_arr;
166 channel->waiting_for_channel = FALSE;
167 channel->waiting_for_termination = FALSE;
168
169 if(resource_name && resource_name->buf) {
170 mrcp_resource_t *resource;
171 mrcp_engine_channel_t *engine_channel;
172 resource = mrcp_resource_find(session->profile->resource_factory,resource_name);
173 if(resource) {
174 channel->resource = resource;
175 if(mrcp_session_version_get(session) == MRCP_VERSION_2) {
176 channel->control_channel = mrcp_server_control_channel_create(
177 session->profile->connection_agent,
178 channel,
179 pool);
180 }
181 engine_channel = mrcp_server_engine_channel_create(session,channel,resource_name);
182 if(engine_channel) {
183 engine_channel->id = session->base.id;
184 engine_channel->event_obj = channel;
185 engine_channel->event_vtable = &engine_channel_vtable;
186 channel->engine_channel = engine_channel;
187 }
188 else {
189 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Engine Channel "APT_NAMESID_FMT" [%s]",
190 MRCP_SESSION_NAMESID(session),
191 resource_name->buf);
192 session->answer->status = MRCP_SESSION_STATUS_UNACCEPTABLE_RESOURCE;
193 }
194 }
195 else {
196 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Resource "APT_NAMESID_FMT" [%s]",
197 MRCP_SESSION_NAMESID(session),
198 resource_name->buf);
199 session->answer->status = MRCP_SESSION_STATUS_NO_SUCH_RESOURCE;
200 }
201 }
202 else {
203 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid Resource Identifier "APT_NAMESID_FMT,
204 MRCP_SESSION_NAMESID(session));
205 session->answer->status = MRCP_SESSION_STATUS_NO_SUCH_RESOURCE;
206 }
207
208 return channel;
209 }
210
mrcp_server_session_state_set(mrcp_server_session_t * session,mrcp_server_session_state_e state)211 static APR_INLINE void mrcp_server_session_state_set(mrcp_server_session_t *session, mrcp_server_session_state_e state)
212 {
213 if(session->subrequest_count != 0) {
214 /* error case */
215 session->subrequest_count = 0;
216 }
217 session->state = state;
218 }
219
mrcp_server_session_subrequest_add(mrcp_server_session_t * session)220 static APR_INLINE void mrcp_server_session_subrequest_add(mrcp_server_session_t *session)
221 {
222 session->subrequest_count++;
223 }
224
mrcp_server_session_subrequest_remove(mrcp_server_session_t * session)225 static void mrcp_server_session_subrequest_remove(mrcp_server_session_t *session)
226 {
227 if(!session->subrequest_count) {
228 /* error case */
229 return;
230 }
231 session->subrequest_count--;
232 if(!session->subrequest_count) {
233 switch(session->state) {
234 case SESSION_STATE_GENERATING_ANSWER:
235 mrcp_server_engine_channels_update(session);
236 break;
237 case SESSION_STATE_INITIALIZING:
238 /* send answer to client */
239 mrcp_server_session_answer_send(session);
240 break;
241 case SESSION_STATE_DEACTIVATING:
242 mrcp_server_session_terminate_process(session);
243 break;
244 case SESSION_STATE_TERMINATING:
245 mrcp_server_session_terminate_send(session);
246 break;
247 default:
248 break;
249 }
250 }
251 }
252
mrcp_server_channel_session_get(mrcp_channel_t * channel)253 mrcp_session_t* mrcp_server_channel_session_get(mrcp_channel_t *channel)
254 {
255 return channel->session;
256 }
257
mrcp_server_signaling_message_process(mrcp_signaling_message_t * signaling_message)258 apt_bool_t mrcp_server_signaling_message_process(mrcp_signaling_message_t *signaling_message)
259 {
260 mrcp_server_session_t *session = signaling_message->session;
261 if(session->active_request) {
262 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Push Request to Queue "APT_NAMESID_FMT,
263 MRCP_SESSION_NAMESID(session));
264 apt_list_push_back(session->request_queue,signaling_message,session->base.pool);
265 }
266 else {
267 session->active_request = signaling_message;
268 mrcp_server_signaling_message_dispatch(session,signaling_message);
269 }
270 return TRUE;
271 }
272
mrcp_server_on_channel_modify(mrcp_channel_t * channel,mrcp_control_descriptor_t * answer,apt_bool_t status)273 apt_bool_t mrcp_server_on_channel_modify(mrcp_channel_t *channel, mrcp_control_descriptor_t *answer, apt_bool_t status)
274 {
275 mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
276 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Control Channel Modified "APT_NAMESIDRES_FMT,
277 MRCP_SESSION_NAMESID(session),
278 channel->resource->name.buf);
279 if(!answer) {
280 return FALSE;
281 }
282 if(!channel->waiting_for_channel) {
283 return FALSE;
284 }
285 channel->waiting_for_channel = FALSE;
286 answer->session_id = session->base.id;
287 mrcp_session_control_media_set(session->answer,channel->id,answer);
288 mrcp_server_session_subrequest_remove(session);
289 return TRUE;
290 }
291
mrcp_server_on_channel_remove(mrcp_channel_t * channel,apt_bool_t status)292 apt_bool_t mrcp_server_on_channel_remove(mrcp_channel_t *channel, apt_bool_t status)
293 {
294 mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
295 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Control Channel Removed "APT_NAMESIDRES_FMT,
296 MRCP_SESSION_NAMESID(session),
297 channel->resource->name.buf);
298 if(!channel->waiting_for_channel) {
299 return FALSE;
300 }
301 channel->waiting_for_channel = FALSE;
302 mrcp_server_session_subrequest_remove(session);
303 return TRUE;
304 }
305
mrcp_server_on_channel_message(mrcp_channel_t * channel,mrcp_message_t * message)306 apt_bool_t mrcp_server_on_channel_message(mrcp_channel_t *channel, mrcp_message_t *message)
307 {
308 mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
309 mrcp_signaling_message_t *signaling_message;
310 signaling_message = apr_palloc(session->base.pool,sizeof(mrcp_signaling_message_t));
311 signaling_message->type = SIGNALING_MESSAGE_CONTROL;
312 signaling_message->session = session;
313 signaling_message->descriptor = NULL;
314 signaling_message->channel = channel;
315 signaling_message->message = message;
316 return mrcp_server_signaling_message_process(signaling_message);
317 }
318
mrcp_server_on_disconnect(mrcp_channel_t * channel)319 apt_bool_t mrcp_server_on_disconnect(mrcp_channel_t *channel)
320 {
321 /* to be processed */
322 return TRUE;
323 }
324
mrcp_server_on_engine_channel_open(mrcp_channel_t * channel,apt_bool_t status)325 apt_bool_t mrcp_server_on_engine_channel_open(mrcp_channel_t *channel, apt_bool_t status)
326 {
327 mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
328 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Engine Channel Opened "APT_NAMESIDRES_FMT" [%s]",
329 MRCP_SESSION_NAMESID(session),
330 channel->resource->name.buf,
331 status == TRUE ? "OK" : "Failed");
332 if(status == FALSE) {
333 session->answer->status = MRCP_SESSION_STATUS_UNAVAILABLE_RESOURCE;
334 }
335 mrcp_server_session_subrequest_remove(session);
336 return TRUE;
337 }
338
mrcp_server_on_engine_channel_close(mrcp_channel_t * channel)339 apt_bool_t mrcp_server_on_engine_channel_close(mrcp_channel_t *channel)
340 {
341 mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
342 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Engine Channel Closed "APT_NAMESIDRES_FMT,
343 MRCP_SESSION_NAMESID(session),
344 channel->resource->name.buf);
345 mrcp_server_session_subrequest_remove(session);
346 return TRUE;
347 }
348
mrcp_server_on_engine_channel_message(mrcp_channel_t * channel,mrcp_message_t * message)349 apt_bool_t mrcp_server_on_engine_channel_message(mrcp_channel_t *channel, mrcp_message_t *message)
350 {
351 if(!channel->state_machine) {
352 return FALSE;
353 }
354 /* update state machine */
355 return mrcp_state_machine_update(channel->state_machine,message);
356 }
357
358
mrcp_session_answer_create(mrcp_session_descriptor_t * offer,apr_pool_t * pool)359 static mrcp_session_descriptor_t* mrcp_session_answer_create(mrcp_session_descriptor_t *offer, apr_pool_t *pool)
360 {
361 int i;
362 mrcp_session_descriptor_t *answer = apr_palloc(pool,sizeof(mrcp_session_descriptor_t));
363 apt_string_reset(&answer->origin);
364 apt_string_reset(&answer->ip);
365 apt_string_reset(&answer->ext_ip);
366 answer->resource_name = offer->resource_name;
367 answer->resource_state = offer->resource_state;
368 answer->status = offer->status;
369 answer->control_media_arr = apr_array_make(pool,offer->control_media_arr->nelts,sizeof(void*));
370 for(i=0; i<offer->control_media_arr->nelts; i++) {
371 APR_ARRAY_PUSH(answer->control_media_arr,void*) = NULL;
372 }
373 answer->audio_media_arr = apr_array_make(pool,offer->audio_media_arr->nelts,sizeof(mpf_rtp_media_descriptor_t*));
374 for(i=0; i<offer->audio_media_arr->nelts; i++) {
375 APR_ARRAY_PUSH(answer->audio_media_arr,mpf_rtp_media_descriptor_t*) = NULL;
376 }
377 answer->video_media_arr = apr_array_make(pool,offer->video_media_arr->nelts,sizeof(mpf_rtp_media_descriptor_t*));
378 for(i=0; i<offer->video_media_arr->nelts; i++) {
379 APR_ARRAY_PUSH(answer->video_media_arr,mpf_rtp_media_descriptor_t*) = NULL;
380 }
381 return answer;
382 }
383
mrcp_server_session_offer_process(mrcp_server_session_t * session,mrcp_session_descriptor_t * descriptor)384 static apt_bool_t mrcp_server_session_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor)
385 {
386 if(!session->context) {
387 /* initial offer received, generate session id and add to session's table */
388 if(!session->base.id.length) {
389 apt_unique_id_generate(&session->base.id,MRCP_SESSION_ID_HEX_STRING_LENGTH,session->base.pool);
390 }
391 mrcp_server_session_add(session);
392
393 session->context = mpf_engine_context_create(
394 session->profile->media_engine,
395 session->base.name,
396 session,5,session->base.pool);
397 }
398 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Offer "APT_NAMESID_FMT" [c:%d a:%d v:%d]",
399 MRCP_SESSION_NAMESID(session),
400 descriptor->control_media_arr->nelts,
401 descriptor->audio_media_arr->nelts,
402 descriptor->video_media_arr->nelts);
403
404 /* store received offer */
405 session->offer = descriptor;
406 session->answer = mrcp_session_answer_create(descriptor,session->base.pool);
407
408 mrcp_server_session_state_set(session,SESSION_STATE_GENERATING_ANSWER);
409
410 /* first, reset/destroy existing associations and topology */
411 if(mpf_engine_topology_message_add(
412 session->profile->media_engine,
413 MPF_RESET_ASSOCIATIONS,session->context,
414 &session->mpf_task_msg) == TRUE){
415 mrcp_server_session_subrequest_add(session);
416 }
417
418 if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
419 if(mrcp_server_resource_offer_process(session,descriptor) == TRUE) {
420 mrcp_server_av_media_offer_process(session,descriptor);
421 }
422 else {
423 session->answer->resource_state = FALSE;
424 }
425 }
426 else {
427 mrcp_server_control_media_offer_process(session,descriptor);
428 mrcp_server_av_media_offer_process(session,descriptor);
429 }
430
431 /* apply topology based on assigned associations */
432 if(mpf_engine_topology_message_add(
433 session->profile->media_engine,
434 MPF_APPLY_TOPOLOGY,session->context,
435 &session->mpf_task_msg) == TRUE) {
436 mrcp_server_session_subrequest_add(session);
437 }
438 mpf_engine_message_send(session->profile->media_engine,&session->mpf_task_msg);
439
440 if(!session->subrequest_count) {
441 /* send answer to client */
442 mrcp_server_session_answer_send(session);
443 }
444 return TRUE;
445 }
446
mrcp_server_session_terminate_process(mrcp_server_session_t * session)447 static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *session)
448 {
449 mrcp_channel_t *channel;
450 mrcp_termination_slot_t *slot;
451 int i;
452 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Terminate Session "APT_NAMESID_FMT,MRCP_SESSION_NAMESID(session));
453
454 mrcp_server_session_state_set(session,SESSION_STATE_TERMINATING);
455
456 if(session->context) {
457 /* first, destroy existing topology */
458 if(mpf_engine_topology_message_add(
459 session->profile->media_engine,
460 MPF_RESET_ASSOCIATIONS,session->context,
461 &session->mpf_task_msg) == TRUE){
462 mrcp_server_session_subrequest_add(session);
463 }
464 }
465
466 for(i=0; i<session->channels->nelts; i++) {
467 channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
468 if(!channel) continue;
469
470 /* send remove channel request */
471 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Remove Control Channel "APT_NAMESIDRES_FMT" [%d]",
472 MRCP_SESSION_NAMESID(session),
473 channel->resource->name.buf,
474 i);
475 if(channel->control_channel) {
476 if(mrcp_server_control_channel_remove(channel->control_channel) == TRUE) {
477 channel->waiting_for_channel = TRUE;
478 mrcp_server_session_subrequest_add(session);
479 }
480 }
481
482 if(channel->engine_channel) {
483 mpf_termination_t *termination = channel->engine_channel->termination;
484 /* send subtract termination request */
485 if(termination) {
486 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract Media Termination "APT_NAMESIDRES_FMT,
487 MRCP_SESSION_NAMESID(session),
488 mpf_termination_name_get(termination));
489 if(mpf_engine_termination_message_add(
490 session->profile->media_engine,
491 MPF_SUBTRACT_TERMINATION,session->context,termination,NULL,
492 &session->mpf_task_msg) == TRUE) {
493 channel->waiting_for_termination = TRUE;
494 mrcp_server_session_subrequest_add(session);
495 }
496 }
497
498 /* close engine channel */
499 if(mrcp_engine_channel_virtual_close(channel->engine_channel) == TRUE) {
500 mrcp_server_session_subrequest_add(session);
501 }
502 }
503 }
504 for(i=0; i<session->terminations->nelts; i++) {
505 /* get existing termination */
506 slot = &APR_ARRAY_IDX(session->terminations,i,mrcp_termination_slot_t);
507 if(!slot->termination) continue;
508
509 /* send subtract termination request */
510 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract Media Termination "APT_NAMESIDRES_FMT,
511 MRCP_SESSION_NAMESID(session),
512 mpf_termination_name_get(slot->termination));
513 if(mpf_engine_termination_message_add(
514 session->profile->media_engine,
515 MPF_SUBTRACT_TERMINATION,session->context,slot->termination,NULL,
516 &session->mpf_task_msg) == TRUE) {
517 slot->waiting = TRUE;
518 mrcp_server_session_subrequest_add(session);
519 }
520 }
521
522 if(session->context) {
523 mpf_engine_message_send(session->profile->media_engine,&session->mpf_task_msg);
524 }
525
526 mrcp_server_session_remove(session);
527
528 if(!session->subrequest_count) {
529 mrcp_server_session_terminate_send(session);
530 }
531
532 return TRUE;
533 }
534
mrcp_server_session_deactivate(mrcp_server_session_t * session)535 static apt_bool_t mrcp_server_session_deactivate(mrcp_server_session_t *session)
536 {
537 mrcp_channel_t *channel;
538 int i;
539 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Deactivate Session "APT_NAMESID_FMT,MRCP_SESSION_NAMESID(session));
540 mrcp_server_session_state_set(session,SESSION_STATE_DEACTIVATING);
541 for(i=0; i<session->channels->nelts; i++) {
542 channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
543 if(!channel || !channel->state_machine) continue;
544
545 if(mrcp_state_machine_deactivate(channel->state_machine) == TRUE) {
546 mrcp_server_session_subrequest_add(session);
547 }
548 }
549
550 if(!session->subrequest_count) {
551 mrcp_server_session_terminate_process(session);
552 }
553
554 return TRUE;
555 }
556
mrcp_server_on_message_receive(mrcp_server_session_t * session,mrcp_channel_t * channel,mrcp_message_t * message)557 static apt_bool_t mrcp_server_on_message_receive(mrcp_server_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
558 {
559 if(!channel) {
560 channel = mrcp_server_channel_find(session,&message->channel_id.resource_name);
561 if(!channel) {
562 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Channel "APT_NAMESIDRES_FMT,
563 MRCP_SESSION_NAMESID(session),
564 message->channel_id.resource_name.buf);
565 return FALSE;
566 }
567 }
568 if(!channel->resource || !channel->state_machine) {
569 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Missing Resource "APT_NAMESIDRES_FMT,
570 MRCP_SESSION_NAMESID(session),
571 message->channel_id.resource_name.buf);
572 return FALSE;
573 }
574
575 /* update state machine */
576 return mrcp_state_machine_update(channel->state_machine,message);
577 }
578
mrcp_server_signaling_message_dispatch(mrcp_server_session_t * session,mrcp_signaling_message_t * signaling_message)579 static apt_bool_t mrcp_server_signaling_message_dispatch(mrcp_server_session_t *session, mrcp_signaling_message_t *signaling_message)
580 {
581 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Dispatch Signaling Message [%d]",signaling_message->type);
582 switch(signaling_message->type) {
583 case SIGNALING_MESSAGE_OFFER:
584 mrcp_server_session_offer_process(signaling_message->session,signaling_message->descriptor);
585 break;
586 case SIGNALING_MESSAGE_CONTROL:
587 mrcp_server_on_message_receive(signaling_message->session,signaling_message->channel,signaling_message->message);
588 break;
589 case SIGNALING_MESSAGE_TERMINATE:
590 mrcp_server_session_deactivate(signaling_message->session);
591 break;
592 default:
593 break;
594 }
595 return TRUE;
596 }
597
mrcp_server_engine_channels_update(mrcp_server_session_t * session)598 static apt_bool_t mrcp_server_engine_channels_update(mrcp_server_session_t *session)
599 {
600 mrcp_channel_t *channel;
601 mrcp_session_descriptor_t *descriptor = session->offer;
602 if(!descriptor) {
603 return FALSE;
604 }
605
606 mrcp_server_session_state_set(session,SESSION_STATE_INITIALIZING);
607
608 if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
609 if(session->offer) {
610 channel = mrcp_server_channel_find(session,&descriptor->resource_name);
611 if(channel && channel->engine_channel) {
612 /* open engine channel */
613 if(mrcp_engine_channel_virtual_open(channel->engine_channel) == TRUE) {
614 mrcp_server_session_subrequest_add(session);
615 }
616 }
617 }
618 }
619 else {
620 int i;
621 mrcp_control_descriptor_t *control_descriptor;
622 for(i=0; i<session->channels->nelts; i++) {
623 channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
624 if(!channel || !channel->engine_channel) continue;
625
626 control_descriptor = mrcp_session_control_media_get(descriptor,i);
627 if(!control_descriptor) continue;
628
629 if(control_descriptor->port) {
630 /* open engine channel */
631 if(mrcp_engine_channel_virtual_open(channel->engine_channel) == TRUE) {
632 mrcp_server_session_subrequest_add(session);
633 }
634 }
635 else {
636 /* close engine channel */
637 if(mrcp_engine_channel_virtual_close(channel->engine_channel) == TRUE) {
638 mrcp_server_session_subrequest_add(session);
639 }
640 }
641 }
642 }
643
644 if(!session->subrequest_count) {
645 mrcp_server_session_answer_send(session);
646 }
647 return TRUE;
648 }
649
mrcp_server_resource_offer_process(mrcp_server_session_t * session,mrcp_session_descriptor_t * descriptor)650 static apt_bool_t mrcp_server_resource_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor)
651 {
652 if(descriptor->resource_state == TRUE) {
653 /* setup */
654 mrcp_channel_t *channel;
655 int count = session->channels->nelts;
656 channel = mrcp_server_channel_find(session,&descriptor->resource_name);
657 if(channel) {
658 /* channel already exists */
659 return TRUE;
660 }
661 /* create new MRCP channel instance */
662 channel = mrcp_server_channel_create(session,&descriptor->resource_name,count,NULL);
663 if(!channel || !channel->resource) {
664 return FALSE;
665 }
666 /* add to channel array */
667 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Control Channel "APT_NAMESIDRES_FMT" [%d]",
668 MRCP_SESSION_NAMESID(session),
669 channel->resource->name.buf,
670 count);
671 APR_ARRAY_PUSH(session->channels,mrcp_channel_t*) = channel;
672 if(channel->engine_channel && channel->engine_channel->termination) {
673 mpf_termination_t *termination = channel->engine_channel->termination;
674 /* send add termination request (add to media context) */
675 if(mpf_engine_termination_message_add(
676 session->profile->media_engine,
677 MPF_ADD_TERMINATION,session->context,termination,NULL,
678 &session->mpf_task_msg) == TRUE) {
679 channel->waiting_for_termination = TRUE;
680 mrcp_server_session_subrequest_add(session);
681 }
682 }
683 }
684 else {
685 /* teardown */
686 }
687 return TRUE;
688 }
689
mrcp_server_control_media_offer_process(mrcp_server_session_t * session,mrcp_session_descriptor_t * descriptor)690 static apt_bool_t mrcp_server_control_media_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor)
691 {
692 mrcp_channel_t *channel;
693 mrcp_control_descriptor_t *control_descriptor;
694 int i;
695 int count = session->channels->nelts;
696 if(count > descriptor->control_media_arr->nelts) {
697 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Number of Control Channels [%d] > Number of Control Media in Offer [%d]",
698 count,descriptor->control_media_arr->nelts);
699 count = descriptor->control_media_arr->nelts;
700 }
701
702 /* update existing control channels */
703 for(i=0; i<count; i++) {
704 channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
705 if(!channel) continue;
706
707 channel->waiting_for_channel = FALSE;
708 /* get control descriptor */
709 control_descriptor = mrcp_session_control_media_get(descriptor,i);
710 if(!control_descriptor) continue;
711
712 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Modify Control Channel "APT_NAMESIDRES_FMT" [%d]",
713 MRCP_SESSION_NAMESID(session),
714 channel->resource->name.buf,
715 i);
716 if(channel->control_channel) {
717 /* send offer */
718 if(mrcp_server_control_channel_modify(channel->control_channel,control_descriptor) == TRUE) {
719 channel->waiting_for_channel = TRUE;
720 mrcp_server_session_subrequest_add(session);
721 }
722 }
723
724 if(channel->waiting_for_channel == FALSE) {
725 mrcp_control_descriptor_t *answer = mrcp_control_answer_create(control_descriptor,channel->pool);
726 answer->port = 0;
727 answer->session_id = session->base.id;
728 mrcp_session_control_media_set(session->answer,channel->id,answer);
729 }
730 }
731
732 /* add new control channels */
733 for(; i<descriptor->control_media_arr->nelts; i++) {
734 /* get control descriptor */
735 control_descriptor = mrcp_session_control_media_get(descriptor,i);
736 if(!control_descriptor) continue;
737
738 /* create new MRCP channel instance */
739 channel = mrcp_server_channel_create(session,&control_descriptor->resource_name,i,control_descriptor->cmid_arr);
740 if(!channel || !channel->resource) continue;
741
742 control_descriptor->session_id = session->base.id;
743 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Control Channel "APT_NAMESIDRES_FMT" [%d]",
744 MRCP_SESSION_NAMESID(session),
745 channel->resource->name.buf,
746 i);
747 APR_ARRAY_PUSH(session->channels,mrcp_channel_t*) = channel;
748
749 if(channel->control_channel) {
750 /* send modify connection request */
751 if(mrcp_server_control_channel_add(channel->control_channel,control_descriptor) == TRUE) {
752 channel->waiting_for_channel = TRUE;
753 mrcp_server_session_subrequest_add(session);
754 }
755 }
756
757 if(channel->waiting_for_channel == FALSE) {
758 mrcp_control_descriptor_t *answer = mrcp_control_answer_create(control_descriptor,channel->pool);
759 answer->port = 0;
760 answer->session_id = session->base.id;
761 mrcp_session_control_media_set(session->answer,channel->id,answer);
762 }
763
764 if(channel->engine_channel && channel->engine_channel->termination) {
765 mpf_termination_t *termination = channel->engine_channel->termination;
766 /* send add termination request (add to media context) */
767 if(mpf_engine_termination_message_add(
768 session->profile->media_engine,
769 MPF_ADD_TERMINATION,session->context,termination,NULL,
770 &session->mpf_task_msg) == TRUE) {
771 channel->waiting_for_termination = TRUE;
772 mrcp_server_session_subrequest_add(session);
773 }
774 }
775 }
776
777 return TRUE;
778 }
779
mrcp_server_associations_build(mrcp_server_session_t * session,mrcp_session_descriptor_t * descriptor,mrcp_termination_slot_t * slot)780 static mpf_rtp_termination_descriptor_t* mrcp_server_associations_build(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor, mrcp_termination_slot_t *slot)
781 {
782 int i;
783 mrcp_channel_t *channel;
784 mpf_audio_stream_t *audio_stream;
785 mpf_stream_capabilities_t *capabilities = NULL;
786 mpf_rtp_termination_descriptor_t *rtp_descriptor;
787 mpf_rtp_media_descriptor_t *media_descriptor = mrcp_session_audio_media_get(descriptor,slot->id);
788 if(!media_descriptor) {
789 return NULL;
790 }
791 /* construct termination descriptor */
792 rtp_descriptor = apr_palloc(session->base.pool,sizeof(mpf_rtp_termination_descriptor_t));
793 mpf_rtp_termination_descriptor_init(rtp_descriptor);
794 rtp_descriptor->audio.local = NULL;
795 rtp_descriptor->audio.remote = media_descriptor;
796 rtp_descriptor->audio.settings = session->profile->rtp_settings;
797
798 slot->mid = media_descriptor->mid;
799 slot->channels = apr_array_make(session->base.pool,1,sizeof(mrcp_channel_t*));
800 for(i=0; i<session->channels->nelts; i++) {
801 channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
802 if(!channel) continue;
803
804 if(session->terminations->nelts == 1 || (!channel->cmid_arr || mrcp_cmid_find(channel->cmid_arr,slot->mid) == TRUE)) {
805 APR_ARRAY_PUSH(slot->channels, mrcp_channel_t*) = channel;
806
807 audio_stream = NULL;
808 if(channel->engine_channel && channel->engine_channel->termination) {
809 audio_stream = mpf_termination_audio_stream_get(channel->engine_channel->termination);
810 }
811 if(!audio_stream) continue;
812
813 if(audio_stream->capabilities) {
814 /* set descriptor according to media termination(s)
815 of associated control channel(s) */
816 if(capabilities) {
817 mpf_stream_capabilities_merge(
818 capabilities,
819 audio_stream->capabilities,
820 session->base.pool);
821 }
822 else {
823 capabilities = mpf_stream_capabilities_clone(
824 audio_stream->capabilities,
825 session->base.pool);
826 }
827 }
828
829 if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
830 mpf_stream_direction_e direction = audio_stream->direction;
831 /* implicitly modify the descriptor, if needed */
832 if(media_descriptor->direction == STREAM_DIRECTION_NONE && mpf_codec_list_is_empty(&media_descriptor->codec_list) == TRUE) {
833 /* this is the case when SETUP contains no SDP, assume all the available codecs are offered */
834 if(mpf_codec_list_is_empty(&session->profile->rtp_settings->codec_list) == FALSE) {
835 mpf_codec_list_copy(&media_descriptor->codec_list,
836 &session->profile->rtp_settings->codec_list,
837 session->base.pool);
838 }
839 }
840
841 media_descriptor->direction |= direction;
842 if(media_descriptor->state == MPF_MEDIA_DISABLED) {
843 media_descriptor->state = MPF_MEDIA_ENABLED;
844 }
845 }
846 }
847 }
848 if(capabilities) {
849 capabilities->direction = mpf_stream_reverse_direction_get(capabilities->direction);
850 rtp_descriptor->audio.capabilities = capabilities;
851 }
852 return rtp_descriptor;
853 }
854
mrcp_server_associations_set(mrcp_server_session_t * session,mrcp_session_descriptor_t * descriptor,mrcp_termination_slot_t * slot)855 static apt_bool_t mrcp_server_associations_set(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor, mrcp_termination_slot_t *slot)
856 {
857 int i;
858 mrcp_channel_t *channel;
859 for(i=0; i<slot->channels->nelts; i++) {
860 channel = ((mrcp_channel_t**)slot->channels->elts)[i];
861 if(!channel || !channel->engine_channel) continue;
862
863 if(mpf_engine_assoc_message_add(
864 session->profile->media_engine,
865 MPF_ADD_ASSOCIATION,session->context,slot->termination,channel->engine_channel->termination,
866 &session->mpf_task_msg) == TRUE) {
867 mrcp_server_session_subrequest_add(session);
868 }
869 }
870 return TRUE;
871 }
872
mrcp_server_av_media_offer_process(mrcp_server_session_t * session,mrcp_session_descriptor_t * descriptor)873 static apt_bool_t mrcp_server_av_media_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor)
874 {
875 mpf_rtp_termination_descriptor_t *rtp_descriptor;
876 mrcp_termination_slot_t *slot;
877 int i;
878 int count = session->terminations->nelts;
879 if(!descriptor->audio_media_arr->nelts) {
880 /* no media to process */
881 return TRUE;
882 }
883 if(count > descriptor->audio_media_arr->nelts) {
884 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Number of Terminations [%d] > Number of Audio Media in Offer [%d]",
885 count,descriptor->audio_media_arr->nelts);
886 count = descriptor->audio_media_arr->nelts;
887 }
888
889 /* update existing terminations */
890 for(i=0; i<count; i++) {
891 /* get existing termination */
892 slot = &APR_ARRAY_IDX(session->terminations,i,mrcp_termination_slot_t);
893 if(!slot->termination) continue;
894
895 /* build associations between specified RTP termination and control channels */
896 rtp_descriptor = mrcp_server_associations_build(session,descriptor,slot);
897 if(!rtp_descriptor) continue;
898
899 /* send modify termination request */
900 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Modify Media Termination "APT_NAMESIDRES_FMT" [%d]",
901 MRCP_SESSION_NAMESID(session),
902 mpf_termination_name_get(slot->termination),
903 i);
904 if(mpf_engine_termination_message_add(
905 session->profile->media_engine,
906 MPF_MODIFY_TERMINATION,session->context,slot->termination,rtp_descriptor,
907 &session->mpf_task_msg) == TRUE) {
908 slot->waiting = TRUE;
909 mrcp_server_session_subrequest_add(session);
910 }
911
912 /* set built associations */
913 mrcp_server_associations_set(session,descriptor,slot);
914 }
915
916 /* add new terminations */
917 for(; i<descriptor->audio_media_arr->nelts; i++) {
918 mpf_termination_t *termination;
919 /* create new RTP termination instance */
920 termination = mpf_termination_create(session->profile->rtp_termination_factory,session,session->base.pool);
921 /* add to termination array */
922 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Media Termination "APT_NAMESIDRES_FMT" [%d]",
923 MRCP_SESSION_NAMESID(session),
924 mpf_termination_name_get(termination),
925 i);
926 slot = apr_array_push(session->terminations);
927 slot->id = i;
928 slot->mid = 0;
929 slot->waiting = FALSE;
930 slot->termination = termination;
931 slot->channels = NULL;
932
933 /* build associations between specified RTP termination and control channels */
934 rtp_descriptor = mrcp_server_associations_build(session,descriptor,slot);
935 if(!rtp_descriptor) continue;
936
937 /* send add termination request (add to media context) */
938 if(mpf_engine_termination_message_add(
939 session->profile->media_engine,
940 MPF_ADD_TERMINATION,session->context,termination,rtp_descriptor,
941 &session->mpf_task_msg) == TRUE) {
942 slot->waiting = TRUE;
943 mrcp_server_session_subrequest_add(session);
944 }
945
946 /* set built associations */
947 mrcp_server_associations_set(session,descriptor,slot);
948 }
949 return TRUE;
950 }
951
mrcp_server_session_answer_send(mrcp_server_session_t * session)952 static apt_bool_t mrcp_server_session_answer_send(mrcp_server_session_t *session)
953 {
954 apt_bool_t status;
955 mrcp_session_descriptor_t *descriptor = session->answer;
956 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Answer "APT_NAMESID_FMT" [c:%d a:%d v:%d] Status %s",
957 MRCP_SESSION_NAMESID(session),
958 descriptor->control_media_arr->nelts,
959 descriptor->audio_media_arr->nelts,
960 descriptor->video_media_arr->nelts,
961 mrcp_session_status_phrase_get(descriptor->status));
962 status = mrcp_session_answer(&session->base,descriptor);
963 session->offer = NULL;
964 session->answer = NULL;
965
966 session->active_request = apt_list_pop_front(session->request_queue);
967 if(session->active_request) {
968 mrcp_server_signaling_message_dispatch(session,session->active_request);
969 }
970 return status;
971 }
972
mrcp_server_session_terminate_send(mrcp_server_session_t * session)973 static apt_bool_t mrcp_server_session_terminate_send(mrcp_server_session_t *session)
974 {
975 int i;
976 mrcp_channel_t *channel;
977 for(i=0; i<session->channels->nelts; i++) {
978 channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
979 if(!channel) continue;
980
981 if(channel->control_channel) {
982 mrcp_server_control_channel_destroy(channel->control_channel);
983 channel->control_channel = NULL;
984 }
985 if(channel->engine_channel) {
986 mrcp_engine_channel_virtual_destroy(channel->engine_channel);
987 channel->engine_channel = NULL;
988 }
989 }
990 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Session Terminated "APT_NAMESID_FMT,MRCP_SESSION_NAMESID(session));
991 mrcp_session_terminate_response(&session->base);
992 return TRUE;
993 }
994
995
mrcp_server_rtp_termination_find(mrcp_server_session_t * session,mpf_termination_t * termination)996 static mrcp_termination_slot_t* mrcp_server_rtp_termination_find(mrcp_server_session_t *session, mpf_termination_t *termination)
997 {
998 int i;
999 mrcp_termination_slot_t *slot;
1000 for(i=0; i<session->terminations->nelts; i++) {
1001 slot = &APR_ARRAY_IDX(session->terminations,i,mrcp_termination_slot_t);
1002 if(slot->termination == termination) {
1003 return slot;
1004 }
1005 }
1006 return NULL;
1007 }
1008
mrcp_server_channel_termination_find(mrcp_server_session_t * session,mpf_termination_t * termination)1009 static mrcp_channel_t* mrcp_server_channel_termination_find(mrcp_server_session_t *session, mpf_termination_t *termination)
1010 {
1011 int i;
1012 mrcp_channel_t *channel;
1013 for(i=0; i<session->channels->nelts; i++) {
1014 channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
1015 if(!channel) continue;
1016
1017 if(channel->engine_channel && channel->engine_channel->termination == termination) {
1018 return channel;
1019 }
1020 }
1021 return NULL;
1022 }
1023
mrcp_server_channel_find(mrcp_server_session_t * session,const apt_str_t * resource_name)1024 static mrcp_channel_t* mrcp_server_channel_find(mrcp_server_session_t *session, const apt_str_t *resource_name)
1025 {
1026 int i;
1027 mrcp_channel_t *channel;
1028 for(i=0; i<session->channels->nelts; i++) {
1029 channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
1030 if(!channel) continue;
1031
1032 if(apt_string_compare(&channel->resource->name,resource_name) == TRUE) {
1033 return channel;
1034 }
1035 }
1036 return NULL;
1037 }
1038
mrcp_server_on_termination_modify(mrcp_server_session_t * session,const mpf_message_t * mpf_message)1039 static apt_bool_t mrcp_server_on_termination_modify(mrcp_server_session_t *session, const mpf_message_t *mpf_message)
1040 {
1041 mrcp_termination_slot_t *termination_slot;
1042 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Media Termination Modified "APT_NAMESIDRES_FMT,
1043 MRCP_SESSION_NAMESID(session),
1044 mpf_termination_name_get(mpf_message->termination));
1045 termination_slot = mrcp_server_rtp_termination_find(session,mpf_message->termination);
1046 if(termination_slot) {
1047 /* rtp termination */
1048 mpf_rtp_termination_descriptor_t *rtp_descriptor;
1049 if(termination_slot->waiting == FALSE) {
1050 return FALSE;
1051 }
1052 termination_slot->waiting = FALSE;
1053 rtp_descriptor = mpf_message->descriptor;
1054 if(rtp_descriptor->audio.local) {
1055 session->answer->ip = rtp_descriptor->audio.local->ip;
1056 session->answer->ext_ip = rtp_descriptor->audio.local->ext_ip;
1057 mrcp_session_audio_media_set(session->answer,termination_slot->id,rtp_descriptor->audio.local);
1058 }
1059 mrcp_server_session_subrequest_remove(session);
1060 }
1061 else {
1062 /* engine channel termination */
1063 mrcp_channel_t *channel = mrcp_server_channel_termination_find(session,mpf_message->termination);
1064 if(channel && channel->waiting_for_termination == TRUE) {
1065 channel->waiting_for_termination = FALSE;
1066 mrcp_server_session_subrequest_remove(session);
1067 }
1068 }
1069 return TRUE;
1070 }
1071
mrcp_server_on_termination_subtract(mrcp_server_session_t * session,const mpf_message_t * mpf_message)1072 static apt_bool_t mrcp_server_on_termination_subtract(mrcp_server_session_t *session, const mpf_message_t *mpf_message)
1073 {
1074 mrcp_termination_slot_t *termination_slot;
1075 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Media Termination Subtracted "APT_NAMESIDRES_FMT,
1076 MRCP_SESSION_NAMESID(session),
1077 mpf_termination_name_get(mpf_message->termination));
1078 termination_slot = mrcp_server_rtp_termination_find(session,mpf_message->termination);
1079 if(termination_slot) {
1080 /* rtp termination */
1081 if(termination_slot->waiting == FALSE) {
1082 return FALSE;
1083 }
1084 termination_slot->waiting = FALSE;
1085 mrcp_server_session_subrequest_remove(session);
1086 }
1087 else {
1088 /* engine channel termination */
1089 mrcp_channel_t *channel = mrcp_server_channel_termination_find(session,mpf_message->termination);
1090 if(channel && channel->waiting_for_termination == TRUE) {
1091 channel->waiting_for_termination = FALSE;
1092 mrcp_server_session_subrequest_remove(session);
1093 }
1094 }
1095 return TRUE;
1096 }
1097
mrcp_server_mpf_message_process(mpf_message_container_t * mpf_message_container)1098 apt_bool_t mrcp_server_mpf_message_process(mpf_message_container_t *mpf_message_container)
1099 {
1100 apr_size_t i;
1101 mrcp_server_session_t *session;
1102 const mpf_message_t *mpf_message;
1103 for(i=0; i<mpf_message_container->count; i++) {
1104 mpf_message = &mpf_message_container->messages[i];
1105 if(mpf_message->context) {
1106 session = mpf_engine_context_object_get(mpf_message->context);
1107 }
1108 else {
1109 session = NULL;
1110 }
1111 if(!session) {
1112 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Received MPF Message: NULL session");
1113 continue;
1114 }
1115 if(mpf_message->message_type == MPF_MESSAGE_TYPE_RESPONSE) {
1116 switch(mpf_message->command_id) {
1117 case MPF_ADD_TERMINATION:
1118 mrcp_server_on_termination_modify(session,mpf_message);
1119 break;
1120 case MPF_MODIFY_TERMINATION:
1121 mrcp_server_on_termination_modify(session,mpf_message);
1122 break;
1123 case MPF_SUBTRACT_TERMINATION:
1124 mrcp_server_on_termination_subtract(session,mpf_message);
1125 break;
1126 case MPF_ADD_ASSOCIATION:
1127 case MPF_REMOVE_ASSOCIATION:
1128 case MPF_RESET_ASSOCIATIONS:
1129 case MPF_APPLY_TOPOLOGY:
1130 case MPF_DESTROY_TOPOLOGY:
1131 mrcp_server_session_subrequest_remove(session);
1132 break;
1133 default:
1134 break;
1135 }
1136 }
1137 else if(mpf_message->message_type == MPF_MESSAGE_TYPE_EVENT) {
1138 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process MPF Event");
1139 }
1140 }
1141 return TRUE;
1142 }
1143
state_machine_on_message_dispatch(mrcp_state_machine_t * state_machine,mrcp_message_t * message)1144 static apt_bool_t state_machine_on_message_dispatch(mrcp_state_machine_t *state_machine, mrcp_message_t *message)
1145 {
1146 mrcp_channel_t *channel = state_machine->obj;
1147
1148 if(message->start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
1149 /* send request message to engine for actual processing */
1150 if(channel->engine_channel) {
1151 mrcp_engine_channel_request_process(channel->engine_channel,message);
1152 }
1153 }
1154 else if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
1155 mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
1156 /* send response message to client */
1157 if(channel->control_channel) {
1158 /* MRCPv2 */
1159 mrcp_server_control_message_send(channel->control_channel,message);
1160 }
1161 else {
1162 /* MRCPv1 */
1163 mrcp_session_control_response(channel->session,message);
1164 }
1165
1166 session->active_request = apt_list_pop_front(session->request_queue);
1167 if(session->active_request) {
1168 mrcp_server_signaling_message_dispatch(session,session->active_request);
1169 }
1170 }
1171 else {
1172 /* send event message to client */
1173 if(channel->control_channel) {
1174 /* MRCPv2 */
1175 mrcp_server_control_message_send(channel->control_channel,message);
1176 }
1177 else {
1178 /* MRCPv1 */
1179 mrcp_session_control_response(channel->session,message);
1180 }
1181 }
1182 return TRUE;
1183 }
1184
state_machine_on_deactivate(mrcp_state_machine_t * state_machine)1185 static apt_bool_t state_machine_on_deactivate(mrcp_state_machine_t *state_machine)
1186 {
1187 mrcp_channel_t *channel = state_machine->obj;
1188 mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
1189 mrcp_server_session_subrequest_remove(session);
1190 return TRUE;
1191 }
1192