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_stream.c 2136 2014-07-04 06:33:36Z achaloyan@gmail.com $
17 */
18
19 #include "mrcp_stream.h"
20 #include "mrcp_message.h"
21 #include "mrcp_resource_factory.h"
22 #include "mrcp_resource.h"
23 #include "apt_log.h"
24
25
26 /** MRCP parser */
27 struct mrcp_parser_t {
28 apt_message_parser_t *base;
29 const mrcp_resource_factory_t *resource_factory;
30 mrcp_resource_t *resource;
31 };
32
33 /** MRCP generator */
34 struct mrcp_generator_t {
35 apt_message_generator_t *base;
36 const mrcp_resource_factory_t *resource_factory;
37 };
38
39 /** Create message and read start line */
40 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);
41 /** Header section handler */
42 static apt_bool_t mrcp_parser_on_header_complete(apt_message_parser_t *parser, apt_message_context_t *context);
43
44 static const apt_message_parser_vtable_t parser_vtable = {
45 mrcp_parser_on_start,
46 mrcp_parser_on_header_complete,
47 NULL
48 };
49
50 /** Start message generation */
51 apt_bool_t mrcp_generator_on_start(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream);
52 /** Finalize by setting overall message length in start line */
53 apt_bool_t mrcp_generator_on_header_complete(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream);
54
55 static const apt_message_generator_vtable_t generator_vtable = {
56 mrcp_generator_on_start,
57 mrcp_generator_on_header_complete,
58 NULL
59 };
60
61
62 /** Create MRCP stream parser */
mrcp_parser_create(const mrcp_resource_factory_t * resource_factory,apr_pool_t * pool)63 MRCP_DECLARE(mrcp_parser_t*) mrcp_parser_create(const mrcp_resource_factory_t *resource_factory, apr_pool_t *pool)
64 {
65 mrcp_parser_t *parser = apr_palloc(pool,sizeof(mrcp_parser_t));
66 parser->base = apt_message_parser_create(parser,&parser_vtable,pool);
67 parser->resource_factory = resource_factory;
68 parser->resource = NULL;
69 return parser;
70 }
71
72 /** Set resource by name to be used for parsing of MRCPv1 messages */
mrcp_parser_resource_set(mrcp_parser_t * parser,const apt_str_t * resource_name)73 MRCP_DECLARE(void) mrcp_parser_resource_set(mrcp_parser_t *parser, const apt_str_t *resource_name)
74 {
75 if(resource_name) {
76 parser->resource = mrcp_resource_find(parser->resource_factory,resource_name);
77 }
78 }
79
80 /** Set verbose mode for the parser */
mrcp_parser_verbose_set(mrcp_parser_t * parser,apt_bool_t verbose)81 MRCP_DECLARE(void) mrcp_parser_verbose_set(mrcp_parser_t *parser, apt_bool_t verbose)
82 {
83 apt_message_parser_verbose_set(parser->base,verbose);
84 }
85
86 /** Parse MRCP stream */
mrcp_parser_run(mrcp_parser_t * parser,apt_text_stream_t * stream,mrcp_message_t ** message)87 MRCP_DECLARE(apt_message_status_e) mrcp_parser_run(mrcp_parser_t *parser, apt_text_stream_t *stream, mrcp_message_t **message)
88 {
89 return apt_message_parser_run(parser->base,stream,(void**)message);
90 }
91
92 /** Create message and read start line */
mrcp_parser_on_start(apt_message_parser_t * parser,apt_message_context_t * context,apt_text_stream_t * stream,apr_pool_t * pool)93 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)
94 {
95 mrcp_message_t *mrcp_message;
96 apt_str_t start_line;
97 /* read start line */
98 if(apt_text_line_read(stream,&start_line) == FALSE) {
99 return FALSE;
100 }
101
102 /* create new MRCP message */
103 mrcp_message = mrcp_message_create(pool);
104 /* parse start-line */
105 if(mrcp_start_line_parse(&mrcp_message->start_line,&start_line,mrcp_message->pool) == FALSE) {
106 return FALSE;
107 }
108
109 if(mrcp_message->start_line.version == MRCP_VERSION_1) {
110 mrcp_parser_t *mrcp_parser = apt_message_parser_object_get(parser);
111 if(!mrcp_parser->resource) {
112 return FALSE;
113 }
114 apt_string_copy(
115 &mrcp_message->channel_id.resource_name,
116 &mrcp_parser->resource->name,
117 pool);
118
119 if(mrcp_message_resource_set(mrcp_message,mrcp_parser->resource) == FALSE) {
120 return FALSE;
121 }
122 }
123
124 context->message = mrcp_message;
125 context->header = &mrcp_message->header.header_section;
126 context->body = &mrcp_message->body;
127 return TRUE;
128 }
129
130 /** Header section handler */
mrcp_parser_on_header_complete(apt_message_parser_t * parser,apt_message_context_t * context)131 static apt_bool_t mrcp_parser_on_header_complete(apt_message_parser_t *parser, apt_message_context_t *context)
132 {
133 mrcp_message_t *mrcp_message = context->message;
134 if(mrcp_message->start_line.version == MRCP_VERSION_2) {
135 mrcp_resource_t *resource;
136 mrcp_parser_t *mrcp_parser;
137 if(mrcp_channel_id_parse(&mrcp_message->channel_id,&mrcp_message->header,mrcp_message->pool) == FALSE) {
138 return FALSE;
139 }
140 mrcp_parser = apt_message_parser_object_get(parser);
141 /* find resource */
142 resource = mrcp_resource_find(mrcp_parser->resource_factory,&mrcp_message->channel_id.resource_name);
143 if(!resource) {
144 return FALSE;
145 }
146
147 if(mrcp_message_resource_set(mrcp_message,resource) == FALSE) {
148 return FALSE;
149 }
150 }
151
152 if(mrcp_header_fields_parse(&mrcp_message->header,mrcp_message->pool) == FALSE) {
153 return FALSE;
154 }
155
156 if(context->body && mrcp_generic_header_property_check(mrcp_message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
157 mrcp_generic_header_t *generic_header = mrcp_generic_header_get(mrcp_message);
158 if(generic_header && generic_header->content_length) {
159 context->body->length = generic_header->content_length;
160 }
161 }
162 return TRUE;
163 }
164
165
166 /** Create MRCP stream generator */
mrcp_generator_create(const mrcp_resource_factory_t * resource_factory,apr_pool_t * pool)167 MRCP_DECLARE(mrcp_generator_t*) mrcp_generator_create(const mrcp_resource_factory_t *resource_factory, apr_pool_t *pool)
168 {
169 mrcp_generator_t *generator = apr_palloc(pool,sizeof(mrcp_generator_t));
170 generator->base = apt_message_generator_create(generator,&generator_vtable,pool);
171 generator->resource_factory = resource_factory;
172 return generator;
173 }
174
175 /** Set verbose mode for the generator */
mrcp_generator_verbose_set(mrcp_generator_t * generator,apt_bool_t verbose)176 MRCP_DECLARE(void) mrcp_generator_verbose_set(mrcp_generator_t *generator, apt_bool_t verbose)
177 {
178 apt_message_generator_verbose_set(generator->base,verbose);
179 }
180
181 /** Generate MRCP stream */
mrcp_generator_run(mrcp_generator_t * generator,mrcp_message_t * message,apt_text_stream_t * stream)182 MRCP_DECLARE(apt_message_status_e) mrcp_generator_run(mrcp_generator_t *generator, mrcp_message_t *message, apt_text_stream_t *stream)
183 {
184 return apt_message_generator_run(generator->base,message,stream);
185 }
186
187 /** Initialize by generating message start line and return header section and body */
mrcp_generator_on_start(apt_message_generator_t * generator,apt_message_context_t * context,apt_text_stream_t * stream)188 apt_bool_t mrcp_generator_on_start(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream)
189 {
190 mrcp_message_t *mrcp_message = context->message;
191 /* validate message */
192 if(mrcp_message_validate(mrcp_message) == FALSE) {
193 return FALSE;
194 }
195 /* generate start-line */
196 if(mrcp_start_line_generate(&mrcp_message->start_line,stream) == FALSE) {
197 return FALSE;
198 }
199
200 if(mrcp_message->start_line.version == MRCP_VERSION_2) {
201 mrcp_channel_id_generate(&mrcp_message->channel_id,stream);
202 }
203
204 context->header = &mrcp_message->header.header_section;
205 context->body = &mrcp_message->body;
206 return TRUE;
207 }
208
209 /** Finalize by setting overall message length in start line */
mrcp_generator_on_header_complete(apt_message_generator_t * generator,apt_message_context_t * context,apt_text_stream_t * stream)210 apt_bool_t mrcp_generator_on_header_complete(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream)
211 {
212 mrcp_message_t *mrcp_message = context->message;
213 /* finalize start-line generation */
214 return mrcp_start_line_finalize(&mrcp_message->start_line,mrcp_message->body.length,stream);
215 }
216
217 /** Generate MRCP message (excluding message body) */
mrcp_message_generate(const mrcp_resource_factory_t * resource_factory,mrcp_message_t * message,apt_text_stream_t * stream)218 MRCP_DECLARE(apt_bool_t) mrcp_message_generate(const mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream)
219 {
220 /* validate message */
221 if(mrcp_message_validate(message) == FALSE) {
222 return FALSE;
223 }
224
225 /* generate start-line */
226 if(mrcp_start_line_generate(&message->start_line,stream) == FALSE) {
227 return FALSE;
228 }
229
230 if(message->start_line.version == MRCP_VERSION_2) {
231 mrcp_channel_id_generate(&message->channel_id,stream);
232 }
233
234 /* generate header section */
235 if(apt_header_section_generate(&message->header.header_section,stream) == FALSE) {
236 return FALSE;
237 }
238
239 /* finalize start-line generation */
240 if(mrcp_start_line_finalize(&message->start_line,message->body.length,stream) == FALSE) {
241 return FALSE;
242 }
243
244 return TRUE;
245 }
246