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