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