/** Parse MRCP speech-length value */ static apt_bool_t mrcp_speech_length_value_parse(mrcp_speech_length_value_t *speech_length, const apt_str_t *value, apr_pool_t *pool) { if(!value->length) { return FALSE; } switch(*value->buf) { case '+': speech_length->type = SPEECH_LENGTH_TYPE_NUMERIC_POSITIVE; break; case '-': speech_length->type = SPEECH_LENGTH_TYPE_NUMERIC_NEGATIVE; break; default : speech_length->type = SPEECH_LENGTH_TYPE_TEXT; } if(speech_length->type == SPEECH_LENGTH_TYPE_TEXT) { apt_string_copy(&speech_length->value.tag,value,pool); } else { mrcp_numeric_speech_length_t *numeric = &speech_length->value.numeric; apt_str_t str; apt_text_stream_t stream; stream.text = *value; apt_text_stream_reset(&stream); stream.pos++; if(apt_text_field_read(&stream,APT_TOKEN_SP,TRUE,&str) == FALSE) { return FALSE; } numeric->length = apt_size_value_parse(&str); if(apt_text_field_read(&stream,APT_TOKEN_SP,TRUE,&str) == FALSE) { return FALSE; } numeric->unit = apt_string_table_value_parse(speech_unit_string_table,SPEECH_UNIT_COUNT,&str); } return TRUE; }
static apt_bool_t mrcp_server_agent_messsage_receive(mrcp_connection_agent_t *agent, mrcp_connection_t *connection) { apr_status_t status; apr_size_t offset; apr_size_t length; apt_text_stream_t *stream; if(!connection || !connection->sock) { return FALSE; } stream = &connection->rx_stream; /* init length of the stream */ stream->text.length = sizeof(connection->rx_buffer)-1; /* calculate offset remaining from the previous receive / if any */ offset = stream->pos - stream->text.buf; /* calculate available length */ length = stream->text.length - offset; status = apr_socket_recv(connection->sock,stream->pos,&length); if(status == APR_EOF || length == 0) { return mrcp_server_agent_connection_close(agent,connection); } /* calculate actual length of the stream */ stream->text.length = offset + length; stream->pos[length] = '\0'; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive MRCPv2 Stream %s [%lu bytes]\n%s", connection->id, length, stream->pos); /* reset pos */ apt_text_stream_reset(stream); /* walk through the stream parsing MRCP messages */ return mrcp_stream_walk(connection->parser,stream,mrcp_server_message_handler,connection); }
/* Receive MRCP message through TCP/MRCPv2 connection */ static apt_bool_t mrcp_client_poller_signal_process(void *obj, const apr_pollfd_t *descriptor) { mrcp_connection_agent_t *agent = obj; mrcp_connection_t *connection = descriptor->client_data; apr_status_t status; apr_size_t offset; apr_size_t length; apt_text_stream_t *stream; mrcp_message_t *message; apt_message_status_e msg_status; if(!connection || !connection->sock) { return FALSE; } stream = &connection->rx_stream; /* calculate offset remaining from the previous receive / if any */ offset = stream->pos - stream->text.buf; /* calculate available length */ length = connection->rx_buffer_size - offset; status = apr_socket_recv(connection->sock,stream->pos,&length); if(status == APR_EOF || length == 0) { apt_pollset_t *pollset = apt_poller_task_pollset_get(agent->task); apt_log(APT_LOG_MARK,APT_PRIO_INFO,"TCP/MRCPv2 Peer Disconnected %s",connection->id); if(pollset) { apt_pollset_remove(pollset,&connection->sock_pfd); } apr_socket_close(connection->sock); connection->sock = NULL; mrcp_client_agent_disconnect_raise(agent,connection); return TRUE; } /* calculate actual length of the stream */ stream->text.length = offset + length; stream->pos[length] = '\0'; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive MRCPv2 Stream %s [%"APR_SIZE_T_FMT" bytes]\n%.*s", connection->id, length, connection->verbose == TRUE ? length : 0, stream->pos); /* reset pos */ apt_text_stream_reset(stream); do { msg_status = mrcp_parser_run(connection->parser,stream,&message); if(mrcp_client_message_handler(connection,message,msg_status) == FALSE) { return FALSE; } } while(apt_text_is_eos(stream) == FALSE); /* scroll remaining stream */ apt_text_stream_scroll(stream); return TRUE; }
static apt_bool_t test_file_process(apt_test_suite_t *suite, const char *file_path) { apr_file_t *file; char buffer[500]; apt_text_stream_t stream; rtsp_parser_t *parser; rtsp_generator_t *generator; apr_size_t length; apr_size_t offset; rtsp_message_t *message; apt_message_status_e msg_status; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open File [%s]",file_path); if(apr_file_open(&file,file_path,APR_FOPEN_READ | APR_FOPEN_BINARY,APR_OS_DEFAULT,suite->pool) != APR_SUCCESS) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open File"); return FALSE; } parser = rtsp_parser_create(suite->pool); generator = rtsp_generator_create(suite->pool); apt_text_stream_init(&stream,buffer,sizeof(buffer)-1); do { /* calculate offset remaining from the previous receive / if any */ offset = stream.pos - stream.text.buf; /* calculate available length */ length = sizeof(buffer) - 1 - offset; if(apr_file_read(file,stream.pos,&length) != APR_SUCCESS) { break; } /* calculate actual length of the stream */ stream.text.length = offset + length; stream.pos[length] = '\0'; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Parse RTSP Stream [%"APR_SIZE_T_FMT" bytes]\n%s",length,stream.pos); /* reset pos */ apt_text_stream_reset(&stream); do { msg_status = rtsp_parser_run(parser,&stream,&message); rtsp_message_handler(generator,message,msg_status); } while(apt_text_is_eos(&stream) == FALSE); /* scroll remaining stream */ apt_text_stream_scroll(&stream); } while(apr_file_eof(file) != APR_EOF); apr_file_close(file); return TRUE; }
/* Receive RTSP message through RTSP connection */ static apt_bool_t rtsp_server_poller_signal_process(void *obj, const apr_pollfd_t *descriptor) { rtsp_server_t *server = obj; rtsp_server_connection_t *rtsp_connection = descriptor->client_data; apr_status_t status; apr_size_t offset; apr_size_t length; apt_text_stream_t *stream; rtsp_message_t *message; apt_message_status_e msg_status; if(descriptor->desc.s == server->listen_sock) { apt_log(RTSP_LOG_MARK,APT_PRIO_DEBUG,"Accept Connection"); return rtsp_server_connection_accept(server); } if(!rtsp_connection || !rtsp_connection->sock) { return FALSE; } stream = &rtsp_connection->rx_stream; /* calculate offset remaining from the previous receive / if any */ offset = stream->pos - stream->text.buf; /* calculate available length */ length = sizeof(rtsp_connection->rx_buffer) - 1 - offset; status = apr_socket_recv(rtsp_connection->sock,stream->pos,&length); if(status == APR_EOF || length == 0) { apt_log(RTSP_LOG_MARK,APT_PRIO_INFO,"RTSP Peer Disconnected %s",rtsp_connection->id); return rtsp_server_connection_close(server,rtsp_connection); } /* calculate actual length of the stream */ stream->text.length = offset + length; stream->pos[length] = '\0'; apt_log(RTSP_LOG_MARK,APT_PRIO_INFO,"Receive RTSP Data %s [%"APR_SIZE_T_FMT" bytes]\n%s", rtsp_connection->id, length, stream->pos); /* reset pos */ apt_text_stream_reset(stream); do { msg_status = rtsp_parser_run(rtsp_connection->parser,stream,&message); rtsp_server_message_handler(rtsp_connection,message,msg_status); } while(apt_text_is_eos(stream) == FALSE); /* scroll remaining stream */ apt_text_stream_scroll(stream); return TRUE; }
static apt_bool_t mrcp_unirtsp_on_announce_response(mrcp_unirtsp_agent_t *agent, mrcp_unirtsp_session_t *session, rtsp_message_t *message, const char *resource_name) { mrcp_message_t *mrcp_message = NULL; if(!session || !resource_name) { return FALSE; } if(rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE && message->header.content_type == RTSP_CONTENT_TYPE_MRCP && rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE && message->header.content_length > 0) { apt_text_stream_t text_stream; mrcp_parser_t *parser; apt_str_t resource_name_str; text_stream.text = message->body; apt_text_stream_reset(&text_stream); apt_string_set(&resource_name_str,resource_name); parser = mrcp_parser_create(agent->sig_agent->resource_factory,session->mrcp_session->pool); mrcp_parser_resource_set(parser,&resource_name_str); if(mrcp_parser_run(parser,&text_stream,&mrcp_message) == APT_MESSAGE_STATUS_COMPLETE) { mrcp_message->channel_id.session_id = message->header.session_id; } else { /* error case */ apt_log(RTSP_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse MRCPv1 Message"); } } else { /* error case */ apt_log(RTSP_LOG_MARK,APT_PRIO_WARNING,"Failed to Determine MRCPv1 Message Content"); } if(!mrcp_message) { if(!session->mrcp_message) { return FALSE; } mrcp_message = mrcp_response_create(session->mrcp_message,session->mrcp_session->pool); mrcp_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED; } if(session->mrcp_message && mrcp_message->start_line.request_id == session->mrcp_message->start_line.request_id) { session->mrcp_message = NULL; } mrcp_session_control_response(session->mrcp_session,mrcp_message); return TRUE; }
/** Parse mrcp request-id list */ static apt_bool_t mrcp_request_id_list_parse(mrcp_request_id_list_t *request_id_list, const apt_str_t *value) { apt_str_t field; apt_text_stream_t stream; stream.text = *value; apt_text_stream_reset(&stream); request_id_list->count = 0; while(request_id_list->count < MAX_ACTIVE_REQUEST_ID_COUNT) { if(apt_text_field_read(&stream,',',TRUE,&field) == FALSE) { break; } request_id_list->ids[request_id_list->count] = mrcp_request_id_parse(&field); request_id_list->count++; } return TRUE; }
/* Receive MRCP message through TCP/MRCPv2 connection */ static apt_bool_t mrcp_server_poller_signal_process(void *obj, const apr_pollfd_t *descriptor) { mrcp_connection_agent_t *agent = obj; mrcp_connection_t *connection = descriptor->client_data; apr_status_t status; apr_size_t offset; apr_size_t length; apt_text_stream_t *stream; if(descriptor->desc.s == agent->listen_sock) { apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Accept Connection"); return mrcp_server_agent_connection_accept(agent); } if(!connection || !connection->sock) { return FALSE; } stream = &connection->rx_stream; /* init length of the buffer to read */ offset = 0; length = connection->rx_buffer_size; if(stream->pos > stream->text.buf) { /* calculate offset remaining from the previous receive / if any */ offset = stream->pos - stream->text.buf; /* calculate available length */ length -= offset; } status = apr_socket_recv(connection->sock,stream->pos,&length); if(status == APR_EOF || length == 0) { return mrcp_server_agent_connection_close(agent,connection); } /* calculate actual length of the stream */ stream->text.length = offset + length; stream->pos[length] = '\0'; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive MRCPv2 Stream %s [%lu bytes]\n%s", connection->id, length, stream->pos); /* reset pos */ apt_text_stream_reset(stream); /* walk through the stream parsing MRCP messages */ return mrcp_stream_walk(connection->parser,stream,mrcp_server_message_handler,connection); }
/** Parse array of name-value pairs */ APT_DECLARE(apt_bool_t) apt_pair_array_parse(apt_pair_arr_t *arr, const apt_str_t *value, apr_pool_t *pool) { apt_str_t field; apt_pair_t *pair; apt_text_stream_t stream; if(!arr || !value) { return FALSE; } stream.text = *value; apt_text_stream_reset(&stream); /* read name-value pairs */ while(apt_text_field_read(&stream,';',TRUE,&field) == TRUE) { pair = apr_array_push(arr); apt_pair_parse(pair,&field,pool); } return TRUE; }
/** Parse name=value pair */ static apt_bool_t apt_pair_parse(apt_pair_t *pair, const apt_str_t *field, apr_pool_t *pool) { apt_text_stream_t stream; apt_str_t item; stream.text = *field; apt_text_stream_reset(&stream); /* read name */ if(apt_text_field_read(&stream,'=',TRUE,&item) == FALSE) { return FALSE; } apt_string_copy(&pair->name,&item,pool); /* read value */ apt_text_field_read(&stream,';',TRUE,&item); apt_string_copy(&pair->value,&item,pool); return TRUE; }
/** Parse MRCP start-line */ MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool) { apt_text_stream_t line; apt_str_t field; apt_bool_t status = TRUE; start_line->message_type = MRCP_MESSAGE_TYPE_UNKNOWN; if(apt_text_line_read(text_stream,&line.text) == FALSE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse MRCP start-line"); return FALSE; } apt_text_stream_reset(&line); if(apt_text_field_read(&line,APT_TOKEN_SP,TRUE,&field) == FALSE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot read the first field in start-line"); return FALSE; } if(field.buf == strstr(field.buf,MRCP_NAME)) { start_line->version = mrcp_version_parse(&field); if(start_line->version == MRCP_VERSION_1) { /* parsing MRCP v1 response */ start_line->message_type = MRCP_MESSAGE_TYPE_RESPONSE; status = mrcp_response_line_parse(start_line,&line); } else if(start_line->version == MRCP_VERSION_2) { /* parsing MRCP v2 start-line (request/response/event) */ status = mrcp_v2_start_line_parse(start_line,&line,pool); } else { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown MRCP version"); return FALSE; } } else { /* parsing MRCP v1 request or event */ apt_string_copy(&start_line->method_name,&field,pool); status = mrcp_request_line_parse(start_line,&line); } return status; }
static apt_bool_t mrcp_unirtsp_session_announce(mrcp_unirtsp_agent_t *agent, mrcp_unirtsp_session_t *session, rtsp_message_t *message) { const char *resource_name = mrcp_name_get_by_rtsp_name( agent->config->resource_map, message->start_line.common.request_line.resource_name); apt_bool_t status = TRUE; if(session && resource_name && rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE && message->header.content_type == RTSP_CONTENT_TYPE_MRCP && rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE && message->header.content_length > 0) { apt_text_stream_t text_stream; mrcp_parser_t *parser; apt_str_t resource_name_str; mrcp_message_t *mrcp_message; text_stream.text = message->body; apt_text_stream_reset(&text_stream); apt_string_set(&resource_name_str,resource_name); parser = mrcp_parser_create(agent->sig_agent->resource_factory,session->mrcp_session->pool); mrcp_parser_resource_set(parser,&resource_name_str); if(mrcp_parser_run(parser,&text_stream,&mrcp_message) == APT_MESSAGE_STATUS_COMPLETE) { mrcp_message->channel_id.session_id = message->header.session_id; status = mrcp_session_control_request(session->mrcp_session,mrcp_message); } else { /* error response */ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse MRCPv1 Message"); status = FALSE; } } else { /* error response */ status = FALSE; } return status; }
/* Send RTSP message through RTSP connection */ static apt_bool_t rtsp_server_message_send(rtsp_server_t *server, rtsp_server_connection_t *rtsp_connection, rtsp_message_t *message) { apt_bool_t status = FALSE; apt_text_stream_t *stream; apt_message_status_e result; if(!rtsp_connection || !rtsp_connection->sock) { apt_log(RTSP_LOG_MARK,APT_PRIO_WARNING,"No RTSP Connection"); return FALSE; } stream = &rtsp_connection->tx_stream; do { stream->text.length = sizeof(rtsp_connection->tx_buffer)-1; apt_text_stream_reset(stream); result = rtsp_generator_run(rtsp_connection->generator,message,stream); if(result != APT_MESSAGE_STATUS_INVALID) { stream->text.length = stream->pos - stream->text.buf; *stream->pos = '\0'; apt_log(RTSP_LOG_MARK,APT_PRIO_INFO,"Send RTSP Data %s [%"APR_SIZE_T_FMT" bytes]\n%s", rtsp_connection->id, stream->text.length, stream->text.buf); if(apr_socket_send(rtsp_connection->sock,stream->text.buf,&stream->text.length) == APR_SUCCESS) { status = TRUE; } else { apt_log(RTSP_LOG_MARK,APT_PRIO_WARNING,"Failed to Send RTSP Data"); } } else { apt_log(RTSP_LOG_MARK,APT_PRIO_WARNING,"Failed to Generate RTSP Data"); } } while(result == APT_MESSAGE_STATUS_INCOMPLETE); return status; }