/** Parse MRCP stream */ MRCP_DECLARE(mrcp_stream_result_e) mrcp_parser_run(mrcp_parser_t *parser, apt_text_stream_t *stream) { mrcp_message_t *message = parser->message; if(message && parser->result == MRCP_STREAM_MESSAGE_TRUNCATED) { /* process continuation data */ parser->result = mrcp_message_body_read(message,stream); return parser->result; } /* create new MRCP message */ message = mrcp_message_create(parser->pool); message->channel_id.resource_name = parser->resource_name; parser->message = message; /* store current position to be able to rewind/restore stream if needed */ parser->pos = stream->pos; /* parse start-line and header */ if(mrcp_message_parse(parser->resource_factory,message,stream) == FALSE) { return mrcp_parser_break(parser,stream); } /* parse body */ parser->result = mrcp_message_body_parse(message,stream,message->pool); /* in the worst case message segmentation may occur between <CR> and <LF> of the final empty header */ if(!message->body.length && *(stream->pos-1)== APT_TOKEN_CR) { /* if this is the case be prepared to skip <LF> */ parser->skip_lf = TRUE; } return parser->result; }
/** Create MRCP request message */ MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(mrcp_resource_id resource_id, mrcp_method_id method_id, apr_pool_t *pool) { mrcp_message_t *request_message = mrcp_message_create(pool); request_message->start_line.message_type = MRCP_MESSAGE_TYPE_REQUEST; request_message->start_line.method_id = method_id; request_message->channel_id.resource_id = resource_id; return request_message; }
/** Create MRCP event message */ MRCP_DECLARE(mrcp_message_t*) mrcp_event_create(const mrcp_message_t *request_message, mrcp_method_id event_id, apr_pool_t *pool) { mrcp_message_t *event_message = mrcp_message_create(pool); if(request_message) { mrcp_message_init_by_request(event_message,request_message); } event_message->start_line.message_type = MRCP_MESSAGE_TYPE_EVENT; event_message->start_line.method_id = event_id; return event_message; }
/** Create MRCP response message */ MRCP_DECLARE(mrcp_message_t*) mrcp_response_create(const mrcp_message_t *request_message, apr_pool_t *pool) { mrcp_message_t *response_message = mrcp_message_create(pool); if(request_message) { mrcp_message_init_by_request(response_message,request_message); } response_message->start_line.message_type = MRCP_MESSAGE_TYPE_RESPONSE; response_message->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE; response_message->start_line.status_code = MRCP_STATUS_CODE_SUCCESS; return response_message; }
/** Create message and read start line */ static apt_bool_t mrcp_parser_on_start(apt_message_parser_t *parser, apt_message_context_t *context, apt_text_stream_t *stream, apr_pool_t *pool) { mrcp_message_t *mrcp_message; apt_str_t start_line; /* read start line */ if(apt_text_line_read(stream,&start_line) == FALSE) { return FALSE; } /* create new MRCP message */ mrcp_message = mrcp_message_create(pool); /* parse start-line */ if(mrcp_start_line_parse(&mrcp_message->start_line,&start_line,mrcp_message->pool) == FALSE) { return FALSE; } if(mrcp_message->start_line.version == MRCP_VERSION_1) { mrcp_parser_t *mrcp_parser = apt_message_parser_object_get(parser); if(!mrcp_parser->resource) { return FALSE; } apt_string_copy( &mrcp_message->channel_id.resource_name, &mrcp_parser->resource->name, pool); if(mrcp_message_resource_set(mrcp_message,mrcp_parser->resource) == FALSE) { return FALSE; } } context->message = mrcp_message; context->header = &mrcp_message->header.header_section; context->body = &mrcp_message->body; return TRUE; }
static apt_bool_t mrcp_client_agent_messsage_receive(mrcp_connection_agent_t *agent, mrcp_connection_t *connection) { char buffer[MRCP_MESSAGE_MAX_SIZE]; apt_bool_t more_messages_on_buffer = FALSE; apr_status_t status; apt_text_stream_t text_stream; mrcp_message_t *message; if(!connection || !connection->sock) { return FALSE; } text_stream.text.buf = buffer; text_stream.text.length = sizeof(buffer)-1; status = apr_socket_recv(connection->sock, text_stream.text.buf, &text_stream.text.length); if(status == APR_EOF || text_stream.text.length == 0) { apt_log(APT_PRIO_NOTICE,"TCP/MRCPv2 Connection Disconnected"); apr_pollset_remove(agent->pollset,&connection->sock_pfd); apr_socket_close(connection->sock); connection->sock = NULL; // agent->vtable->on_disconnect(agent,connection); return TRUE; } text_stream.text.buf[text_stream.text.length] = '\0'; text_stream.pos = text_stream.text.buf; apt_log(APT_PRIO_INFO,"Receive MRCPv2 Message size=%lu\n%s",text_stream.text.length,text_stream.text.buf); if(!connection->access_count) { return FALSE; } do { message = mrcp_message_create(connection->pool); if(mrcp_message_parse(agent->resource_factory,message,&text_stream) == TRUE) { mrcp_control_channel_t *channel; apt_str_t identifier; apt_id_resource_generate(&message->channel_id.session_id,&message->channel_id.resource_name,'@',&identifier,connection->pool); channel = mrcp_connection_channel_find(connection,&identifier); if(channel) { mrcp_connection_message_receive(agent->vtable,channel,message); } else { apt_log(APT_PRIO_WARNING,"Failed to Find Channel <%s@%s>", message->channel_id.session_id.buf, message->channel_id.resource_name.buf); } } else { apt_log(APT_PRIO_WARNING,"Failed to Parse MRCPv2 Message"); if(message->start_line.version == MRCP_VERSION_2) { /* assume that at least message length field is valid */ if(message->start_line.length <= text_stream.text.length) { /* skip to the end of the message */ text_stream.pos = text_stream.text.buf + message->start_line.length; } else { /* skip to the end of the buffer (support incomplete) */ text_stream.pos = text_stream.text.buf + text_stream.text.length; } } } more_messages_on_buffer = FALSE; if(text_stream.text.length > (apr_size_t)(text_stream.pos - text_stream.text.buf)) { /* there are more MRCPv2 messages to signal */ more_messages_on_buffer = TRUE; text_stream.text.length -= text_stream.pos - text_stream.text.buf; text_stream.text.buf = text_stream.pos; apt_log(APT_PRIO_DEBUG,"Saving Remaining Buffer for Next Message"); } } while(more_messages_on_buffer); return TRUE; }
static apt_bool_t mrcp_server_agent_messsage_receive(mrcp_connection_agent_t *agent, mrcp_connection_t *connection) { char buffer[MRCP_MESSAGE_MAX_SIZE]; apt_bool_t more_messages_on_buffer = FALSE; apr_status_t status; apt_text_stream_t text_stream; mrcp_message_t *message; if(!connection || !connection->sock) { return FALSE; } text_stream.text.buf = buffer; text_stream.text.length = sizeof(buffer)-1; status = apr_socket_recv(connection->sock, text_stream.text.buf, &text_stream.text.length); if(status == APR_EOF || text_stream.text.length == 0) { return mrcp_server_agent_connection_close(agent,connection); } text_stream.text.buf[text_stream.text.length] = '\0'; text_stream.pos = text_stream.text.buf; apt_log(APT_PRIO_INFO,"Receive MRCPv2 Message size=%lu\n%s",text_stream.text.length,text_stream.text.buf); do { message = mrcp_message_create(connection->pool); if(mrcp_message_parse(agent->resource_factory,message,&text_stream) == TRUE) { mrcp_control_channel_t *channel = mrcp_connection_channel_associate(agent,connection,message); if(channel) { mrcp_connection_message_receive(agent->vtable,channel,message); } else { apt_log(APT_PRIO_WARNING,"Failed to Find Channel <%s@%s>", message->channel_id.session_id.buf, message->channel_id.resource_name.buf); } } else { mrcp_message_t *response; apt_log(APT_PRIO_WARNING,"Failed to Parse MRCPv2 Message"); if(message->start_line.version == MRCP_VERSION_2) { /* assume that at least message length field is valid */ if(message->start_line.length <= text_stream.text.length) { /* skip to the end of the message */ text_stream.pos = text_stream.text.buf + message->start_line.length; } else { /* skip to the end of the buffer (support incomplete) */ text_stream.pos = text_stream.text.buf + text_stream.text.length; } } response = mrcp_response_create(message,message->pool); response->start_line.status_code = MRCP_STATUS_CODE_UNRECOGNIZED_MESSAGE; if(mrcp_server_agent_messsage_send(agent,connection,response) == FALSE) { apt_log(APT_PRIO_WARNING,"Failed to Send MRCPv2 Response"); } } more_messages_on_buffer = FALSE; if(text_stream.text.length > (apr_size_t)(text_stream.pos - text_stream.text.buf)) { /* there are more MRCPv2 messages to signal */ more_messages_on_buffer = TRUE; text_stream.text.length -= text_stream.pos - text_stream.text.buf; text_stream.text.buf = text_stream.pos; apt_log(APT_PRIO_DEBUG,"Saving Remaining Buffer for Next Message"); } } while(more_messages_on_buffer); return TRUE; }