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.c 2251 2014-11-21 02:36:44Z achaloyan@gmail.com $
17 */
18
19 #include "mrcp_server.h"
20 #include "mrcp_server_session.h"
21 #include "mrcp_message.h"
22 #include "mrcp_resource_factory.h"
23 #include "mrcp_resource.h"
24 #include "mrcp_engine_factory.h"
25 #include "mrcp_engine_loader.h"
26 #include "mrcp_sig_agent.h"
27 #include "mrcp_server_connection.h"
28 #include "mpf_termination_factory.h"
29 #include "apt_pool.h"
30 #include "apt_consumer_task.h"
31 #include "apt_obj_list.h"
32 #include "apt_log.h"
33
34 #define SERVER_TASK_NAME "MRCP Server"
35
36 /** MRCP server */
37 struct mrcp_server_t {
38 /** Main message processing task */
39 apt_consumer_task_t *task;
40
41 /** MRCP resource factory */
42 mrcp_resource_factory_t *resource_factory;
43 /** MRCP engine factory */
44 mrcp_engine_factory_t *engine_factory;
45 /** Loader of plugins for MRCP engines */
46 mrcp_engine_loader_t *engine_loader;
47
48 /** Codec manager */
49 mpf_codec_manager_t *codec_manager;
50 /** Table of media processing engines (mpf_engine_t*) */
51 apr_hash_t *media_engine_table;
52 /** Table of RTP termination factories (mpf_termination_factory_t*) */
53 apr_hash_t *rtp_factory_table;
54 /** Table of signaling agents (mrcp_sig_agent_t*) */
55 apr_hash_t *sig_agent_table;
56 /** Table of connection agents (mrcp_connection_agent_t*) */
57 apr_hash_t *cnt_agent_table;
58 /** Table of RTP settings (mpf_rtp_settings_t*) */
59 apr_hash_t *rtp_settings_table;
60 /** Table of profiles (mrcp_server_profile_t*) */
61 apr_hash_t *profile_table;
62
63 /** Table of sessions */
64 apr_hash_t *session_table;
65
66 /** Connection task message pool */
67 apt_task_msg_pool_t *connection_msg_pool;
68 /** Engine task message pool */
69 apt_task_msg_pool_t *engine_msg_pool;
70
71 /** Dir layout structure */
72 apt_dir_layout_t *dir_layout;
73 /** Time server started at */
74 apr_time_t start_time;
75 /** Memory pool */
76 apr_pool_t *pool;
77 };
78
79
80 typedef enum {
81 MRCP_SERVER_SIGNALING_TASK_MSG = TASK_MSG_USER,
82 MRCP_SERVER_CONNECTION_TASK_MSG,
83 MRCP_SERVER_ENGINE_TASK_MSG,
84 MRCP_SERVER_MEDIA_TASK_MSG
85 } mrcp_server_task_msg_type_e;
86
87
88 static apt_bool_t mrcp_server_offer_signal(mrcp_session_t *session, mrcp_session_descriptor_t *descriptor);
89 static apt_bool_t mrcp_server_terminate_signal(mrcp_session_t *session);
90 static apt_bool_t mrcp_server_control_signal(mrcp_session_t *session, mrcp_message_t *message);
91
92 static const mrcp_session_request_vtable_t session_request_vtable = {
93 mrcp_server_offer_signal,
94 mrcp_server_terminate_signal,
95 mrcp_server_control_signal,
96 NULL /* mrcp_server_discover_signal */
97 };
98
99
100 /* Connection agent interface */
101 typedef enum {
102 CONNECTION_AGENT_TASK_MSG_ADD_CHANNEL,
103 CONNECTION_AGENT_TASK_MSG_MODIFY_CHANNEL,
104 CONNECTION_AGENT_TASK_MSG_REMOVE_CHANNEL,
105 CONNECTION_AGENT_TASK_MSG_RECEIVE_MESSAGE,
106 CONNECTION_AGENT_TASK_MSG_DISCONNECT
107 } connection_agent_task_msg_type_e;
108
109 typedef struct connection_agent_task_msg_data_t connection_agent_task_msg_data_t;
110 struct connection_agent_task_msg_data_t {
111 mrcp_channel_t *channel;
112 mrcp_control_descriptor_t *descriptor;
113 mrcp_message_t *message;
114 apt_bool_t status;
115 };
116
117 static apt_bool_t mrcp_server_channel_add_signal(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor, apt_bool_t status);
118 static apt_bool_t mrcp_server_channel_modify_signal(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor, apt_bool_t status);
119 static apt_bool_t mrcp_server_channel_remove_signal(mrcp_control_channel_t *channel, apt_bool_t status);
120 static apt_bool_t mrcp_server_message_signal(mrcp_control_channel_t *channel, mrcp_message_t *message);
121 static apt_bool_t mrcp_server_disconnect_signal(mrcp_control_channel_t *channel);
122
123 static const mrcp_connection_event_vtable_t connection_method_vtable = {
124 mrcp_server_channel_add_signal,
125 mrcp_server_channel_modify_signal,
126 mrcp_server_channel_remove_signal,
127 mrcp_server_message_signal,
128 mrcp_server_disconnect_signal
129 };
130
131
132 /* MRCP engine interface */
133 typedef enum {
134 ENGINE_TASK_MSG_OPEN_ENGINE,
135 ENGINE_TASK_MSG_CLOSE_ENGINE,
136 ENGINE_TASK_MSG_OPEN_CHANNEL,
137 ENGINE_TASK_MSG_CLOSE_CHANNEL,
138 ENGINE_TASK_MSG_MESSAGE
139 } engine_task_msg_type_e;
140
141 typedef struct engine_task_msg_data_t engine_task_msg_data_t;
142 struct engine_task_msg_data_t {
143 mrcp_engine_t *engine;
144 mrcp_channel_t *channel;
145 apt_bool_t status;
146 mrcp_message_t *mrcp_message;
147 };
148
149 static apt_bool_t mrcp_server_engine_open_signal(mrcp_engine_t *engine, apt_bool_t status);
150 static apt_bool_t mrcp_server_engine_close_signal(mrcp_engine_t *engine);
151
152 const mrcp_engine_event_vtable_t engine_vtable = {
153 mrcp_server_engine_open_signal,
154 mrcp_server_engine_close_signal,
155 };
156
157 static apt_bool_t mrcp_server_channel_open_signal(mrcp_engine_channel_t *channel, apt_bool_t status);
158 static apt_bool_t mrcp_server_channel_close_signal(mrcp_engine_channel_t *channel);
159 static apt_bool_t mrcp_server_channel_message_signal(mrcp_engine_channel_t *channel, mrcp_message_t *message);
160
161 const mrcp_engine_channel_event_vtable_t engine_channel_vtable = {
162 mrcp_server_channel_open_signal,
163 mrcp_server_channel_close_signal,
164 mrcp_server_channel_message_signal
165 };
166
167 /* Task interface */
168 static apt_bool_t mrcp_server_msg_process(apt_task_t *task, apt_task_msg_t *msg);
169 static apt_bool_t mrcp_server_start_request_process(apt_task_t *task);
170 static apt_bool_t mrcp_server_terminate_request_process(apt_task_t *task);
171 static void mrcp_server_on_start_complete(apt_task_t *task);
172 static void mrcp_server_on_terminate_complete(apt_task_t *task);
173
174 static mrcp_session_t* mrcp_server_sig_agent_session_create(mrcp_sig_agent_t *signaling_agent);
175
176
177 /** Create MRCP server instance */
mrcp_server_create(apt_dir_layout_t * dir_layout)178 MRCP_DECLARE(mrcp_server_t*) mrcp_server_create(apt_dir_layout_t *dir_layout)
179 {
180 mrcp_server_t *server;
181 apr_pool_t *pool;
182 apt_task_t *task;
183 apt_task_vtable_t *vtable;
184 apt_task_msg_pool_t *msg_pool;
185
186 pool = apt_pool_create();
187 if(!pool) {
188 return NULL;
189 }
190
191 apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "SERVER_TASK_NAME);
192 server = apr_palloc(pool,sizeof(mrcp_server_t));
193 server->pool = pool;
194 server->dir_layout = dir_layout;
195 server->resource_factory = NULL;
196 server->engine_factory = NULL;
197 server->engine_loader = NULL;
198 server->media_engine_table = NULL;
199 server->rtp_factory_table = NULL;
200 server->sig_agent_table = NULL;
201 server->cnt_agent_table = NULL;
202 server->rtp_settings_table = NULL;
203 server->profile_table = NULL;
204 server->session_table = NULL;
205 server->connection_msg_pool = NULL;
206 server->engine_msg_pool = NULL;
207
208 msg_pool = apt_task_msg_pool_create_dynamic(0,pool);
209
210 server->task = apt_consumer_task_create(server,msg_pool,pool);
211 if(!server->task) {
212 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Server Task");
213 return NULL;
214 }
215 task = apt_consumer_task_base_get(server->task);
216 apt_task_name_set(task,SERVER_TASK_NAME);
217 vtable = apt_task_vtable_get(task);
218 if(vtable) {
219 vtable->process_msg = mrcp_server_msg_process;
220 vtable->process_start = mrcp_server_start_request_process;
221 vtable->process_terminate = mrcp_server_terminate_request_process;
222 vtable->on_start_complete = mrcp_server_on_start_complete;
223 vtable->on_terminate_complete = mrcp_server_on_terminate_complete;
224 }
225
226 server->engine_factory = mrcp_engine_factory_create(server->pool);
227 server->engine_loader = mrcp_engine_loader_create(server->pool);
228
229 server->media_engine_table = apr_hash_make(server->pool);
230 server->rtp_factory_table = apr_hash_make(server->pool);
231 server->rtp_settings_table = apr_hash_make(server->pool);
232 server->sig_agent_table = apr_hash_make(server->pool);
233 server->cnt_agent_table = apr_hash_make(server->pool);
234
235 server->profile_table = apr_hash_make(server->pool);
236
237 server->session_table = apr_hash_make(server->pool);
238 return server;
239 }
240
241 /** Start message processing loop */
mrcp_server_start(mrcp_server_t * server)242 MRCP_DECLARE(apt_bool_t) mrcp_server_start(mrcp_server_t *server)
243 {
244 apt_task_t *task;
245 if(!server || !server->task) {
246 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid Server");
247 return FALSE;
248 }
249 server->start_time = apr_time_now();
250 task = apt_consumer_task_base_get(server->task);
251 if(apt_task_start(task) == FALSE) {
252 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Start Server Task");
253 return FALSE;
254 }
255 return TRUE;
256 }
257
258 /** Shutdown message processing loop */
mrcp_server_shutdown(mrcp_server_t * server)259 MRCP_DECLARE(apt_bool_t) mrcp_server_shutdown(mrcp_server_t *server)
260 {
261 apt_task_t *task;
262 apr_time_t uptime;
263 if(!server || !server->task) {
264 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid Server");
265 return FALSE;
266 }
267 task = apt_consumer_task_base_get(server->task);
268 if(apt_task_terminate(task,TRUE) == FALSE) {
269 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Shutdown Server Task");
270 return FALSE;
271 }
272 server->session_table = NULL;
273 uptime = apr_time_now() - server->start_time;
274 apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Server Uptime [%"APR_TIME_T_FMT" sec]", apr_time_sec(uptime));
275 return TRUE;
276 }
277
278 /** Destroy MRCP server */
mrcp_server_destroy(mrcp_server_t * server)279 MRCP_DECLARE(apt_bool_t) mrcp_server_destroy(mrcp_server_t *server)
280 {
281 apt_task_t *task;
282 if(!server || !server->task) {
283 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid Server");
284 return FALSE;
285 }
286
287 mrcp_engine_factory_destroy(server->engine_factory);
288 mrcp_engine_loader_destroy(server->engine_loader);
289
290 task = apt_consumer_task_base_get(server->task);
291 apt_task_destroy(task);
292
293 apr_pool_destroy(server->pool);
294 return TRUE;
295 }
296
297 /** Register MRCP resource factory */
mrcp_server_resource_factory_register(mrcp_server_t * server,mrcp_resource_factory_t * resource_factory)298 MRCP_DECLARE(apt_bool_t) mrcp_server_resource_factory_register(mrcp_server_t *server, mrcp_resource_factory_t *resource_factory)
299 {
300 if(!resource_factory) {
301 return FALSE;
302 }
303 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Resource Factory");
304 server->resource_factory = resource_factory;
305 return TRUE;
306 }
307
308 /** Register MRCP engine */
mrcp_server_engine_register(mrcp_server_t * server,mrcp_engine_t * engine)309 MRCP_DECLARE(apt_bool_t) mrcp_server_engine_register(mrcp_server_t *server, mrcp_engine_t *engine)
310 {
311 if(!engine || !engine->id) {
312 return FALSE;
313 }
314
315 if(!server->engine_msg_pool) {
316 server->engine_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(engine_task_msg_data_t),server->pool);
317 }
318 engine->codec_manager = server->codec_manager;
319 engine->dir_layout = server->dir_layout;
320 engine->event_vtable = &engine_vtable;
321 engine->event_obj = server;
322 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register MRCP Engine [%s]",engine->id);
323 return mrcp_engine_factory_engine_register(server->engine_factory,engine);
324 }
325
326 /** Register codec manager */
mrcp_server_codec_manager_register(mrcp_server_t * server,mpf_codec_manager_t * codec_manager)327 MRCP_DECLARE(apt_bool_t) mrcp_server_codec_manager_register(mrcp_server_t *server, mpf_codec_manager_t *codec_manager)
328 {
329 if(!codec_manager) {
330 return FALSE;
331 }
332 server->codec_manager = codec_manager;
333 return TRUE;
334 }
335
336 /** Get registered codec manager */
mrcp_server_codec_manager_get(const mrcp_server_t * server)337 MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_server_codec_manager_get(const mrcp_server_t *server)
338 {
339 return server->codec_manager;
340 }
341
342 /** Register media engine */
mrcp_server_media_engine_register(mrcp_server_t * server,mpf_engine_t * media_engine)343 MRCP_DECLARE(apt_bool_t) mrcp_server_media_engine_register(mrcp_server_t *server, mpf_engine_t *media_engine)
344 {
345 const char *id;
346 if(!media_engine) {
347 return FALSE;
348 }
349 id = mpf_engine_id_get(media_engine);
350 if(!id) {
351 return FALSE;
352 }
353
354 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Media Engine [%s]",id);
355 mpf_engine_codec_manager_register(media_engine,server->codec_manager);
356 apr_hash_set(server->media_engine_table,id,APR_HASH_KEY_STRING,media_engine);
357 mpf_engine_task_msg_type_set(media_engine,MRCP_SERVER_MEDIA_TASK_MSG);
358 if(server->task) {
359 apt_task_t *media_task = mpf_task_get(media_engine);
360 apt_task_t *task = apt_consumer_task_base_get(server->task);
361 apt_task_add(task,media_task);
362 }
363 return TRUE;
364 }
365
366 /** Get media engine by name */
mrcp_server_media_engine_get(const mrcp_server_t * server,const char * name)367 MRCP_DECLARE(mpf_engine_t*) mrcp_server_media_engine_get(const mrcp_server_t *server, const char *name)
368 {
369 return apr_hash_get(server->media_engine_table,name,APR_HASH_KEY_STRING);
370 }
371
372 /** Register RTP termination factory */
mrcp_server_rtp_factory_register(mrcp_server_t * server,mpf_termination_factory_t * rtp_termination_factory,const char * name)373 MRCP_DECLARE(apt_bool_t) mrcp_server_rtp_factory_register(mrcp_server_t *server, mpf_termination_factory_t *rtp_termination_factory, const char *name)
374 {
375 if(!rtp_termination_factory || !name) {
376 return FALSE;
377 }
378 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register RTP Termination Factory [%s]",name);
379 apr_hash_set(server->rtp_factory_table,name,APR_HASH_KEY_STRING,rtp_termination_factory);
380 return TRUE;
381 }
382
383 /** Get RTP termination factory by name */
mrcp_server_rtp_factory_get(const mrcp_server_t * server,const char * name)384 MRCP_DECLARE(mpf_termination_factory_t*) mrcp_server_rtp_factory_get(const mrcp_server_t *server, const char *name)
385 {
386 return apr_hash_get(server->rtp_factory_table,name,APR_HASH_KEY_STRING);
387 }
388
389 /** Register RTP settings */
mrcp_server_rtp_settings_register(mrcp_server_t * server,mpf_rtp_settings_t * rtp_settings,const char * name)390 MRCP_DECLARE(apt_bool_t) mrcp_server_rtp_settings_register(mrcp_server_t *server, mpf_rtp_settings_t *rtp_settings, const char *name)
391 {
392 if(!rtp_settings || !name) {
393 return FALSE;
394 }
395 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register RTP Settings [%s]",name);
396 apr_hash_set(server->rtp_settings_table,name,APR_HASH_KEY_STRING,rtp_settings);
397 return TRUE;
398 }
399
400 /** Get RTP settings by name */
mrcp_server_rtp_settings_get(const mrcp_server_t * server,const char * name)401 MRCP_DECLARE(mpf_rtp_settings_t*) mrcp_server_rtp_settings_get(const mrcp_server_t *server, const char *name)
402 {
403 return apr_hash_get(server->rtp_settings_table,name,APR_HASH_KEY_STRING);
404 }
405
406 /** Register MRCP signaling agent */
mrcp_server_signaling_agent_register(mrcp_server_t * server,mrcp_sig_agent_t * signaling_agent)407 MRCP_DECLARE(apt_bool_t) mrcp_server_signaling_agent_register(mrcp_server_t *server, mrcp_sig_agent_t *signaling_agent)
408 {
409 if(!signaling_agent || !signaling_agent->id) {
410 return FALSE;
411 }
412 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Signaling Agent [%s]",signaling_agent->id);
413 signaling_agent->parent = server;
414 signaling_agent->resource_factory = server->resource_factory;
415 signaling_agent->create_server_session = mrcp_server_sig_agent_session_create;
416 signaling_agent->msg_pool = apt_task_msg_pool_create_dynamic(sizeof(mrcp_signaling_message_t*),server->pool);
417 apr_hash_set(server->sig_agent_table,signaling_agent->id,APR_HASH_KEY_STRING,signaling_agent);
418 if(server->task) {
419 apt_task_t *task = apt_consumer_task_base_get(server->task);
420 apt_task_add(task,signaling_agent->task);
421 }
422 return TRUE;
423 }
424
425 /** Get signaling agent by name */
mrcp_server_signaling_agent_get(const mrcp_server_t * server,const char * name)426 MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_server_signaling_agent_get(const mrcp_server_t *server, const char *name)
427 {
428 return apr_hash_get(server->sig_agent_table,name,APR_HASH_KEY_STRING);
429 }
430
431 /** Register MRCP connection agent (MRCPv2 only) */
mrcp_server_connection_agent_register(mrcp_server_t * server,mrcp_connection_agent_t * connection_agent)432 MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_register(mrcp_server_t *server, mrcp_connection_agent_t *connection_agent)
433 {
434 const char *id;
435 if(!connection_agent) {
436 return FALSE;
437 }
438 id = mrcp_server_connection_agent_id_get(connection_agent);
439 if(!id) {
440 return FALSE;
441 }
442 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Connection Agent [%s]",id);
443 mrcp_server_connection_resource_factory_set(connection_agent,server->resource_factory);
444 mrcp_server_connection_agent_handler_set(connection_agent,server,&connection_method_vtable);
445 server->connection_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(connection_agent_task_msg_data_t),server->pool);
446 apr_hash_set(server->cnt_agent_table,id,APR_HASH_KEY_STRING,connection_agent);
447 if(server->task) {
448 apt_task_t *task = apt_consumer_task_base_get(server->task);
449 apt_task_t *connection_task = mrcp_server_connection_agent_task_get(connection_agent);
450 apt_task_add(task,connection_task);
451 }
452 return TRUE;
453 }
454
455 /** Get connection agent by name */
mrcp_server_connection_agent_get(const mrcp_server_t * server,const char * name)456 MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_server_connection_agent_get(const mrcp_server_t *server, const char *name)
457 {
458 return apr_hash_get(server->cnt_agent_table,name,APR_HASH_KEY_STRING);
459 }
460
461 /** Create MRCP profile */
mrcp_server_profile_create(const char * id,mrcp_version_e mrcp_version,mrcp_resource_factory_t * resource_factory,mrcp_sig_agent_t * signaling_agent,mrcp_connection_agent_t * connection_agent,mpf_engine_t * media_engine,mpf_termination_factory_t * rtp_factory,mpf_rtp_settings_t * rtp_settings,apr_pool_t * pool)462 MRCP_DECLARE(mrcp_server_profile_t*) mrcp_server_profile_create(
463 const char *id,
464 mrcp_version_e mrcp_version,
465 mrcp_resource_factory_t *resource_factory,
466 mrcp_sig_agent_t *signaling_agent,
467 mrcp_connection_agent_t *connection_agent,
468 mpf_engine_t *media_engine,
469 mpf_termination_factory_t *rtp_factory,
470 mpf_rtp_settings_t *rtp_settings,
471 apr_pool_t *pool)
472 {
473 mrcp_server_profile_t *profile = apr_palloc(pool,sizeof(mrcp_server_profile_t));
474 profile->id = id;
475 profile->mrcp_version = mrcp_version;
476 profile->resource_factory = resource_factory;
477 profile->engine_table = NULL;
478 profile->media_engine = media_engine;
479 profile->rtp_termination_factory = rtp_factory;
480 profile->rtp_settings = rtp_settings;
481 profile->signaling_agent = signaling_agent;
482 profile->connection_agent = connection_agent;
483
484 mpf_termination_factory_engine_assign(rtp_factory,media_engine);
485 return profile;
486 }
487
mrcp_server_engine_table_make(mrcp_server_t * server,mrcp_server_profile_t * profile,apr_table_t * plugin_map)488 static apt_bool_t mrcp_server_engine_table_make(mrcp_server_t *server, mrcp_server_profile_t *profile, apr_table_t *plugin_map)
489 {
490 int i;
491 mrcp_resource_t *resource;
492 const char *plugin_name = NULL;
493 mrcp_engine_t *engine;
494
495 profile->engine_table = apr_hash_make(server->pool);
496 for(i=0; i<MRCP_RESOURCE_TYPE_COUNT; i++) {
497 resource = mrcp_resource_get(server->resource_factory,i);
498 if(!resource) continue;
499
500 engine = NULL;
501 /* first, try to find engine by name specified in plugin map (if available) */
502 if(plugin_map) {
503 plugin_name = apr_table_get(plugin_map,resource->name.buf);
504 if(plugin_name) {
505 engine = mrcp_engine_factory_engine_get(server->engine_factory,plugin_name);
506 }
507 }
508
509 /* next, if no engine found or specified, try to find the first available one */
510 if(!engine) {
511 engine = mrcp_engine_factory_engine_find(server->engine_factory,i);
512 }
513
514 if(engine) {
515 if(engine->id) {
516 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Assign MRCP Engine [%s] [%s]",resource->name.buf,engine->id);
517 }
518 apr_hash_set(profile->engine_table,resource->name.buf,resource->name.length,engine);
519 }
520 else {
521 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No MRCP Engine Available [%s]",resource->name.buf);
522 }
523 }
524
525 return TRUE;
526 }
527
528 /** Register MRCP profile */
mrcp_server_profile_register(mrcp_server_t * server,mrcp_server_profile_t * profile,apr_table_t * plugin_map)529 MRCP_DECLARE(apt_bool_t) mrcp_server_profile_register(
530 mrcp_server_t *server,
531 mrcp_server_profile_t *profile,
532 apr_table_t *plugin_map)
533 {
534 if(!profile || !profile->id) {
535 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile: no name");
536 return FALSE;
537 }
538 if(!profile->resource_factory) {
539 if(!server->resource_factory) {
540 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing resource factory",profile->id);
541 return FALSE;
542 }
543 profile->resource_factory = server->resource_factory;
544 }
545 mrcp_server_engine_table_make(server,profile,plugin_map);
546
547 if(!profile->signaling_agent) {
548 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing signaling agent",profile->id);
549 return FALSE;
550 }
551 if(profile->mrcp_version == MRCP_VERSION_2 &&
552 !profile->connection_agent) {
553 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing connection agent",profile->id);
554 return FALSE;
555 }
556 if(!profile->media_engine) {
557 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing media engine",profile->id);
558 return FALSE;
559 }
560 if(!profile->rtp_termination_factory) {
561 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing RTP factory",profile->id);
562 return FALSE;
563 }
564
565 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Profile [%s]",profile->id);
566 apr_hash_set(server->profile_table,profile->id,APR_HASH_KEY_STRING,profile);
567 return TRUE;
568 }
569
570 /** Get profile by name */
mrcp_server_profile_get(const mrcp_server_t * server,const char * name)571 MRCP_DECLARE(mrcp_server_profile_t*) mrcp_server_profile_get(const mrcp_server_t *server, const char *name)
572 {
573 return apr_hash_get(server->profile_table,name,APR_HASH_KEY_STRING);
574 }
575
576 /** Load MRCP engine */
mrcp_server_engine_load(mrcp_server_t * server,const char * id,const char * path,mrcp_engine_config_t * config)577 MRCP_DECLARE(mrcp_engine_t*) mrcp_server_engine_load(
578 mrcp_server_t *server,
579 const char *id,
580 const char *path,
581 mrcp_engine_config_t *config)
582 {
583 mrcp_engine_t *engine;
584 if(!id || !path || !config) {
585 return FALSE;
586 }
587
588 engine = mrcp_engine_loader_plugin_load(server->engine_loader,id,path,config);
589 if(!engine) {
590 return FALSE;
591 }
592
593 return engine;
594 }
595
mrcp_server_memory_pool_get(const mrcp_server_t * server)596 MRCP_DECLARE(apr_pool_t*) mrcp_server_memory_pool_get(const mrcp_server_t *server)
597 {
598 return server->pool;
599 }
600
mrcp_server_session_add(mrcp_server_session_t * session)601 void mrcp_server_session_add(mrcp_server_session_t *session)
602 {
603 if(session->base.id.buf) {
604 apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Add Session "APT_SID_FMT,MRCP_SESSION_SID(&session->base));
605 apr_hash_set(session->server->session_table,session->base.id.buf,session->base.id.length,session);
606 }
607 }
608
mrcp_server_session_remove(mrcp_server_session_t * session)609 void mrcp_server_session_remove(mrcp_server_session_t *session)
610 {
611 if(session->base.id.buf) {
612 apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Remove Session "APT_SID_FMT,MRCP_SESSION_SID(&session->base));
613 apr_hash_set(session->server->session_table,session->base.id.buf,session->base.id.length,NULL);
614 }
615 }
616
mrcp_server_session_find(mrcp_server_t * server,const apt_str_t * session_id)617 static APR_INLINE mrcp_server_session_t* mrcp_server_session_find(mrcp_server_t *server, const apt_str_t *session_id)
618 {
619 return apr_hash_get(server->session_table,session_id->buf,session_id->length);
620 }
621
mrcp_server_start_request_process(apt_task_t * task)622 static apt_bool_t mrcp_server_start_request_process(apt_task_t *task)
623 {
624 apt_consumer_task_t *consumer_task = apt_task_object_get(task);
625 mrcp_server_t *server = apt_consumer_task_object_get(consumer_task);
626
627 mrcp_engine_t *engine;
628 apr_hash_index_t *it;
629 void *val;
630 it = mrcp_engine_factory_engine_first(server->engine_factory);
631 for(; it; it = apr_hash_next(it)) {
632 apr_hash_this(it,NULL,NULL,&val);
633 engine = val;
634 if(engine) {
635 if(mrcp_engine_virtual_open(engine) == TRUE) {
636 apt_task_start_request_add(task);
637 }
638 }
639 }
640
641 return apt_task_start_request_process(task);
642 }
643
mrcp_server_terminate_request_process(apt_task_t * task)644 static apt_bool_t mrcp_server_terminate_request_process(apt_task_t *task)
645 {
646 apt_consumer_task_t *consumer_task = apt_task_object_get(task);
647 mrcp_server_t *server = apt_consumer_task_object_get(consumer_task);
648
649 mrcp_engine_t *engine;
650 apr_hash_index_t *it;
651 void *val;
652 it = mrcp_engine_factory_engine_first(server->engine_factory);
653 for(; it; it = apr_hash_next(it)) {
654 apr_hash_this(it,NULL,NULL,&val);
655 engine = val;
656 if(engine) {
657 if(mrcp_engine_virtual_close(engine) == TRUE) {
658 apt_task_terminate_request_add(task);
659 }
660 }
661 }
662
663 return apt_task_terminate_request_process(task);
664 }
665
mrcp_server_on_start_complete(apt_task_t * task)666 static void mrcp_server_on_start_complete(apt_task_t *task)
667 {
668 apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,SERVER_TASK_NAME" Started");
669 }
670
mrcp_server_on_terminate_complete(apt_task_t * task)671 static void mrcp_server_on_terminate_complete(apt_task_t *task)
672 {
673 apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,SERVER_TASK_NAME" Terminated");
674 }
675
mrcp_server_msg_process(apt_task_t * task,apt_task_msg_t * msg)676 static apt_bool_t mrcp_server_msg_process(apt_task_t *task, apt_task_msg_t *msg)
677 {
678 switch(msg->type) {
679 case MRCP_SERVER_SIGNALING_TASK_MSG:
680 {
681 mrcp_signaling_message_t **signaling_message = (mrcp_signaling_message_t**) msg->data;
682 mrcp_server_signaling_message_process(*signaling_message);
683 break;
684 }
685 case MRCP_SERVER_CONNECTION_TASK_MSG:
686 {
687 const connection_agent_task_msg_data_t *connection_message = (const connection_agent_task_msg_data_t*)msg->data;
688 switch(msg->sub_type) {
689 case CONNECTION_AGENT_TASK_MSG_ADD_CHANNEL:
690 {
691 mrcp_server_on_channel_modify(connection_message->channel,connection_message->descriptor,connection_message->status);
692 break;
693 }
694 case CONNECTION_AGENT_TASK_MSG_MODIFY_CHANNEL:
695 {
696 mrcp_server_on_channel_modify(connection_message->channel,connection_message->descriptor,connection_message->status);
697 break;
698 }
699 case CONNECTION_AGENT_TASK_MSG_REMOVE_CHANNEL:
700 {
701 mrcp_server_on_channel_remove(connection_message->channel,connection_message->status);
702 break;
703 }
704 case CONNECTION_AGENT_TASK_MSG_RECEIVE_MESSAGE:
705 {
706 mrcp_server_on_channel_message(connection_message->channel, connection_message->message);
707 break;
708 }
709 case CONNECTION_AGENT_TASK_MSG_DISCONNECT:
710 {
711 mrcp_server_on_channel_message(connection_message->channel, connection_message->message);
712 break;
713 }
714 default:
715 break;
716 }
717 break;
718 }
719 case MRCP_SERVER_ENGINE_TASK_MSG:
720 {
721 engine_task_msg_data_t *data = (engine_task_msg_data_t*)msg->data;
722 switch(msg->sub_type) {
723 case ENGINE_TASK_MSG_OPEN_ENGINE:
724 mrcp_engine_on_open(data->engine,data->status);
725 apt_task_start_request_remove(task);
726 break;
727 case ENGINE_TASK_MSG_CLOSE_ENGINE:
728 mrcp_engine_on_close(data->engine);
729 apt_task_terminate_request_remove(task);
730 break;
731 case ENGINE_TASK_MSG_OPEN_CHANNEL:
732 mrcp_server_on_engine_channel_open(data->channel,data->status);
733 break;
734 case ENGINE_TASK_MSG_CLOSE_CHANNEL:
735 mrcp_server_on_engine_channel_close(data->channel);
736 break;
737 case ENGINE_TASK_MSG_MESSAGE:
738 mrcp_server_on_engine_channel_message(data->channel,data->mrcp_message);
739 break;
740 default:
741 break;
742 }
743 break;
744 }
745 case MRCP_SERVER_MEDIA_TASK_MSG:
746 {
747 mpf_message_container_t *mpf_message_container = (mpf_message_container_t*) msg->data;
748 mrcp_server_mpf_message_process(mpf_message_container);
749 break;
750 }
751 default:
752 {
753 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Task Message Received [%d;%d]", msg->type,msg->sub_type);
754 break;
755 }
756 }
757 return TRUE;
758 }
759
mrcp_server_signaling_task_msg_signal(mrcp_signaling_message_type_e type,mrcp_session_t * session,mrcp_session_descriptor_t * descriptor,mrcp_message_t * message)760 static apt_bool_t mrcp_server_signaling_task_msg_signal(mrcp_signaling_message_type_e type, mrcp_session_t *session, mrcp_session_descriptor_t *descriptor, mrcp_message_t *message)
761 {
762 mrcp_signaling_message_t *signaling_message;
763 apt_task_msg_t *task_msg = apt_task_msg_acquire(session->signaling_agent->msg_pool);
764 mrcp_signaling_message_t **slot = ((mrcp_signaling_message_t**)task_msg->data);
765 task_msg->type = MRCP_SERVER_SIGNALING_TASK_MSG;
766 task_msg->sub_type = type;
767
768 signaling_message = apr_palloc(session->pool,sizeof(mrcp_signaling_message_t));
769 signaling_message->type = type;
770 signaling_message->session = (mrcp_server_session_t*)session;
771 signaling_message->descriptor = descriptor;
772 signaling_message->channel = NULL;
773 signaling_message->message = message;
774 *slot = signaling_message;
775
776 return apt_task_msg_parent_signal(session->signaling_agent->task,task_msg);
777 }
778
mrcp_server_connection_task_msg_signal(connection_agent_task_msg_type_e type,mrcp_connection_agent_t * agent,mrcp_control_channel_t * channel,mrcp_control_descriptor_t * descriptor,mrcp_message_t * message,apt_bool_t status)779 static apt_bool_t mrcp_server_connection_task_msg_signal(
780 connection_agent_task_msg_type_e type,
781 mrcp_connection_agent_t *agent,
782 mrcp_control_channel_t *channel,
783 mrcp_control_descriptor_t *descriptor,
784 mrcp_message_t *message,
785 apt_bool_t status)
786 {
787 mrcp_server_t *server = mrcp_server_connection_agent_object_get(agent);
788 apt_task_t *task = apt_consumer_task_base_get(server->task);
789 connection_agent_task_msg_data_t *data;
790 apt_task_msg_t *task_msg = apt_task_msg_acquire(server->connection_msg_pool);
791 task_msg->type = MRCP_SERVER_CONNECTION_TASK_MSG;
792 task_msg->sub_type = type;
793 data = (connection_agent_task_msg_data_t*) task_msg->data;
794 data->channel = channel ? channel->obj : NULL;
795 data->descriptor = descriptor;
796 data->message = message;
797 data->status = status;
798
799 return apt_task_msg_signal(task,task_msg);
800 }
801
mrcp_server_engine_task_msg_signal(engine_task_msg_type_e type,mrcp_engine_t * engine,apt_bool_t status)802 static apt_bool_t mrcp_server_engine_task_msg_signal(
803 engine_task_msg_type_e type,
804 mrcp_engine_t *engine,
805 apt_bool_t status)
806 {
807 mrcp_server_t *server = engine->event_obj;
808 apt_task_t *task = apt_consumer_task_base_get(server->task);
809 engine_task_msg_data_t *data;
810 apt_task_msg_t *task_msg = apt_task_msg_acquire(server->engine_msg_pool);
811 task_msg->type = MRCP_SERVER_ENGINE_TASK_MSG;
812 task_msg->sub_type = type;
813 data = (engine_task_msg_data_t*) task_msg->data;
814 data->engine = engine;
815 data->channel = NULL;
816 data->status = status;
817 data->mrcp_message = NULL;
818
819 return apt_task_msg_signal(task,task_msg);
820 }
821
mrcp_server_channel_task_msg_signal(engine_task_msg_type_e type,mrcp_engine_channel_t * engine_channel,apt_bool_t status,mrcp_message_t * message)822 static apt_bool_t mrcp_server_channel_task_msg_signal(
823 engine_task_msg_type_e type,
824 mrcp_engine_channel_t *engine_channel,
825 apt_bool_t status,
826 mrcp_message_t *message)
827 {
828 mrcp_channel_t *channel = engine_channel->event_obj;
829 mrcp_session_t *session = mrcp_server_channel_session_get(channel);
830 mrcp_server_t *server = session->signaling_agent->parent;
831 apt_task_t *task = apt_consumer_task_base_get(server->task);
832 engine_task_msg_data_t *data;
833 apt_task_msg_t *task_msg = apt_task_msg_acquire(server->engine_msg_pool);
834 task_msg->type = MRCP_SERVER_ENGINE_TASK_MSG;
835 task_msg->sub_type = type;
836 data = (engine_task_msg_data_t*) task_msg->data;
837 data->engine = engine_channel->engine;
838 data->channel = channel;
839 data->status = status;
840 data->mrcp_message = message;
841
842 return apt_task_msg_signal(task,task_msg);
843 }
844
mrcp_server_profile_get_by_agent(mrcp_server_t * server,mrcp_server_session_t * session,const mrcp_sig_agent_t * signaling_agent)845 static mrcp_server_profile_t* mrcp_server_profile_get_by_agent(mrcp_server_t *server, mrcp_server_session_t *session, const mrcp_sig_agent_t *signaling_agent)
846 {
847 mrcp_server_profile_t *profile;
848 apr_hash_index_t *it;
849 void *val;
850 it = apr_hash_first(session->base.pool,server->profile_table);
851 for(; it; it = apr_hash_next(it)) {
852 apr_hash_this(it,NULL,NULL,&val);
853 profile = val;
854 if(profile && profile->signaling_agent == signaling_agent) {
855 return profile;
856 }
857 }
858 return NULL;
859 }
860
mrcp_server_sig_agent_session_create(mrcp_sig_agent_t * signaling_agent)861 static mrcp_session_t* mrcp_server_sig_agent_session_create(mrcp_sig_agent_t *signaling_agent)
862 {
863 mrcp_server_t *server = signaling_agent->parent;
864 mrcp_server_session_t *session = mrcp_server_session_create();
865 session->server = server;
866 session->profile = mrcp_server_profile_get_by_agent(server,session,signaling_agent);
867 if(!session->profile) {
868 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot Find Profile by Agent "APT_NAMESID_FMT,
869 session->base.name,
870 MRCP_SESSION_SID(&session->base));
871 mrcp_session_destroy(&session->base);
872 return NULL;
873 }
874 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create Session "APT_NAMESID_FMT" [%s]",
875 session->base.name,
876 MRCP_SESSION_SID(&session->base),
877 session->profile->id);
878 session->base.signaling_agent = signaling_agent;
879 session->base.request_vtable = &session_request_vtable;
880 return &session->base;
881 }
882
mrcp_server_offer_signal(mrcp_session_t * session,mrcp_session_descriptor_t * descriptor)883 static apt_bool_t mrcp_server_offer_signal(mrcp_session_t *session, mrcp_session_descriptor_t *descriptor)
884 {
885 return mrcp_server_signaling_task_msg_signal(SIGNALING_MESSAGE_OFFER,session,descriptor,NULL);
886 }
887
mrcp_server_terminate_signal(mrcp_session_t * session)888 static apt_bool_t mrcp_server_terminate_signal(mrcp_session_t *session)
889 {
890 return mrcp_server_signaling_task_msg_signal(SIGNALING_MESSAGE_TERMINATE,session,NULL,NULL);
891 }
892
mrcp_server_control_signal(mrcp_session_t * session,mrcp_message_t * message)893 static apt_bool_t mrcp_server_control_signal(mrcp_session_t *session, mrcp_message_t *message)
894 {
895 return mrcp_server_signaling_task_msg_signal(SIGNALING_MESSAGE_CONTROL,session,NULL,message);
896 }
897
mrcp_server_channel_add_signal(mrcp_control_channel_t * channel,mrcp_control_descriptor_t * descriptor,apt_bool_t status)898 static apt_bool_t mrcp_server_channel_add_signal(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor, apt_bool_t status)
899 {
900 mrcp_connection_agent_t *agent = channel->agent;
901 return mrcp_server_connection_task_msg_signal(
902 CONNECTION_AGENT_TASK_MSG_ADD_CHANNEL,
903 agent,
904 channel,
905 descriptor,
906 NULL,
907 status);
908 }
909
mrcp_server_channel_modify_signal(mrcp_control_channel_t * channel,mrcp_control_descriptor_t * descriptor,apt_bool_t status)910 static apt_bool_t mrcp_server_channel_modify_signal(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor, apt_bool_t status)
911 {
912 mrcp_connection_agent_t *agent = channel->agent;
913 return mrcp_server_connection_task_msg_signal(
914 CONNECTION_AGENT_TASK_MSG_MODIFY_CHANNEL,
915 agent,
916 channel,
917 descriptor,
918 NULL,
919 status);
920 }
921
mrcp_server_channel_remove_signal(mrcp_control_channel_t * channel,apt_bool_t status)922 static apt_bool_t mrcp_server_channel_remove_signal(mrcp_control_channel_t *channel, apt_bool_t status)
923 {
924 mrcp_connection_agent_t *agent = channel->agent;
925 return mrcp_server_connection_task_msg_signal(
926 CONNECTION_AGENT_TASK_MSG_REMOVE_CHANNEL,
927 agent,
928 channel,
929 NULL,
930 NULL,
931 status);
932 }
933
mrcp_server_message_signal(mrcp_control_channel_t * channel,mrcp_message_t * message)934 static apt_bool_t mrcp_server_message_signal(mrcp_control_channel_t *channel, mrcp_message_t *message)
935 {
936 mrcp_connection_agent_t *agent = channel->agent;
937 return mrcp_server_connection_task_msg_signal(
938 CONNECTION_AGENT_TASK_MSG_RECEIVE_MESSAGE,
939 agent,
940 channel,
941 NULL,
942 message,
943 TRUE);
944 }
945
mrcp_server_disconnect_signal(mrcp_control_channel_t * channel)946 static apt_bool_t mrcp_server_disconnect_signal(mrcp_control_channel_t *channel)
947 {
948 mrcp_connection_agent_t *agent = channel->agent;
949 return mrcp_server_connection_task_msg_signal(
950 CONNECTION_AGENT_TASK_MSG_DISCONNECT,
951 agent,
952 channel,
953 NULL,
954 NULL,
955 TRUE);
956 }
957
mrcp_server_engine_open_signal(mrcp_engine_t * engine,apt_bool_t status)958 static apt_bool_t mrcp_server_engine_open_signal(mrcp_engine_t *engine, apt_bool_t status)
959 {
960 return mrcp_server_engine_task_msg_signal(
961 ENGINE_TASK_MSG_OPEN_ENGINE,
962 engine,
963 status);
964 }
965
mrcp_server_engine_close_signal(mrcp_engine_t * engine)966 static apt_bool_t mrcp_server_engine_close_signal(mrcp_engine_t *engine)
967 {
968 return mrcp_server_engine_task_msg_signal(
969 ENGINE_TASK_MSG_CLOSE_ENGINE,
970 engine,
971 TRUE);
972 }
973
mrcp_server_channel_open_signal(mrcp_engine_channel_t * channel,apt_bool_t status)974 static apt_bool_t mrcp_server_channel_open_signal(mrcp_engine_channel_t *channel, apt_bool_t status)
975 {
976 return mrcp_server_channel_task_msg_signal(
977 ENGINE_TASK_MSG_OPEN_CHANNEL,
978 channel,
979 status,
980 NULL);
981 }
982
mrcp_server_channel_close_signal(mrcp_engine_channel_t * channel)983 static apt_bool_t mrcp_server_channel_close_signal(mrcp_engine_channel_t *channel)
984 {
985 return mrcp_server_channel_task_msg_signal(
986 ENGINE_TASK_MSG_CLOSE_CHANNEL,
987 channel,
988 TRUE,
989 NULL);
990 }
991
mrcp_server_channel_message_signal(mrcp_engine_channel_t * channel,mrcp_message_t * message)992 static apt_bool_t mrcp_server_channel_message_signal(mrcp_engine_channel_t *channel, mrcp_message_t *message)
993 {
994 return mrcp_server_channel_task_msg_signal(
995 ENGINE_TASK_MSG_MESSAGE,
996 channel,
997 TRUE,
998 message);
999 }
1000