Home | History | Annotate | Download | only in microspdy
      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
     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 *
     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
     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 *
    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
    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
    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
    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 *
    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
    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
    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
    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