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