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_generic_header.c 2136 2014-07-04 06:33:36Z achaloyan@gmail.com $
17 */
18
19 #include "mrcp_generic_header.h"
20 #include "mrcp_start_line.h"
21
22 /** String table of mrcp generic-header fields (mrcp_generic_header_id) */
23 static const apt_str_table_item_t generic_header_string_table[] = {
24 {{"Active-Request-Id-List", 22},3},
25 {{"Proxy-Sync-Id", 13},0},
26 {{"Accept-Charset", 14},7},
27 {{"Content-Type", 12},9},
28 {{"Content-Id", 10},9},
29 {{"Content-Base", 12},8},
30 {{"Content-Encoding", 16},9},
31 {{"Content-Location", 16},9},
32 {{"Content-Length", 14},10},
33 {{"Cache-Control", 13},1},
34 {{"Logging-Tag", 11},0},
35 {{"Vendor-Specific-Parameters",26},0},
36 {{"Accept", 6},6},
37 {{"Fetch-Timeout", 13},0},
38 {{"Set-Cookie", 10},10},
39 {{"Set-Cookie2", 11},10}
40 };
41
42 /** Parse mrcp request-id list */
mrcp_request_id_list_parse(mrcp_request_id_list_t * request_id_list,const apt_str_t * value)43 static apt_bool_t mrcp_request_id_list_parse(mrcp_request_id_list_t *request_id_list, const apt_str_t *value)
44 {
45 apt_str_t field;
46 apt_text_stream_t stream;
47 stream.text = *value;
48 apt_text_stream_reset(&stream);
49 request_id_list->count = 0;
50 while(request_id_list->count < MAX_ACTIVE_REQUEST_ID_COUNT) {
51 if(apt_text_field_read(&stream,',',TRUE,&field) == FALSE) {
52 break;
53 }
54 request_id_list->ids[request_id_list->count] = mrcp_request_id_parse(&field);
55 request_id_list->count++;
56 }
57 return TRUE;
58 }
59
60 /** Generate mrcp request-id list */
mrcp_request_id_list_generate(const mrcp_request_id_list_t * request_id_list,apt_str_t * str,apr_pool_t * pool)61 static apt_bool_t mrcp_request_id_list_generate(const mrcp_request_id_list_t *request_id_list, apt_str_t *str, apr_pool_t *pool)
62 {
63 apr_size_t i;
64 int length;
65 char *pos;
66
67 /* compute estimated length, assuming request-ids consist of upto 10 digits */
68 str->length = 10 * request_id_list->count;
69 if(request_id_list->count > 1) {
70 /* , */
71 str->length += request_id_list->count - 1;
72 }
73
74 str->buf = apr_palloc(pool,str->length + 1);
75
76 pos = str->buf;
77 for(i=0; i<request_id_list->count; i++) {
78 if(i != 0) {
79 *pos++ = ',';
80 }
81
82 length = apr_snprintf(pos, str->length - (pos - str->buf), "%"MRCP_REQUEST_ID_FMT, request_id_list->ids[i]);
83 if(length < 0)
84 return FALSE;
85 pos += length;
86 }
87 *pos = '\0';
88 return TRUE;
89 }
90
91
92 /** Initialize generic-header */
mrcp_generic_header_init(mrcp_generic_header_t * generic_header)93 static void mrcp_generic_header_init(mrcp_generic_header_t *generic_header)
94 {
95 generic_header->active_request_id_list.count = 0;
96 apt_string_reset(&generic_header->proxy_sync_id);
97 apt_string_reset(&generic_header->accept_charset);
98 apt_string_reset(&generic_header->content_type);
99 apt_string_reset(&generic_header->content_id);
100 apt_string_reset(&generic_header->content_base);
101 apt_string_reset(&generic_header->content_encoding);
102 apt_string_reset(&generic_header->content_location);
103 generic_header->content_length = 0;
104 apt_string_reset(&generic_header->cache_control);
105 apt_string_reset(&generic_header->logging_tag);
106 generic_header->vendor_specific_params = NULL;
107 /* initializes additionnal MRCP v2 generic header fields */
108 apt_string_reset(&generic_header->accept);
109 generic_header->fetch_timeout = 0;
110 apt_string_reset(&generic_header->set_cookie);
111 apt_string_reset(&generic_header->set_cookie2);
112 }
113
114
115 /** Allocate generic-header */
mrcp_generic_header_allocate(mrcp_header_accessor_t * accessor,apr_pool_t * pool)116 static void* mrcp_generic_header_allocate(mrcp_header_accessor_t *accessor, apr_pool_t *pool)
117 {
118 mrcp_generic_header_t *generic_header = apr_palloc(pool,sizeof(mrcp_generic_header_t));
119 mrcp_generic_header_init(generic_header);
120 accessor->data = generic_header;
121 return accessor->data;
122 }
123
124 /** Parse generic-header */
mrcp_generic_header_parse(mrcp_header_accessor_t * accessor,size_t id,const apt_str_t * value,apr_pool_t * pool)125 static apt_bool_t mrcp_generic_header_parse(mrcp_header_accessor_t *accessor, size_t id, const apt_str_t *value, apr_pool_t *pool)
126 {
127 apt_bool_t status = TRUE;
128 mrcp_generic_header_t *generic_header = accessor->data;
129 switch(id) {
130 case GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST:
131 mrcp_request_id_list_parse(&generic_header->active_request_id_list,value);
132 break;
133 case GENERIC_HEADER_PROXY_SYNC_ID:
134 generic_header->proxy_sync_id = *value;
135 break;
136 case GENERIC_HEADER_ACCEPT_CHARSET:
137 generic_header->accept_charset = *value;
138 break;
139 case GENERIC_HEADER_CONTENT_TYPE:
140 generic_header->content_type = *value;
141 break;
142 case GENERIC_HEADER_CONTENT_ID:
143 generic_header->content_id = *value;
144 break;
145 case GENERIC_HEADER_CONTENT_BASE:
146 generic_header->content_base = *value;
147 break;
148 case GENERIC_HEADER_CONTENT_ENCODING:
149 generic_header->content_encoding = *value;
150 break;
151 case GENERIC_HEADER_CONTENT_LOCATION:
152 generic_header->content_location = *value;
153 break;
154 case GENERIC_HEADER_CONTENT_LENGTH:
155 generic_header->content_length = apt_size_value_parse(value);
156 break;
157 case GENERIC_HEADER_CACHE_CONTROL:
158 generic_header->cache_control = *value;
159 break;
160 case GENERIC_HEADER_LOGGING_TAG:
161 generic_header->logging_tag = *value;
162 break;
163 case GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS:
164 if(!generic_header->vendor_specific_params) {
165 generic_header->vendor_specific_params = apt_pair_array_create(1,pool);
166 }
167 apt_pair_array_parse(generic_header->vendor_specific_params,value,pool);
168 break;
169 case GENERIC_HEADER_ACCEPT:
170 generic_header->accept = *value;
171 break;
172 case GENERIC_HEADER_FETCH_TIMEOUT:
173 generic_header->fetch_timeout = apt_size_value_parse(value);
174 break;
175 case GENERIC_HEADER_SET_COOKIE:
176 generic_header->set_cookie = *value;
177 break;
178 case GENERIC_HEADER_SET_COOKIE2:
179 generic_header->set_cookie2 = *value;
180 break;
181 default:
182 status = FALSE;
183 }
184 return status;
185 }
186
187 /** Generate generic-header */
mrcp_generic_header_generate(const mrcp_header_accessor_t * accessor,apr_size_t id,apt_str_t * value,apr_pool_t * pool)188 static apt_bool_t mrcp_generic_header_generate(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_str_t *value, apr_pool_t *pool)
189 {
190 mrcp_generic_header_t *generic_header = accessor->data;
191 switch(id) {
192 case GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST:
193 mrcp_request_id_list_generate(&generic_header->active_request_id_list,value,pool);
194 break;
195 case GENERIC_HEADER_PROXY_SYNC_ID:
196 *value = generic_header->proxy_sync_id;
197 break;
198 case GENERIC_HEADER_ACCEPT_CHARSET:
199 *value = generic_header->accept_charset;
200 break;
201 case GENERIC_HEADER_CONTENT_TYPE:
202 *value = generic_header->content_type;
203 break;
204 case GENERIC_HEADER_CONTENT_ID:
205 *value = generic_header->content_id;
206 break;
207 case GENERIC_HEADER_CONTENT_BASE:
208 *value = generic_header->content_base;
209 break;
210 case GENERIC_HEADER_CONTENT_ENCODING:
211 *value = generic_header->content_encoding;
212 break;
213 case GENERIC_HEADER_CONTENT_LOCATION:
214 *value = generic_header->content_location;
215 break;
216 case GENERIC_HEADER_CONTENT_LENGTH:
217 apt_size_value_generate(generic_header->content_length,value,pool);
218 break;
219 case GENERIC_HEADER_CACHE_CONTROL:
220 *value = generic_header->cache_control;
221 break;
222 case GENERIC_HEADER_LOGGING_TAG:
223 *value = generic_header->logging_tag;
224 break;
225 case GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS:
226 apt_pair_array_generate(generic_header->vendor_specific_params,value,pool);
227 break;
228 case GENERIC_HEADER_ACCEPT:
229 *value = generic_header->accept;
230 break;
231 case GENERIC_HEADER_FETCH_TIMEOUT:
232 apt_size_value_generate(generic_header->fetch_timeout,value,pool);
233 break;
234 case GENERIC_HEADER_SET_COOKIE:
235 *value = generic_header->set_cookie;
236 break;
237 case GENERIC_HEADER_SET_COOKIE2:
238 *value = generic_header->set_cookie2;
239 break;
240 default:
241 break;
242 }
243 return TRUE;
244 }
245
246 /** Duplicate generic-header */
mrcp_generic_header_duplicate(mrcp_header_accessor_t * accessor,const mrcp_header_accessor_t * src,apr_size_t id,const apt_str_t * value,apr_pool_t * pool)247 static apt_bool_t mrcp_generic_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, const apt_str_t *value, apr_pool_t *pool)
248 {
249 mrcp_generic_header_t *generic_header = accessor->data;
250 const mrcp_generic_header_t *src_generic_header = src->data;
251 apt_bool_t status = TRUE;
252
253 if(!generic_header || !src_generic_header) {
254 return FALSE;
255 }
256
257 switch(id) {
258 case GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST:
259 break;
260 case GENERIC_HEADER_PROXY_SYNC_ID:
261 generic_header->proxy_sync_id = *value;
262 break;
263 case GENERIC_HEADER_ACCEPT_CHARSET:
264 generic_header->accept_charset = *value;
265 break;
266 case GENERIC_HEADER_CONTENT_TYPE:
267 generic_header->content_type = *value;
268 break;
269 case GENERIC_HEADER_CONTENT_ID:
270 generic_header->content_id = *value;
271 break;
272 case GENERIC_HEADER_CONTENT_BASE:
273 generic_header->content_base = *value;
274 break;
275 case GENERIC_HEADER_CONTENT_ENCODING:
276 generic_header->content_encoding = *value;
277 break;
278 case GENERIC_HEADER_CONTENT_LOCATION:
279 generic_header->content_location = *value;
280 break;
281 case GENERIC_HEADER_CONTENT_LENGTH:
282 generic_header->content_length = src_generic_header->content_length;
283 break;
284 case GENERIC_HEADER_CACHE_CONTROL:
285 generic_header->cache_control = *value;
286 break;
287 case GENERIC_HEADER_LOGGING_TAG:
288 generic_header->logging_tag = *value;
289 break;
290 case GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS:
291 generic_header->vendor_specific_params = apt_pair_array_copy(src_generic_header->vendor_specific_params,pool);
292 break;
293 case GENERIC_HEADER_ACCEPT:
294 generic_header->accept = *value;
295 break;
296 case GENERIC_HEADER_FETCH_TIMEOUT:
297 generic_header->fetch_timeout = src_generic_header->fetch_timeout;
298 break;
299 case GENERIC_HEADER_SET_COOKIE:
300 generic_header->set_cookie = *value;
301 break;
302 case GENERIC_HEADER_SET_COOKIE2:
303 generic_header->set_cookie2 = *value;
304 break;
305 default:
306 status = FALSE;
307 }
308 return status;
309 }
310
311 static const mrcp_header_vtable_t vtable = {
312 mrcp_generic_header_allocate,
313 NULL, /* nothing to destroy */
314 mrcp_generic_header_parse,
315 mrcp_generic_header_generate,
316 mrcp_generic_header_duplicate,
317 generic_header_string_table,
318 GENERIC_HEADER_COUNT
319 };
320
321
mrcp_generic_header_vtable_get(mrcp_version_e version)322 MRCP_DECLARE(const mrcp_header_vtable_t*) mrcp_generic_header_vtable_get(mrcp_version_e version)
323 {
324 return &vtable;
325 }
326
327
328 /** Append active request id list */
active_request_id_list_append(mrcp_generic_header_t * generic_header,mrcp_request_id request_id)329 MRCP_DECLARE(apt_bool_t) active_request_id_list_append(mrcp_generic_header_t *generic_header, mrcp_request_id request_id)
330 {
331 mrcp_request_id_list_t *request_id_list = &generic_header->active_request_id_list;
332 if(request_id_list->count >= MAX_ACTIVE_REQUEST_ID_COUNT) {
333 return FALSE;
334 }
335 request_id_list->ids[request_id_list->count++] = request_id;
336 return TRUE;
337 }
338
339 /** Find request id in active request id list */
active_request_id_list_find(const mrcp_generic_header_t * generic_header,mrcp_request_id request_id)340 MRCP_DECLARE(apt_bool_t) active_request_id_list_find(const mrcp_generic_header_t *generic_header, mrcp_request_id request_id)
341 {
342 size_t i;
343 const mrcp_request_id_list_t *request_id_list = &generic_header->active_request_id_list;
344 for(i=0; i<request_id_list->count; i++) {
345 if(request_id_list->ids[i] == request_id) {
346 return TRUE;
347 }
348 }
349 return FALSE;
350 }
351