1 /*
2 This file is part of libmicrospdy
3 Copyright Copyright (C) 2012 Andrey Uzunov
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * @file structures.c
21 * @brief Functions for handling most of the structures in defined
22 * in structures.h
23 * @author Andrey Uzunov
24 */
25
26 #include "platform.h"
27 #include "structures.h"
28 #include "internal.h"
29 #include "session.h"
30 //TODO not for here?
31 #include <ctype.h>
32
33
34 int
SPDYF_name_value_is_empty(struct SPDY_NameValue * container)35 SPDYF_name_value_is_empty(struct SPDY_NameValue *container)
36 {
37 SPDYF_ASSERT(NULL != container, "NULL is not an empty container!");
38 return (NULL == container->name && NULL == container->value) ? SPDY_YES : SPDY_NO;
39 }
40
41 struct SPDY_NameValue *
SPDY_name_value_create()42 SPDY_name_value_create ()
43 {
44 struct SPDY_NameValue *pair;
45
46 if(NULL == (pair = malloc(sizeof(struct SPDY_NameValue))))
47 return NULL;
48
49 memset (pair, 0, sizeof (struct SPDY_NameValue));
50
51 return pair;
52 }
53
54
55 int
SPDY_name_value_add(struct SPDY_NameValue * container,const char * name,const char * value)56 SPDY_name_value_add (struct SPDY_NameValue *container,
57 const char *name,
58 const char *value)
59 {
60 unsigned int i;
61 unsigned int len;
62 struct SPDY_NameValue *pair;
63 struct SPDY_NameValue *temp;
64 char **temp_value;
65 char *temp_string;
66
67 if(NULL == container || NULL == name || NULL == value || 0 == (len = strlen(name)))
68 return SPDY_INPUT_ERROR;
69 //TODO there is old code handling value==NULL
70 //update it to handle strlen(value)==0
71
72 for(i=0; i<len; ++i)
73 {
74 if(isupper((int) name[i]))
75 return SPDY_INPUT_ERROR;
76 }
77
78 if(SPDYF_name_value_is_empty(container))
79 {
80 //container is empty/just created
81 if (NULL == (container->name = strdup (name)))
82 {
83 return SPDY_NO;
84 }
85 if (NULL == (container->value = malloc(sizeof(char *))))
86 {
87 free(container->name);
88 return SPDY_NO;
89 }
90 /*if(NULL == value)
91 container->value[0] = NULL;
92 else */if (NULL == (container->value[0] = strdup (value)))
93 {
94 free(container->value);
95 free(container->name);
96 return SPDY_NO;
97 }
98 container->num_values = 1;
99 return SPDY_YES;
100 }
101
102 pair = container;
103 while(NULL != pair)
104 {
105 if(0 == strcmp(pair->name, name))
106 {
107 //the value will be added to this pair
108 break;
109 }
110 pair = pair->next;
111 }
112
113 if(NULL == pair)
114 {
115 //the name doesn't exist in container, add new pair
116 if(NULL == (pair = malloc(sizeof(struct SPDY_NameValue))))
117 return SPDY_NO;
118
119 memset(pair, 0, sizeof(struct SPDY_NameValue));
120
121 if (NULL == (pair->name = strdup (name)))
122 {
123 free(pair);
124 return SPDY_NO;
125 }
126 if (NULL == (pair->value = malloc(sizeof(char *))))
127 {
128 free(pair->name);
129 free(pair);
130 return SPDY_NO;
131 }
132 /*if(NULL == value)
133 pair->value[0] = NULL;
134 else */if (NULL == (pair->value[0] = strdup (value)))
135 {
136 free(pair->value);
137 free(pair->name);
138 free(pair);
139 return SPDY_NO;
140 }
141 pair->num_values = 1;
142
143 temp = container;
144 while(NULL != temp->next)
145 temp = temp->next;
146 temp->next = pair;
147 pair->prev = temp;
148
149 return SPDY_YES;
150 }
151
152 //check for duplication (case sensitive)
153 for(i=0; i<pair->num_values; ++i)
154 if(0 == strcmp(pair->value[i], value))
155 return SPDY_NO;
156
157 if(strlen(pair->value[0]) > 0)
158 {
159 //the value will be appended to the others for this name
160 if (NULL == (temp_value = malloc((pair->num_values + 1) * sizeof(char *))))
161 {
162 return SPDY_NO;
163 }
164 memcpy(temp_value, pair->value, pair->num_values * sizeof(char *));
165 if (NULL == (temp_value[pair->num_values] = strdup (value)))
166 {
167 free(temp_value);
168 return SPDY_NO;
169 }
170 free(pair->value);
171 pair->value = temp_value;
172 ++pair->num_values;
173 return SPDY_YES;
174 }
175
176 //just replace the empty value
177
178 if (NULL == (temp_string = strdup (value)))
179 {
180 return SPDY_NO;
181 }
182 free(pair->value[0]);
183 pair->value[0] = temp_string;
184
185 return SPDY_YES;
186 }
187
188
189 const char * const *
SPDY_name_value_lookup(struct SPDY_NameValue * container,const char * name,int * num_values)190 SPDY_name_value_lookup (struct SPDY_NameValue *container,
191 const char *name,
192 int *num_values)
193 {
194 struct SPDY_NameValue *temp = container;
195
196 if(NULL == container || NULL == name || NULL == num_values)
197 return NULL;
198 if(SPDYF_name_value_is_empty(container))
199 return NULL;
200
201 do
202 {
203 if(strcmp(name, temp->name) == 0)
204 {
205 *num_values = temp->num_values;
206 return (const char * const *)temp->value;
207 }
208
209 temp = temp->next;
210 }
211 while(NULL != temp);
212
213 return NULL;
214 }
215
216
217 void
SPDY_name_value_destroy(struct SPDY_NameValue * container)218 SPDY_name_value_destroy (struct SPDY_NameValue *container)
219 {
220 unsigned int i;
221 struct SPDY_NameValue *temp = container;
222
223 while(NULL != temp)
224 {
225 container = container->next;
226 free(temp->name);
227 for(i=0; i<temp->num_values; ++i)
228 free(temp->value[i]);
229 free(temp->value);
230 free(temp);
231 temp=container;
232 }
233 }
234
235
236 int
SPDY_name_value_iterate(struct SPDY_NameValue * container,SPDY_NameValueIterator iterator,void * iterator_cls)237 SPDY_name_value_iterate (struct SPDY_NameValue *container,
238 SPDY_NameValueIterator iterator,
239 void *iterator_cls)
240 {
241 int count;
242 int ret;
243 struct SPDY_NameValue *temp = container;
244
245 if(NULL == container)
246 return SPDY_INPUT_ERROR;
247
248 //check if container is an empty struct
249 if(SPDYF_name_value_is_empty(container))
250 return 0;
251
252 count = 0;
253
254 if(NULL == iterator)
255 {
256 do
257 {
258 ++count;
259 temp=temp->next;
260 }
261 while(NULL != temp);
262
263 return count;
264 }
265
266 //code duplication for avoiding if here
267 do
268 {
269 ++count;
270 ret = iterator(iterator_cls, temp->name, (const char * const *)temp->value, temp->num_values);
271 temp=temp->next;
272 }
273 while(NULL != temp && SPDY_YES == ret);
274
275 return count;
276 }
277
278 void
SPDY_destroy_response(struct SPDY_Response * response)279 SPDY_destroy_response(struct SPDY_Response *response)
280 {
281 if(NULL == response)
282 return;
283 free(response->data);
284 free(response->headers);
285 free(response);
286 }
287
288
289 struct SPDYF_Response_Queue *
SPDYF_response_queue_create(bool is_data,void * data,size_t data_size,struct SPDY_Response * response,struct SPDYF_Stream * stream,bool closestream,SPDYF_ResponseQueueResultCallback frqcb,void * frqcb_cls,SPDY_ResponseResultCallback rrcb,void * rrcb_cls)290 SPDYF_response_queue_create(bool is_data,
291 void *data,
292 size_t data_size,
293 struct SPDY_Response *response,
294 struct SPDYF_Stream *stream,
295 bool closestream,
296 SPDYF_ResponseQueueResultCallback frqcb,
297 void *frqcb_cls,
298 SPDY_ResponseResultCallback rrcb,
299 void *rrcb_cls)
300 {
301 struct SPDYF_Response_Queue *head = NULL;
302 struct SPDYF_Response_Queue *prev;
303 struct SPDYF_Response_Queue *response_to_queue;
304 struct SPDYF_Control_Frame *control_frame;
305 struct SPDYF_Data_Frame *data_frame;
306 unsigned int i;
307 bool is_last;
308
309 SPDYF_ASSERT((! is_data)
310 || ((0 == data_size) && (NULL != response->rcb))
311 || ((0 < data_size) && (NULL == response->rcb)),
312 "either data or request->rcb must not be null");
313
314 if (is_data && (data_size > SPDY_MAX_SUPPORTED_FRAME_SIZE))
315 {
316 //separate the data in more frames and add them to the queue
317
318 prev=NULL;
319 for(i = 0; i < data_size; i += SPDY_MAX_SUPPORTED_FRAME_SIZE)
320 {
321 is_last = (i + SPDY_MAX_SUPPORTED_FRAME_SIZE) >= data_size;
322
323 if(NULL == (response_to_queue = malloc(sizeof(struct SPDYF_Response_Queue))))
324 goto free_and_fail;
325
326 memset(response_to_queue, 0, sizeof(struct SPDYF_Response_Queue));
327 if(0 == i)
328 head = response_to_queue;
329
330 if(NULL == (data_frame = malloc(sizeof(struct SPDYF_Data_Frame))))
331 {
332 free(response_to_queue);
333 goto free_and_fail;
334 }
335 memset(data_frame, 0, sizeof(struct SPDYF_Data_Frame));
336 data_frame->control_bit = 0;
337 data_frame->stream_id = stream->stream_id;
338 if(is_last && closestream)
339 data_frame->flags |= SPDY_DATA_FLAG_FIN;
340
341 response_to_queue->data_frame = data_frame;
342 response_to_queue->process_response_handler = &SPDYF_handler_write_data;
343 response_to_queue->is_data = is_data;
344 response_to_queue->stream = stream;
345 if(is_last)
346 {
347 response_to_queue->frqcb = frqcb;
348 response_to_queue->frqcb_cls = frqcb_cls;
349 response_to_queue->rrcb = rrcb;
350 response_to_queue->rrcb_cls = rrcb_cls;
351 }
352 response_to_queue->data = data + i;
353 response_to_queue->data_size = is_last
354 ? (data_size - 1) % SPDY_MAX_SUPPORTED_FRAME_SIZE + 1
355 : SPDY_MAX_SUPPORTED_FRAME_SIZE;
356 response_to_queue->response = response;
357
358 response_to_queue->prev = prev;
359 if(NULL != prev)
360 prev->next = response_to_queue;
361 prev = response_to_queue;
362 }
363
364 return head;
365
366 //for GOTO
367 free_and_fail:
368 while(NULL != head)
369 {
370 response_to_queue = head;
371 head = head->next;
372 free(response_to_queue->data_frame);
373 free(response_to_queue);
374 }
375 return NULL;
376 }
377
378 //create only one frame for data, data with callback or control frame
379
380 if(NULL == (response_to_queue = malloc(sizeof(struct SPDYF_Response_Queue))))
381 {
382 return NULL;
383 }
384 memset(response_to_queue, 0, sizeof(struct SPDYF_Response_Queue));
385
386 if(is_data)
387 {
388 if(NULL == (data_frame = malloc(sizeof(struct SPDYF_Data_Frame))))
389 {
390 free(response_to_queue);
391 return NULL;
392 }
393 memset(data_frame, 0, sizeof(struct SPDYF_Data_Frame));
394 data_frame->control_bit = 0;
395 data_frame->stream_id = stream->stream_id;
396 if(closestream && NULL == response->rcb)
397 data_frame->flags |= SPDY_DATA_FLAG_FIN;
398
399 response_to_queue->data_frame = data_frame;
400 response_to_queue->process_response_handler = &SPDYF_handler_write_data;
401 }
402 else
403 {
404 if(NULL == (control_frame = malloc(sizeof(struct SPDYF_Control_Frame))))
405 {
406 free(response_to_queue);
407 return NULL;
408 }
409 memset(control_frame, 0, sizeof(struct SPDYF_Control_Frame));
410 control_frame->control_bit = 1;
411 control_frame->version = SPDY_VERSION;
412 control_frame->type = SPDY_CONTROL_FRAME_TYPES_SYN_REPLY;
413 if(closestream)
414 control_frame->flags |= SPDY_SYN_REPLY_FLAG_FIN;
415
416 response_to_queue->control_frame = control_frame;
417 response_to_queue->process_response_handler = &SPDYF_handler_write_syn_reply;
418 }
419
420 response_to_queue->is_data = is_data;
421 response_to_queue->stream = stream;
422 response_to_queue->frqcb = frqcb;
423 response_to_queue->frqcb_cls = frqcb_cls;
424 response_to_queue->rrcb = rrcb;
425 response_to_queue->rrcb_cls = rrcb_cls;
426 response_to_queue->data = data;
427 response_to_queue->data_size = data_size;
428 response_to_queue->response = response;
429
430 return response_to_queue;
431 }
432
433
434 void
SPDYF_response_queue_destroy(struct SPDYF_Response_Queue * response_queue)435 SPDYF_response_queue_destroy(struct SPDYF_Response_Queue *response_queue)
436 {
437 //data is not copied to the struct but only linked
438 //but this is not valid for GOAWAY and RST_STREAM
439 if(!response_queue->is_data
440 && (SPDY_CONTROL_FRAME_TYPES_RST_STREAM == response_queue->control_frame->type
441 || SPDY_CONTROL_FRAME_TYPES_GOAWAY == response_queue->control_frame->type))
442 {
443 free(response_queue->data);
444 }
445 if(response_queue->is_data)
446 free(response_queue->data_frame);
447 else
448 free(response_queue->control_frame);
449
450 free(response_queue);
451 }
452
453
454 /* Needed by testcase to be extern -- should this be
455 in the header? */
456 _MHD_EXTERN ssize_t
SPDYF_name_value_to_stream(struct SPDY_NameValue * container[],int num_containers,void ** stream)457 SPDYF_name_value_to_stream(struct SPDY_NameValue * container[],
458 int num_containers,
459 void **stream)
460 {
461 size_t size;
462 int32_t num_pairs = 0;
463 int32_t value_size;
464 int32_t name_size;
465 int32_t temp;
466 unsigned int i;
467 unsigned int offset;
468 unsigned int value_offset;
469 struct SPDY_NameValue * iterator;
470 int j;
471
472 size = 4; //for num pairs
473
474 for(j=0; j<num_containers; ++j)
475 {
476 iterator = container[j];
477 while(iterator != NULL)
478 {
479 ++num_pairs;
480 size += 4 + strlen(iterator->name); //length + string
481
482 SPDYF_ASSERT(iterator->num_values>0, "num_values is 0");
483
484 size += 4; //value length
485
486 for(i=0; i<iterator->num_values; ++i)
487 {
488 //if(NULL == iterator->value[i])
489 // continue;
490 size += strlen(iterator->value[i]); // string
491 if(i/* || !strlen(iterator->value[i])*/) ++size; //NULL separator
492 }
493
494 iterator = iterator->next;
495 }
496 }
497
498 if(NULL == (*stream = malloc(size)))
499 {
500 return -1;
501 }
502
503 //put num_pairs to the stream
504 num_pairs = htonl(num_pairs);
505 memcpy(*stream, &num_pairs, 4);
506 offset = 4;
507
508 //put all other headers to the stream
509 for(j=0; j<num_containers; ++j)
510 {
511 iterator = container[j];
512 while(iterator != NULL)
513 {
514 name_size = strlen(iterator->name);
515 temp = htonl(name_size);
516 memcpy(*stream + offset, &temp, 4);
517 offset += 4;
518 strncpy(*stream + offset, iterator->name, name_size);
519 offset += name_size;
520
521 value_offset = offset;
522 offset += 4;
523 for(i=0; i<iterator->num_values; ++i)
524 {
525 if(i /*|| !strlen(iterator->value[0])*/)
526 {
527 memset(*stream + offset, 0, 1);
528 ++offset;
529 //if(!i) continue;
530 }
531 //else if(NULL != iterator->value[i])
532 //{
533 strncpy(*stream + offset, iterator->value[i], strlen(iterator->value[i]));
534 offset += strlen(iterator->value[i]);
535 //}
536 }
537 value_size = offset - value_offset - 4;
538 value_size = htonl(value_size);
539 memcpy(*stream + value_offset, &value_size, 4);
540
541 iterator = iterator->next;
542 }
543 }
544
545 SPDYF_ASSERT(offset == size,"offset is wrong");
546
547 return size;
548 }
549
550
551 /* Needed by testcase to be extern -- should this be
552 in the header? */
553 _MHD_EXTERN int
SPDYF_name_value_from_stream(void * stream,size_t size,struct SPDY_NameValue ** container)554 SPDYF_name_value_from_stream(void *stream,
555 size_t size,
556 struct SPDY_NameValue ** container)
557 {
558 int32_t num_pairs;
559 int32_t value_size;
560 int32_t name_size;
561 int i;
562 unsigned int offset = 0;
563 unsigned int value_end_offset;
564 char *name;
565 char *value;
566
567 if(NULL == (*container = SPDY_name_value_create ()))
568 {
569 return SPDY_NO;
570 }
571
572 //get number of pairs
573 memcpy(&num_pairs, stream, 4);
574 offset = 4;
575 num_pairs = ntohl(num_pairs);
576
577 if(num_pairs > 0)
578 {
579 for(i = 0; i < num_pairs; ++i)
580 {
581 //get name size
582 memcpy(&name_size, stream + offset, 4);
583 offset += 4;
584 name_size = ntohl(name_size);
585 //get name
586 if(NULL == (name = strndup(stream + offset, name_size)))
587 {
588 SPDY_name_value_destroy(*container);
589 return SPDY_NO;
590 }
591 offset+=name_size;
592
593 //get value size
594 memcpy(&value_size, stream + offset, 4);
595 offset += 4;
596 value_size = ntohl(value_size);
597 value_end_offset = offset + value_size;
598 //get value
599 do
600 {
601 if(NULL == (value = strndup(stream + offset, value_size)))
602 {
603 free(name);
604 SPDY_name_value_destroy(*container);
605 return SPDY_NO;
606 }
607 offset += strlen(value);
608 if(offset < value_end_offset)
609 ++offset; //NULL separator
610
611 //add name/value to the struct
612 if(SPDY_YES != SPDY_name_value_add(*container, name, value))
613 {
614 free(name);
615 free(value);
616 SPDY_name_value_destroy(*container);
617 return SPDY_NO;
618 }
619 free(value);
620 }
621 while(offset < value_end_offset);
622
623 free(name);
624
625 if(offset != value_end_offset)
626 {
627 SPDY_name_value_destroy(*container);
628 return SPDY_INPUT_ERROR;
629 }
630 }
631 }
632
633 if(offset == size)
634 return SPDY_YES;
635
636 SPDY_name_value_destroy(*container);
637 return SPDY_INPUT_ERROR;
638 }
639