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
34int
35SPDYF_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
41struct SPDY_NameValue *
42SPDY_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
55int
56SPDY_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
189const char * const *
190SPDY_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
217void
218SPDY_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
236int
237SPDY_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
278void
279SPDY_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
289struct SPDYF_Response_Queue *
290SPDYF_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
434void
435SPDYF_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
457SPDYF_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
554SPDYF_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