/* * OpenMRCP - Open Source Media Resource Control Protocol Stack * Copyright (C) 2007, Cepstral LLC * * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * Author(s): * Arsen Chaloyan * * Contributor(s): * */ #include #include #include "mrcp_server_signaling_agent.h" #include "mrcp_server_proto_agent.h" #include "apt_task.h" #include "mrcp_parser.h" #include "rtsp_engine.h" typedef struct mrcp_server_rtsp_agent_t mrcp_server_rtsp_agent_t; struct mrcp_server_rtsp_agent_t { mrcp_signaling_agent_t *signaling_agent; mrcp_proto_agent_t proto_agent; unsigned char create_count; unsigned char open_count; rtsp_engine_event_handler_t handler; rtsp_engine_t *engine; apt_task_msg_pool_t *msg_pool; apr_pool_t *pool; }; typedef struct mrcp_server_rtsp_session_t mrcp_server_rtsp_session_t; struct mrcp_server_rtsp_session_t { mrcp_signaling_channel_t *channel; mrcp_connection_t *proto_connection; rtsp_session_t *session; rtsp_message_t *request; su_home_t *home; }; typedef enum { MRCP_RTSP_EVENT_AGENT_STARTED, MRCP_RTSP_EVENT_AGENT_TERMINATED, MRCP_RTSP_EVENT_SESSION_CREATED, MRCP_RTSP_EVENT_SESSION_TERMINATED, MRCP_RTSP_EVENT_REQUEST_RECEIVED, MRCP_RTSP_EVENT_RESPONSE_RECEIVED } mrcp_rtsp_event_id; typedef struct mrcp_rtsp_event_t mrcp_rtsp_event_t; struct mrcp_rtsp_event_t { mrcp_rtsp_event_id event_id; mrcp_server_rtsp_agent_t *rtsp_agent; rtsp_session_t *session; rtsp_message_t *request; rtsp_message_t *response; }; static mrcp_status_t mrcp_rtsp_agent_destroy(mrcp_module_t *module); static mrcp_module_state_t mrcp_rtsp_agent_open(mrcp_module_t *module); static mrcp_module_state_t mrcp_rtsp_agent_close(mrcp_module_t *module); static mrcp_status_t mrcp_rtsp_agent_signal_handler(mrcp_module_t *module, apt_task_msg_t *msg); static const mrcp_module_method_set_t module_method_set = { mrcp_rtsp_agent_destroy, mrcp_rtsp_agent_open, mrcp_rtsp_agent_close, mrcp_rtsp_agent_signal_handler }; static mrcp_status_t mrcp_rtsp_session_answer(mrcp_signaling_channel_t *channel); static mrcp_status_t mrcp_rtsp_session_destroy(mrcp_signaling_channel_t *channel); static const mrcp_signaling_channel_method_set_t signaling_channel_method_set = { NULL, /*offer*/ mrcp_rtsp_session_answer, NULL, /*terminate*/ mrcp_rtsp_session_destroy }; static mrcp_connection_t* mrcp_rtsp_proto_connection_add(mrcp_proto_agent_t *proto_agent, mrcp_signaling_channel_t *channel, const char *remote_ip); static const mrcp_proto_agent_method_set_t proto_agent_method_set = { mrcp_rtsp_proto_connection_add, }; static mrcp_status_t mrcp_rtsp_proto_connection_remove(mrcp_connection_t *proto_connection); static mrcp_status_t mrcp_rtsp_message_send(mrcp_connection_t *proto_connection, mrcp_message_t *mrcp_message); static const mrcp_connection_method_set_t connection_method_set = { mrcp_rtsp_proto_connection_remove, mrcp_rtsp_message_send }; mrcp_status_t mrcp_descriptor_generate_by_rtsp_request(mrcp_descriptor_t *descriptor, rtsp_message_t *request, apr_pool_t *pool, su_home_t *home); size_t rtsp_response_generate_by_mrcp_descriptor(rtsp_message_t *message, mrcp_descriptor_t *descriptor, const char *resource_name); size_t rtsp_resource_discover_sdp_generate(rtsp_message_t *message, mrcp_descriptor_t *descriptor); static APR_INLINE mrcp_server_rtsp_agent_t* mrcp_rtsp_agent_get(mrcp_module_t *module) { return ((mrcp_signaling_agent_t*)module)->object; } static mrcp_status_t mrcp_rtsp_session_answer(mrcp_signaling_channel_t *channel) { mrcp_server_rtsp_session_t *rtsp_session = channel->object; rtsp_message_t *response; if(!rtsp_session || !rtsp_session->request) { return MRCP_STATUS_FAILURE; } response = rtsp_response_create(rtsp_session->request,RTSP_STATUS_CODE_OK,RTSP_REASON_PHRASE_OK,channel->pool); if(rtsp_session->request->start_line.common.request_line.method_id == RTSP_METHOD_SETUP) { if(rtsp_response_generate_by_mrcp_descriptor(response,&channel->local_descriptor, rtsp_session->request->start_line.common.request_line.resource_name) > 0) { apt_log(APT_PRIO_INFO,"Local SDP\n[%s]\n", response->body); } } rtsp_engine_message_send(rtsp_session->session,response); if(rtsp_session->request->start_line.common.request_line.method_id == RTSP_METHOD_TEARDOWN || (rtsp_session->request->start_line.common.request_line.method_id == RTSP_METHOD_SETUP && response->start_line.common.status_line.status_code != RTSP_STATUS_CODE_OK) ) { if(!mrcp_enabled_control_media_get(&rtsp_session->channel->local_descriptor)) { rtsp_engine_session_terminate(rtsp_session->session); } } return MRCP_STATUS_SUCCESS; } static mrcp_status_t mrcp_rtsp_session_destroy(mrcp_signaling_channel_t *channel) { mrcp_server_rtsp_session_t *rtsp_session = channel->object; if(!rtsp_session || !rtsp_session->request) { return MRCP_STATUS_FAILURE; } if(rtsp_session->home) { su_home_unref(rtsp_session->home); rtsp_session->home = NULL; } channel->object = NULL; rtsp_engine_session_destroy(rtsp_session->session); rtsp_session->session = NULL; return MRCP_STATUS_SUCCESS; } static mrcp_connection_t* mrcp_rtsp_proto_connection_add(mrcp_proto_agent_t *proto_agent, mrcp_signaling_channel_t *channel, const char *remote_ip) { mrcp_server_rtsp_session_t* rtsp_session = channel->object; if(!rtsp_session) { return NULL; } if(!rtsp_session->proto_connection) { rtsp_session->proto_connection = apr_palloc(rtsp_session->channel->pool,sizeof(mrcp_connection_t)); rtsp_session->proto_connection->agent = proto_agent; rtsp_session->proto_connection->method_set = &connection_method_set; rtsp_session->proto_connection->event_set = proto_agent->connection_event_set; rtsp_session->proto_connection->object = rtsp_session; } return rtsp_session->proto_connection; } static mrcp_status_t mrcp_rtsp_proto_connection_remove(mrcp_connection_t *proto_connection) { /* nothing to do, no actual connection exists */ return MRCP_STATUS_SUCCESS; } static mrcp_status_t mrcp_rtsp_message_send(mrcp_connection_t *proto_connection, mrcp_message_t *mrcp_message) { char buffer[MRCP_MESSAGE_MAX_SIZE]; apt_text_stream_t text_stream; size_t size = sizeof(buffer)-1; mrcp_server_rtsp_session_t *rtsp_session = proto_connection->object; mrcp_server_rtsp_agent_t *rtsp_agent = proto_connection->agent->object; rtsp_message_t *rtsp_message = NULL; if(!rtsp_agent || !rtsp_session || !rtsp_session->session) { return MRCP_STATUS_FAILURE; } text_stream.buffer = buffer; text_stream.size = size; text_stream.pos = text_stream.buffer; mrcp_message->start_line.version = MRCP_VERSION_1; if(mrcp_message_generate(proto_connection->agent->resource_container,mrcp_message,&text_stream) != MRCP_STATUS_SUCCESS) { apt_log(APT_PRIO_WARNING,"Failed to Generate MRCPv1 Message\n"); return MRCP_STATUS_FAILURE; } *text_stream.pos = '\0'; apt_log(APT_PRIO_DEBUG,"Send MRCPv1 Message size=%lu\n%s\n",text_stream.size,text_stream.buffer); if(mrcp_message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) { /* send rtsp response (ok) */ rtsp_message = rtsp_response_create(rtsp_session->request,RTSP_STATUS_CODE_OK,RTSP_REASON_PHRASE_OK,rtsp_session->channel->pool); } else if(mrcp_message->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) { /* send rtsp announce */ rtsp_message = rtsp_request_create(rtsp_session->channel->pool); rtsp_message->start_line.common.request_line.method_id = RTSP_METHOD_ANNOUNCE; if(rtsp_session->request) { rtsp_message->start_line.common.request_line.url = rtsp_session->request->start_line.common.request_line.url; } } if(!rtsp_message) { return MRCP_STATUS_FAILURE; } rtsp_message->body = apr_pstrdup(rtsp_message->pool,text_stream.buffer); rtsp_message->header.content_type = RTSP_CONTENT_TYPE_MRCP; rtsp_header_property_add(&rtsp_message->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE); rtsp_message->header.content_length = text_stream.size; rtsp_header_property_add(&rtsp_message->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH); return rtsp_engine_message_send(rtsp_session->session,rtsp_message); } static mrcp_status_t mrcp_rtsp_process_session_create(mrcp_server_rtsp_agent_t *rtsp_agent, rtsp_session_t *session) { mrcp_server_rtsp_session_t *rtsp_session; apr_pool_t *pool; const mrcp_signaling_agent_event_set_t *event_set = rtsp_agent->signaling_agent->agent_event_set; mrcp_session_id *session_id = rtsp_engine_session_id_get(session); mrcp_session_t *mrcp_session = event_set->on_session_create(rtsp_agent->signaling_agent,session_id,&pool); if(!mrcp_session || !pool) { return MRCP_STATUS_FAILURE; } rtsp_session = apr_palloc(pool,sizeof(*rtsp_session)); rtsp_session->home = su_home_new(sizeof(*rtsp_session->home)); rtsp_session->proto_connection = NULL; rtsp_session->session = session; rtsp_engine_session_object_set(session,rtsp_session); rtsp_session->request = NULL; rtsp_session->channel = mrcp_server_signaling_channel_create( rtsp_agent->signaling_agent, &signaling_channel_method_set, rtsp_session, pool); event_set->on_channel_attach(mrcp_session,rtsp_session->channel); return MRCP_STATUS_SUCCESS; } static mrcp_status_t mrcp_rtsp_process_session_terminate(mrcp_server_rtsp_agent_t *rtsp_agent, rtsp_session_t *session) { mrcp_server_rtsp_session_t *rtsp_session = rtsp_engine_session_object_get(session); if(rtsp_session) { rtsp_session->channel->event_set->on_terminate(rtsp_session->channel); } return MRCP_STATUS_SUCCESS; } static mrcp_status_t mrcp_rtsp_process_setup(mrcp_server_rtsp_agent_t *agent, rtsp_session_t *session, rtsp_message_t *message) { mrcp_server_rtsp_session_t *rtsp_session = rtsp_engine_session_object_get(session); apt_log(APT_PRIO_NOTICE,"RTSP Setup\n"); if(!rtsp_session || !rtsp_session->channel) { return MRCP_STATUS_FAILURE; } rtsp_session->request = message; if(rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE) == MRCP_STATUS_SUCCESS) { if(message->header.content_type == RTSP_CONTENT_TYPE_SDP && message->body) { apt_log(APT_PRIO_INFO,"Remote SDP\n[%s]\n", message->body); mrcp_descriptor_generate_by_rtsp_request( &rtsp_session->channel->remote_descriptor, message, rtsp_session->channel->pool, rtsp_session->home); } } return rtsp_session->channel->event_set->on_offer(rtsp_session->channel); } static mrcp_status_t mrcp_rtsp_process_teardown(mrcp_server_rtsp_agent_t *agent, rtsp_session_t *session, rtsp_message_t *message) { mrcp_server_rtsp_session_t *rtsp_session = rtsp_engine_session_object_get(session); mrcp_media_control_t *control_media; apt_log(APT_PRIO_NOTICE,"RTSP Teardown <%s>\n",message->header.session_id); if(!rtsp_session) { apt_log(APT_PRIO_NOTICE,"RTSP Teardown <%s>: no such session\n",message->header.session_id); return MRCP_STATUS_FAILURE; } rtsp_session->request = message; control_media = mrcp_control_media_get(&rtsp_session->channel->remote_descriptor,message->start_line.common.request_line.resource_name); if(!control_media) { apt_log(APT_PRIO_NOTICE,"RTSP Teardown <%s@%s>: no such resource\n",message->header.session_id,message->start_line.common.request_line.resource_name); return MRCP_STATUS_FAILURE; } control_media->base.state = MRCP_MEDIA_DISABLED; return rtsp_session->channel->event_set->on_offer(rtsp_session->channel); } static mrcp_status_t mrcp_rtsp_process_announce(mrcp_server_rtsp_agent_t *agent, rtsp_session_t *session, rtsp_message_t *message) { mrcp_server_rtsp_session_t *rtsp_session = rtsp_engine_session_object_get(session); const char *resource_name = message->start_line.common.request_line.resource_name; mrcp_status_t status = MRCP_STATUS_SUCCESS; apt_log(APT_PRIO_NOTICE,"RTSP Announce\n"); if(rtsp_session && resource_name && rtsp_session->proto_connection && rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE) == MRCP_STATUS_SUCCESS && message->header.content_type == RTSP_CONTENT_TYPE_MRCP && rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH) == MRCP_STATUS_SUCCESS && message->header.content_length > 0) { apt_text_stream_t text_stream; mrcp_message_t *mrcp_message; rtsp_session->request = message; text_stream.buffer = message->body; text_stream.size = message->header.content_length; text_stream.pos = text_stream.buffer; apt_log(APT_PRIO_DEBUG,"Receive MRCPv1 Message size=%lu\n%s\n",text_stream.size,text_stream.buffer); mrcp_message = mrcp_message_create(rtsp_session->channel->pool); mrcp_message->channel_id.session_id.hex_str = message->header.session_id; mrcp_message->channel_id.session_id.length = strlen(message->header.session_id); mrcp_message->channel_id.resource_name = resource_name; if(mrcp_message_parse(agent->proto_agent.resource_container,mrcp_message,&text_stream) == MRCP_STATUS_SUCCESS) { rtsp_session->proto_connection->event_set->on_receive(rtsp_session->proto_connection,mrcp_message); } else { /* error response */ apt_log(APT_PRIO_WARNING,"Failed to Parse MRCPv1 Message\n"); status = MRCP_STATUS_FAILURE; } } else { /* error response */ status = MRCP_STATUS_FAILURE; } return status; } static mrcp_status_t mrcp_rtsp_process_describe(mrcp_server_rtsp_agent_t *agent, rtsp_session_t *session, rtsp_message_t *message) { rtsp_message_t *response; apt_log(APT_PRIO_NOTICE,"RTSP Describe\n"); response = rtsp_response_create(message,RTSP_STATUS_CODE_OK,RTSP_REASON_PHRASE_OK,message->pool); if(rtsp_resource_discover_sdp_generate(response,&agent->signaling_agent->capabilities) > 0) { apt_log(APT_PRIO_INFO,"Local SDP\n[%s]\n", message->body); } return rtsp_engine_message_send(session,response); } static mrcp_status_t mrcp_rtsp_process_request(mrcp_server_rtsp_agent_t *rtsp_agent, rtsp_session_t *session, rtsp_message_t *message) { if(!rtsp_agent) { return MRCP_STATUS_FAILURE; } if(message->start_line.message_type == RTSP_MESSAGE_TYPE_REQUEST) { mrcp_status_t status = MRCP_STATUS_SUCCESS; apt_log(APT_PRIO_DEBUG,"Process RTSP Request [%s]\n",message->start_line.common.request_line.method_name); switch(message->start_line.common.request_line.method_id) { case RTSP_METHOD_SETUP: status = mrcp_rtsp_process_setup(rtsp_agent,session,message); break; case RTSP_METHOD_ANNOUNCE: status = mrcp_rtsp_process_announce(rtsp_agent,session,message); break; case RTSP_METHOD_TEARDOWN: status = mrcp_rtsp_process_teardown(rtsp_agent,session,message); break; case RTSP_METHOD_DESCRIBE: status = mrcp_rtsp_process_describe(rtsp_agent,session,message); break; default: { /* not supported message */ rtsp_message_t *response = rtsp_response_create(message, RTSP_STATUS_CODE_METHOD_NOT_ALLOWED,RTSP_REASON_PHRASE_METHOD_NOT_ALLOWED,message->pool); rtsp_engine_message_send(session,response); } } if(status == MRCP_STATUS_FAILURE) { rtsp_message_t *response = rtsp_response_create(message, RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR,RTSP_REASON_PHRASE_INTERNAL_SERVER_ERROR,message->pool); rtsp_engine_message_send(session,response); } } return MRCP_STATUS_SUCCESS; } static mrcp_status_t mrcp_rtsp_process_response(mrcp_server_rtsp_agent_t *rtsp_agent, rtsp_session_t *session, rtsp_message_t *response, rtsp_message_t *request) { if(response->start_line.message_type == RTSP_MESSAGE_TYPE_RESPONSE) { apt_log(APT_PRIO_DEBUG,"Process RTSP Response\n"); } return MRCP_STATUS_SUCCESS; } static mrcp_status_t mrcp_rtsp_agent_signal_handler(mrcp_module_t *module, apt_task_msg_t *msg) { mrcp_server_rtsp_agent_t *rtsp_agent = mrcp_rtsp_agent_get(module); mrcp_rtsp_event_t *rtsp_event = (mrcp_rtsp_event_t*)msg->data; if(!rtsp_event) { return MRCP_STATUS_FAILURE; } switch(rtsp_event->event_id) { case MRCP_RTSP_EVENT_AGENT_STARTED: break; case MRCP_RTSP_EVENT_AGENT_TERMINATED: if(module->event_set->on_close) { module->event_set->on_close(module); } break; case MRCP_RTSP_EVENT_SESSION_CREATED: mrcp_rtsp_process_session_create(rtsp_agent,rtsp_event->session); break; case MRCP_RTSP_EVENT_SESSION_TERMINATED: mrcp_rtsp_process_session_terminate(rtsp_agent,rtsp_event->session); break; case MRCP_RTSP_EVENT_REQUEST_RECEIVED: mrcp_rtsp_process_request(rtsp_agent,rtsp_event->session,rtsp_event->request); break; case MRCP_RTSP_EVENT_RESPONSE_RECEIVED: mrcp_rtsp_process_response(rtsp_agent,rtsp_event->session,rtsp_event->response,rtsp_event->request); break; } return MRCP_STATUS_SUCCESS; } static mrcp_status_t mrcp_rtsp_task_msg_signal(mrcp_server_rtsp_agent_t *rtsp_agent, mrcp_rtsp_event_id event_id, rtsp_session_t *session, rtsp_message_t *request, rtsp_message_t *response) { apt_task_msg_t *task_msg; if(!rtsp_agent || !session) { return MRCP_STATUS_FAILURE; } task_msg = apt_task_msg_acquire(rtsp_agent->msg_pool); if(task_msg) { mrcp_rtsp_event_t *rtsp_event = (mrcp_rtsp_event_t*)task_msg->data; rtsp_event->event_id = event_id; rtsp_event->rtsp_agent = rtsp_agent; rtsp_event->session = session; rtsp_event->request = request; rtsp_event->response = response; task_msg->msg_pool = rtsp_agent->msg_pool; rtsp_agent->signaling_agent->module.signal( &rtsp_agent->signaling_agent->module, task_msg); } return MRCP_STATUS_SUCCESS; } static apt_bool_t mrcp_rtsp_on_session_create(rtsp_engine_event_handler_t *handler, rtsp_session_t *session) { return mrcp_rtsp_task_msg_signal(handler->object,MRCP_RTSP_EVENT_SESSION_CREATED,session,NULL,NULL); } static apt_bool_t mrcp_rtsp_on_session_terminate(rtsp_engine_event_handler_t *handler, rtsp_session_t *session) { return mrcp_rtsp_task_msg_signal(handler->object,MRCP_RTSP_EVENT_SESSION_TERMINATED,session,NULL,NULL); } static apt_bool_t mrcp_rtsp_on_request_receive(rtsp_engine_event_handler_t *handler, rtsp_session_t *session, rtsp_message_t *request) { return mrcp_rtsp_task_msg_signal(handler->object,MRCP_RTSP_EVENT_REQUEST_RECEIVED,session,request,NULL); } static apt_bool_t mrcp_rtsp_on_response_receive(rtsp_engine_event_handler_t *handler, rtsp_session_t *session, rtsp_message_t *response, rtsp_message_t *request) { return mrcp_rtsp_task_msg_signal(handler->object,MRCP_RTSP_EVENT_RESPONSE_RECEIVED,session,request,response); } static mrcp_module_state_t mrcp_rtsp_agent_open(mrcp_module_t *module) { mrcp_server_rtsp_agent_t *rtsp_agent = mrcp_rtsp_agent_get(module); if(rtsp_agent->open_count++ != 0) { return MODULE_STATE_OPENED; } apt_log(APT_PRIO_INFO,"Open RTSP Agent\n"); rtsp_agent->handler.object = rtsp_agent; rtsp_agent->handler.on_session_create = mrcp_rtsp_on_session_create; rtsp_agent->handler.on_session_terminate = mrcp_rtsp_on_session_terminate; rtsp_agent->handler.on_request_receive = mrcp_rtsp_on_request_receive; rtsp_agent->handler.on_response_receive = mrcp_rtsp_on_response_receive; rtsp_agent->engine = rtsp_server_engine_start(&rtsp_agent->handler, rtsp_agent->signaling_agent->capabilities.ip, rtsp_agent->signaling_agent->sip_port, rtsp_agent->signaling_agent->resource_location); return MODULE_STATE_OPEN_INPROGRESS; } static mrcp_module_state_t mrcp_rtsp_agent_close(mrcp_module_t *module) { mrcp_server_rtsp_agent_t *rtsp_agent = mrcp_rtsp_agent_get(module); if(--rtsp_agent->open_count > 0) { return MODULE_STATE_CLOSED; } apt_log(APT_PRIO_INFO,"Close RTSP Agent\n"); rtsp_engine_shutdown(rtsp_agent->engine); return MODULE_STATE_CLOSED; } static void mrcp_rtsp_agent_config(mrcp_server_rtsp_agent_t *rtsp_agent, const char *ip, unsigned short rtsp_port, const char *resource_location) { if(ip) { rtsp_agent->signaling_agent->capabilities.ip = apr_pstrdup(rtsp_agent->pool,ip); } rtsp_agent->signaling_agent->mrcp_port = 0; rtsp_agent->signaling_agent->sip_port = rtsp_port; if(resource_location) { rtsp_agent->signaling_agent->resource_location = apr_pstrdup(rtsp_agent->pool,resource_location); } } static mrcp_status_t mrcp_rtsp_agent_destroy(mrcp_module_t *module) { mrcp_server_rtsp_agent_t *rtsp_agent = mrcp_rtsp_agent_get(module); if(--rtsp_agent->create_count > 0) { return MRCP_STATUS_SUCCESS; } apt_log(APT_PRIO_NOTICE,"Destroy RTSP Agent\n"); apt_task_msg_pool_destroy(rtsp_agent->msg_pool); rtsp_agent->pool = NULL; return MRCP_STATUS_SUCCESS; } mrcp_signaling_agent_t* mrcp_server_rtsp_agent_create(const char *ip, unsigned short rtsp_port, const char *resource_location, apr_pool_t *pool) { mrcp_server_rtsp_agent_t *rtsp_agent = apr_palloc(pool,sizeof(mrcp_server_rtsp_agent_t)); mrcp_signaling_agent_t *agent = mrcp_server_signaling_agent_create(&module_method_set,rtsp_agent,pool); apt_log(APT_PRIO_NOTICE,"Create RTSP Agent %s:%hu\n",ip,rtsp_port); rtsp_agent->pool = pool; rtsp_agent->signaling_agent = agent; rtsp_agent->engine = NULL; mrcp_rtsp_agent_config(rtsp_agent,ip,rtsp_port,resource_location); rtsp_agent->create_count = 1; rtsp_agent->open_count = 0; rtsp_agent->msg_pool = apt_task_msg_pool_create_waitable_static(sizeof(mrcp_rtsp_event_t),pool); return agent; } mrcp_proto_agent_t* mrcp_server_rtsp_proto_agent_create(mrcp_signaling_agent_t *signaling_agent) { mrcp_server_rtsp_agent_t *rtsp_agent; if(!signaling_agent || !signaling_agent->object) { return NULL; } rtsp_agent = signaling_agent->object; rtsp_agent->proto_agent.object = rtsp_agent; rtsp_agent->proto_agent.agent_method_set = &proto_agent_method_set; mrcp_module_init(&rtsp_agent->proto_agent.module,&module_method_set); rtsp_agent->create_count++; return &rtsp_agent->proto_agent; }