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 applicationlayer.c 21 * @brief SPDY application or HTTP layer 22 * @author Andrey Uzunov 23 */ 24 25 #include "platform.h" 26 #include "applicationlayer.h" 27 #include "alstructures.h" 28 #include "structures.h" 29 #include "internal.h" 30 #include "daemon.h" 31 #include "session.h" 32 33 34 void 35 spdy_callback_response_done(void *cls, 36 struct SPDY_Response *response, 37 struct SPDY_Request *request, 38 enum SPDY_RESPONSE_RESULT status, 39 bool streamopened) 40 { 41 (void)cls; 42 (void)status; 43 (void)streamopened; 44 45 SPDY_destroy_request(request); 46 SPDY_destroy_response(response); 47 } 48 49 50 /** 51 * Callback called when new stream is created. It extracts the info from 52 * the stream to create (HTTP) request object and pass it to the client. 53 * 54 * @param cls 55 * @param stream the new SPDY stream 56 * @return SPDY_YES on success, SPDY_NO on memomry error 57 */ 58 static int 59 spdy_handler_new_stream (void *cls, 60 struct SPDYF_Stream * stream) 61 { 62 (void)cls; 63 unsigned int i; 64 char *method = NULL; 65 char *path = NULL; 66 char *version = NULL; 67 char *host = NULL; 68 char *scheme = NULL; 69 struct SPDY_Request * request = NULL; 70 struct SPDY_NameValue * headers = NULL; 71 struct SPDY_NameValue * iterator = stream->headers; 72 struct SPDY_Daemon *daemon; 73 74 daemon = stream->session->daemon; 75 76 //if the user doesn't care, ignore it 77 if(NULL == daemon->new_request_cb) 78 return SPDY_YES; 79 80 if(NULL == (headers=SPDY_name_value_create())) 81 goto free_and_fail; 82 83 if(NULL==(request = malloc(sizeof(struct SPDY_Request)))) 84 goto free_and_fail; 85 86 memset(request, 0, sizeof(struct SPDY_Request)); 87 request->stream = stream; 88 89 /* extract the mandatory fields from stream->headers' structure 90 * to pass them to the client */ 91 while(iterator != NULL) 92 { 93 if(strcmp(":method",iterator->name) == 0) 94 { 95 if(1 != iterator->num_values) 96 break; 97 method = iterator->value[0]; 98 } 99 else if(strcmp(":path",iterator->name) == 0) 100 { 101 if(1 != iterator->num_values) 102 break; 103 path = iterator->value[0]; 104 } 105 else if(strcmp(":version",iterator->name) == 0) 106 { 107 if(1 != iterator->num_values) 108 break; 109 version = iterator->value[0]; 110 } 111 else if(strcmp(":host",iterator->name) == 0) 112 { 113 //TODO can it have more values? 114 if(1 != iterator->num_values) 115 break; 116 host = iterator->value[0]; 117 } 118 else if(strcmp(":scheme",iterator->name) == 0) 119 { 120 if(1 != iterator->num_values) 121 break; 122 scheme = iterator->value[0]; 123 } 124 else 125 for(i=0; i<iterator->num_values; ++i) 126 if (SPDY_YES != SPDY_name_value_add(headers,iterator->name,iterator->value[i])) 127 { 128 SPDY_destroy_request(request); 129 goto free_and_fail; 130 } 131 132 iterator = iterator->next; 133 } 134 135 request->method=method; 136 request->path=path; 137 request->version=version; 138 request->host=host; 139 request->scheme=scheme; 140 request->headers=headers; 141 142 //check request validity, all these fields are mandatory for a request 143 if(NULL == method || strlen(method) == 0 144 || NULL == path || strlen(path) == 0 145 || NULL == version || strlen(version) == 0 146 || NULL == host || strlen(host) == 0 147 || NULL == scheme || strlen(scheme) == 0 148 ) 149 { 150 //TODO HTTP 400 Bad Request must be answered 151 152 SPDYF_DEBUG("Bad request"); 153 154 SPDY_destroy_request(request); 155 156 return SPDY_YES; 157 } 158 159 //call client's callback function to notify 160 daemon->new_request_cb(daemon->cls, 161 request, 162 stream->priority, 163 method, 164 path, 165 version, 166 host, 167 scheme, 168 headers, 169 !stream->is_in_closed); 170 171 stream->cls = request; 172 173 return SPDY_YES; 174 175 //for GOTO 176 free_and_fail: 177 178 SPDY_name_value_destroy(headers); 179 return SPDY_NO; 180 } 181 182 183 /** 184 * TODO 185 */ 186 static int 187 spdy_handler_new_data (void * cls, 188 struct SPDYF_Stream *stream, 189 const void * buf, 190 size_t size, 191 bool more) 192 { 193 return stream->session->daemon->received_data_cb(cls, stream->cls, buf, size, more); 194 } 195 196 197 198 /** 199 * Callback to be called when the response queue object was handled and 200 * the data was already sent or discarded. 201 * 202 * @param cls 203 * @param response_queue the object which is being handled 204 * @param status shows if actually the response was sent or it was 205 * discarded by the lib for any reason (e.g., closing session, 206 * closing stream, stopping daemon, etc.). It is possible that 207 * status indicates an error but parts of the response headers 208 * and/or body (in one 209 * or several frames) were already sent to the client. 210 */ 211 static void 212 spdy_handler_response_queue_result(void * cls, 213 struct SPDYF_Response_Queue *response_queue, 214 enum SPDY_RESPONSE_RESULT status) 215 { 216 int streamopened; 217 struct SPDY_Request *request = (struct SPDY_Request *)cls; 218 219 SPDYF_ASSERT( ( (NULL == response_queue->data_frame) && 220 (NULL != response_queue->control_frame) ) || 221 ( (NULL != response_queue->data_frame) && 222 (NULL == response_queue->control_frame) ), 223 "response queue must have either control frame or data frame"); 224 225 streamopened = !response_queue->stream->is_out_closed; 226 227 response_queue->rrcb(response_queue->rrcb_cls, response_queue->response, request, status, streamopened); 228 } 229 230 231 int 232 (SPDY_init) (enum SPDY_IO_SUBSYSTEM io_subsystem, ...) 233 { 234 SPDYF_ASSERT(SPDYF_BUFFER_SIZE >= SPDY_MAX_SUPPORTED_FRAME_SIZE, 235 "Buffer size is less than max supported frame size!"); 236 SPDYF_ASSERT(SPDY_MAX_SUPPORTED_FRAME_SIZE >= 32, 237 "Max supported frame size must be bigger than the minimal value!"); 238 SPDYF_ASSERT(SPDY_IO_SUBSYSTEM_NONE == spdyf_io_initialized, 239 "SPDY_init must be called only once per program or after SPDY_deinit"); 240 241 if(SPDY_IO_SUBSYSTEM_OPENSSL & io_subsystem) 242 { 243 SPDYF_openssl_global_init(); 244 spdyf_io_initialized |= SPDY_IO_SUBSYSTEM_OPENSSL; 245 } 246 else if(SPDY_IO_SUBSYSTEM_RAW & io_subsystem) 247 { 248 SPDYF_raw_global_init(); 249 spdyf_io_initialized |= SPDY_IO_SUBSYSTEM_RAW; 250 } 251 252 SPDYF_ASSERT(SPDY_IO_SUBSYSTEM_NONE != spdyf_io_initialized, 253 "SPDY_init could not find even one IO subsystem"); 254 255 return SPDY_YES; 256 } 257 258 259 void 260 SPDY_deinit () 261 { 262 SPDYF_ASSERT(SPDY_IO_SUBSYSTEM_NONE != spdyf_io_initialized, 263 "SPDY_init has not been called!"); 264 265 if(SPDY_IO_SUBSYSTEM_OPENSSL & spdyf_io_initialized) 266 SPDYF_openssl_global_deinit(); 267 else if(SPDY_IO_SUBSYSTEM_RAW & spdyf_io_initialized) 268 SPDYF_raw_global_deinit(); 269 270 spdyf_io_initialized = SPDY_IO_SUBSYSTEM_NONE; 271 } 272 273 274 void 275 SPDY_run (struct SPDY_Daemon *daemon) 276 { 277 if(NULL == daemon) 278 { 279 SPDYF_DEBUG("daemon is NULL"); 280 return; 281 } 282 283 SPDYF_run(daemon); 284 } 285 286 287 int 288 SPDY_get_timeout (struct SPDY_Daemon *daemon, 289 unsigned long long *timeout) 290 { 291 if(NULL == daemon) 292 { 293 SPDYF_DEBUG("daemon is NULL"); 294 return SPDY_INPUT_ERROR; 295 } 296 297 return SPDYF_get_timeout(daemon,timeout); 298 } 299 300 301 int 302 SPDY_get_fdset (struct SPDY_Daemon *daemon, 303 fd_set *read_fd_set, 304 fd_set *write_fd_set, 305 fd_set *except_fd_set) 306 { 307 if(NULL == daemon 308 || NULL == read_fd_set 309 || NULL == write_fd_set 310 || NULL == except_fd_set) 311 { 312 SPDYF_DEBUG("a parameter is NULL"); 313 return SPDY_INPUT_ERROR; 314 } 315 316 return SPDYF_get_fdset(daemon, 317 read_fd_set, 318 write_fd_set, 319 except_fd_set, 320 false); 321 } 322 323 324 struct SPDY_Daemon * 325 SPDY_start_daemon (uint16_t port, 326 const char *certfile, 327 const char *keyfile, 328 SPDY_NewSessionCallback nscb, 329 SPDY_SessionClosedCallback sccb, 330 SPDY_NewRequestCallback nrcb, 331 SPDY_NewDataCallback npdcb, 332 void * cls, 333 ...) 334 { 335 struct SPDY_Daemon *daemon; 336 va_list valist; 337 338 if(SPDY_IO_SUBSYSTEM_NONE == spdyf_io_initialized) 339 { 340 SPDYF_DEBUG("library not initialized"); 341 return NULL; 342 } 343 /* 344 * for now make this checks in framing layer 345 if(NULL == certfile) 346 { 347 SPDYF_DEBUG("certfile is NULL"); 348 return NULL; 349 } 350 if(NULL == keyfile) 351 { 352 SPDYF_DEBUG("keyfile is NULL"); 353 return NULL; 354 } 355 */ 356 357 va_start(valist, cls); 358 daemon = SPDYF_start_daemon_va ( port, 359 certfile, 360 keyfile, 361 nscb, 362 sccb, 363 nrcb, 364 npdcb, 365 &spdy_handler_new_stream, 366 &spdy_handler_new_data, 367 cls, 368 NULL, 369 valist 370 ); 371 va_end(valist); 372 373 return daemon; 374 } 375 376 377 void 378 SPDY_stop_daemon (struct SPDY_Daemon *daemon) 379 { 380 if(NULL == daemon) 381 { 382 SPDYF_DEBUG("daemon is NULL"); 383 return; 384 } 385 386 SPDYF_stop_daemon(daemon); 387 } 388 389 390 struct SPDY_Response * 391 SPDY_build_response(int status, 392 const char * statustext, 393 const char * version, 394 struct SPDY_NameValue * headers, 395 const void * data, 396 size_t size) 397 { 398 struct SPDY_Response *response = NULL; 399 struct SPDY_NameValue ** all_headers = NULL; //TODO maybe array in stack is enough 400 char *fullstatus = NULL; 401 int ret; 402 int num_hdr_containers = 1; 403 404 if(NULL == version) 405 { 406 SPDYF_DEBUG("version is NULL"); 407 return NULL; 408 } 409 410 if(NULL == (response = malloc(sizeof(struct SPDY_Response)))) 411 goto free_and_fail; 412 memset(response, 0, sizeof(struct SPDY_Response)); 413 414 if(NULL != headers && !SPDYF_name_value_is_empty(headers)) 415 num_hdr_containers = 2; 416 417 if(NULL == (all_headers = malloc(num_hdr_containers * sizeof(struct SPDY_NameValue *)))) 418 goto free_and_fail; 419 memset(all_headers, 0, num_hdr_containers * sizeof(struct SPDY_NameValue *)); 420 421 if(2 == num_hdr_containers) 422 all_headers[1] = headers; 423 424 if(NULL == (all_headers[0] = SPDY_name_value_create())) 425 goto free_and_fail; 426 427 if(NULL == statustext) 428 ret = asprintf(&fullstatus, "%i", status); 429 else 430 ret = asprintf(&fullstatus, "%i %s", status, statustext); 431 if(-1 == ret) 432 goto free_and_fail; 433 434 if(SPDY_YES != SPDY_name_value_add(all_headers[0], ":status", fullstatus)) 435 goto free_and_fail; 436 437 free(fullstatus); 438 fullstatus = NULL; 439 440 if(SPDY_YES != SPDY_name_value_add(all_headers[0], ":version", version)) 441 goto free_and_fail; 442 443 if(0 >= (response->headers_size = SPDYF_name_value_to_stream(all_headers, 444 num_hdr_containers, 445 &(response->headers)))) 446 goto free_and_fail; 447 448 SPDY_name_value_destroy(all_headers[0]); 449 free(all_headers); 450 all_headers = NULL; 451 452 if(size > 0) 453 { 454 //copy the data to the response object 455 if(NULL == (response->data = malloc(size))) 456 { 457 free(response->headers); 458 goto free_and_fail; 459 } 460 memcpy(response->data, data, size); 461 response->data_size = size; 462 } 463 464 return response; 465 466 //for GOTO 467 free_and_fail: 468 469 free(fullstatus); 470 if(NULL != all_headers) 471 SPDY_name_value_destroy(all_headers[0]); 472 free(all_headers); 473 free(response); 474 475 return NULL; 476 } 477 478 479 struct SPDY_Response * 480 SPDY_build_response_with_callback(int status, 481 const char * statustext, 482 const char * version, 483 struct SPDY_NameValue * headers, 484 SPDY_ResponseCallback rcb, 485 void *rcb_cls, 486 uint32_t block_size) 487 { 488 struct SPDY_Response *response; 489 490 if(NULL == rcb) 491 { 492 SPDYF_DEBUG("rcb is NULL"); 493 return NULL; 494 } 495 if(block_size > SPDY_MAX_SUPPORTED_FRAME_SIZE) 496 { 497 SPDYF_DEBUG("block_size is wrong"); 498 return NULL; 499 } 500 501 if(0 == block_size) 502 block_size = SPDY_MAX_SUPPORTED_FRAME_SIZE; 503 504 response = SPDY_build_response(status, 505 statustext, 506 version, 507 headers, 508 NULL, 509 0); 510 511 if(NULL == response) 512 { 513 return NULL; 514 } 515 516 response->rcb = rcb; 517 response->rcb_cls = rcb_cls; 518 response->rcb_block_size = block_size; 519 520 return response; 521 } 522 523 524 int 525 SPDY_queue_response (struct SPDY_Request * request, 526 struct SPDY_Response *response, 527 bool closestream, 528 bool consider_priority, 529 SPDY_ResponseResultCallback rrcb, 530 void * rrcb_cls) 531 { 532 struct SPDYF_Response_Queue *headers_to_queue; 533 struct SPDYF_Response_Queue *body_to_queue; 534 SPDYF_ResponseQueueResultCallback frqcb = NULL; 535 void *frqcb_cls = NULL; 536 int int_consider_priority = consider_priority ? SPDY_YES : SPDY_NO; 537 538 if(NULL == request) 539 { 540 SPDYF_DEBUG("request is NULL"); 541 return SPDY_INPUT_ERROR; 542 } 543 if(NULL == response) 544 { 545 SPDYF_DEBUG("request is NULL"); 546 return SPDY_INPUT_ERROR; 547 } 548 549 if(request->stream->is_out_closed 550 || SPDY_SESSION_STATUS_CLOSING == request->stream->session->status) 551 return SPDY_NO; 552 553 if(NULL != rrcb) 554 { 555 frqcb_cls = request; 556 frqcb = &spdy_handler_response_queue_result; 557 } 558 559 if(response->data_size > 0) 560 { 561 //SYN_REPLY and DATA will be queued 562 563 if(NULL == (headers_to_queue = SPDYF_response_queue_create(false, 564 response->headers, 565 response->headers_size, 566 response, 567 request->stream, 568 false, 569 NULL, 570 NULL, 571 NULL, 572 NULL))) 573 { 574 return SPDY_NO; 575 } 576 577 if(NULL == (body_to_queue = SPDYF_response_queue_create(true, 578 response->data, 579 response->data_size, 580 response, 581 request->stream, 582 closestream, 583 frqcb, 584 frqcb_cls, 585 rrcb, 586 rrcb_cls))) 587 { 588 SPDYF_response_queue_destroy(headers_to_queue); 589 return SPDY_NO; 590 } 591 592 SPDYF_queue_response (headers_to_queue, 593 request->stream->session, 594 int_consider_priority); 595 596 SPDYF_queue_response (body_to_queue, 597 request->stream->session, 598 int_consider_priority); 599 } 600 else if(NULL == response->rcb) 601 { 602 //no "body" will be queued, e.g. HTTP 404 without body 603 604 if(NULL == (headers_to_queue = SPDYF_response_queue_create(false, 605 response->headers, 606 response->headers_size, 607 response, 608 request->stream, 609 closestream, 610 frqcb, 611 frqcb_cls, 612 rrcb, 613 rrcb_cls))) 614 { 615 return SPDY_NO; 616 } 617 618 SPDYF_queue_response (headers_to_queue, 619 request->stream->session, 620 int_consider_priority); 621 } 622 else 623 { 624 //response with callbacks 625 626 if(NULL == (headers_to_queue = SPDYF_response_queue_create(false, 627 response->headers, 628 response->headers_size, 629 response, 630 request->stream, 631 false, 632 NULL, 633 NULL, 634 NULL, 635 NULL))) 636 { 637 return SPDY_NO; 638 } 639 640 if(NULL == (body_to_queue = SPDYF_response_queue_create(true, 641 response->data, 642 response->data_size, 643 response, 644 request->stream, 645 closestream, 646 frqcb, 647 frqcb_cls, 648 rrcb, 649 rrcb_cls))) 650 { 651 SPDYF_response_queue_destroy(headers_to_queue); 652 return SPDY_NO; 653 } 654 655 SPDYF_queue_response (headers_to_queue, 656 request->stream->session, 657 int_consider_priority); 658 659 SPDYF_queue_response (body_to_queue, 660 request->stream->session, 661 int_consider_priority); 662 } 663 664 return SPDY_YES; 665 } 666 667 668 socklen_t 669 SPDY_get_remote_addr(struct SPDY_Session * session, 670 struct sockaddr ** addr) 671 { 672 if(NULL == session) 673 { 674 SPDYF_DEBUG("session is NULL"); 675 return 0; 676 } 677 678 *addr = session->addr; 679 680 return session->addr_len; 681 } 682 683 684 struct SPDY_Session * 685 SPDY_get_session_for_request(const struct SPDY_Request * request) 686 { 687 if(NULL == request) 688 { 689 SPDYF_DEBUG("request is NULL"); 690 return NULL; 691 } 692 693 return request->stream->session; 694 } 695 696 697 void * 698 SPDY_get_cls_from_session(struct SPDY_Session * session) 699 { 700 if(NULL == session) 701 { 702 SPDYF_DEBUG("session is NULL"); 703 return NULL; 704 } 705 706 return session->user_cls; 707 } 708 709 710 void 711 SPDY_set_cls_to_session(struct SPDY_Session * session, 712 void * cls) 713 { 714 if(NULL == session) 715 { 716 SPDYF_DEBUG("session is NULL"); 717 return; 718 } 719 720 session->user_cls = cls; 721 } 722 723 724 void * 725 SPDY_get_cls_from_request(struct SPDY_Request * request) 726 { 727 if(NULL == request) 728 { 729 SPDYF_DEBUG("request is NULL"); 730 return NULL; 731 } 732 733 return request->user_cls; 734 } 735 736 737 void 738 SPDY_set_cls_to_request(struct SPDY_Request * request, 739 void * cls) 740 { 741 if(NULL == request) 742 { 743 SPDYF_DEBUG("request is NULL"); 744 return; 745 } 746 747 request->user_cls = cls; 748 } 749