• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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