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