00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00025 #include "platform.h"
00026 #include "applicationlayer.h"
00027 #include "alstructures.h"
00028 #include "structures.h"
00029 #include "internal.h"
00030 #include "daemon.h"
00031 #include "session.h"
00032
00033
00034 void
00035 spdy_callback_response_done(void *cls,
00036 struct SPDY_Response *response,
00037 struct SPDY_Request *request,
00038 enum SPDY_RESPONSE_RESULT status,
00039 bool streamopened)
00040 {
00041 (void)cls;
00042 (void)status;
00043 (void)streamopened;
00044
00045 SPDY_destroy_request(request);
00046 SPDY_destroy_response(response);
00047 }
00048
00049
00058 static int
00059 spdy_handler_new_stream (void *cls,
00060 struct SPDYF_Stream * stream)
00061 {
00062 (void)cls;
00063 unsigned int i;
00064 char *method = NULL;
00065 char *path = NULL;
00066 char *version = NULL;
00067 char *host = NULL;
00068 char *scheme = NULL;
00069 struct SPDY_Request * request = NULL;
00070 struct SPDY_NameValue * headers = NULL;
00071 struct SPDY_NameValue * iterator = stream->headers;
00072 struct SPDY_Daemon *daemon;
00073
00074 daemon = stream->session->daemon;
00075
00076
00077 if(NULL == daemon->new_request_cb)
00078 return SPDY_YES;
00079
00080 if(NULL == (headers=SPDY_name_value_create()))
00081 goto free_and_fail;
00082
00083 if(NULL==(request = malloc(sizeof(struct SPDY_Request))))
00084 goto free_and_fail;
00085
00086 memset(request, 0, sizeof(struct SPDY_Request));
00087 request->stream = stream;
00088
00089
00090
00091 while(iterator != NULL)
00092 {
00093 if(strcmp(":method",iterator->name) == 0)
00094 {
00095 if(1 != iterator->num_values)
00096 break;
00097 method = iterator->value[0];
00098 }
00099 else if(strcmp(":path",iterator->name) == 0)
00100 {
00101 if(1 != iterator->num_values)
00102 break;
00103 path = iterator->value[0];
00104 }
00105 else if(strcmp(":version",iterator->name) == 0)
00106 {
00107 if(1 != iterator->num_values)
00108 break;
00109 version = iterator->value[0];
00110 }
00111 else if(strcmp(":host",iterator->name) == 0)
00112 {
00113
00114 if(1 != iterator->num_values)
00115 break;
00116 host = iterator->value[0];
00117 }
00118 else if(strcmp(":scheme",iterator->name) == 0)
00119 {
00120 if(1 != iterator->num_values)
00121 break;
00122 scheme = iterator->value[0];
00123 }
00124 else
00125 for(i=0; i<iterator->num_values; ++i)
00126 if (SPDY_YES != SPDY_name_value_add(headers,iterator->name,iterator->value[i]))
00127 {
00128 SPDY_destroy_request(request);
00129 goto free_and_fail;
00130 }
00131
00132 iterator = iterator->next;
00133 }
00134
00135 request->method=method;
00136 request->path=path;
00137 request->version=version;
00138 request->host=host;
00139 request->scheme=scheme;
00140 request->headers=headers;
00141
00142
00143 if(NULL == method || strlen(method) == 0
00144 || NULL == path || strlen(path) == 0
00145 || NULL == version || strlen(version) == 0
00146 || NULL == host || strlen(host) == 0
00147 || NULL == scheme || strlen(scheme) == 0
00148 )
00149 {
00150
00151
00152 SPDYF_DEBUG("Bad request");
00153
00154 SPDY_destroy_request(request);
00155
00156 return SPDY_YES;
00157 }
00158
00159
00160 daemon->new_request_cb(daemon->cls,
00161 request,
00162 stream->priority,
00163 method,
00164 path,
00165 version,
00166 host,
00167 scheme,
00168 headers,
00169 !stream->is_in_closed);
00170
00171 stream->cls = request;
00172
00173 return SPDY_YES;
00174
00175
00176 free_and_fail:
00177
00178 SPDY_name_value_destroy(headers);
00179 return SPDY_NO;
00180 }
00181
00182
00186 static int
00187 spdy_handler_new_data (void * cls,
00188 struct SPDYF_Stream *stream,
00189 const void * buf,
00190 size_t size,
00191 bool more)
00192 {
00193 return stream->session->daemon->received_data_cb(cls, stream->cls, buf, size, more);
00194 }
00195
00196
00197
00211 static void
00212 spdy_handler_response_queue_result(void * cls,
00213 struct SPDYF_Response_Queue *response_queue,
00214 enum SPDY_RESPONSE_RESULT status)
00215 {
00216 int streamopened;
00217 struct SPDY_Request *request = (struct SPDY_Request *)cls;
00218
00219 SPDYF_ASSERT( ( (NULL == response_queue->data_frame) &&
00220 (NULL != response_queue->control_frame) ) ||
00221 ( (NULL != response_queue->data_frame) &&
00222 (NULL == response_queue->control_frame) ),
00223 "response queue must have either control frame or data frame");
00224
00225 streamopened = !response_queue->stream->is_out_closed;
00226
00227 response_queue->rrcb(response_queue->rrcb_cls, response_queue->response, request, status, streamopened);
00228 }
00229
00230
00231 int
00232 (SPDY_init) (enum SPDY_IO_SUBSYSTEM io_subsystem, ...)
00233 {
00234 SPDYF_ASSERT(SPDYF_BUFFER_SIZE >= SPDY_MAX_SUPPORTED_FRAME_SIZE,
00235 "Buffer size is less than max supported frame size!");
00236 SPDYF_ASSERT(SPDY_MAX_SUPPORTED_FRAME_SIZE >= 32,
00237 "Max supported frame size must be bigger than the minimal value!");
00238 SPDYF_ASSERT(SPDY_IO_SUBSYSTEM_NONE == spdyf_io_initialized,
00239 "SPDY_init must be called only once per program or after SPDY_deinit");
00240
00241 if(SPDY_IO_SUBSYSTEM_OPENSSL & io_subsystem)
00242 {
00243 SPDYF_openssl_global_init();
00244 spdyf_io_initialized |= SPDY_IO_SUBSYSTEM_OPENSSL;
00245 }
00246 else if(SPDY_IO_SUBSYSTEM_RAW & io_subsystem)
00247 {
00248 SPDYF_raw_global_init();
00249 spdyf_io_initialized |= SPDY_IO_SUBSYSTEM_RAW;
00250 }
00251
00252 SPDYF_ASSERT(SPDY_IO_SUBSYSTEM_NONE != spdyf_io_initialized,
00253 "SPDY_init could not find even one IO subsystem");
00254
00255 return SPDY_YES;
00256 }
00257
00258
00259 void
00260 SPDY_deinit ()
00261 {
00262 SPDYF_ASSERT(SPDY_IO_SUBSYSTEM_NONE != spdyf_io_initialized,
00263 "SPDY_init has not been called!");
00264
00265 if(SPDY_IO_SUBSYSTEM_OPENSSL & spdyf_io_initialized)
00266 SPDYF_openssl_global_deinit();
00267 else if(SPDY_IO_SUBSYSTEM_RAW & spdyf_io_initialized)
00268 SPDYF_raw_global_deinit();
00269
00270 spdyf_io_initialized = SPDY_IO_SUBSYSTEM_NONE;
00271 }
00272
00273
00274 void
00275 SPDY_run (struct SPDY_Daemon *daemon)
00276 {
00277 if(NULL == daemon)
00278 {
00279 SPDYF_DEBUG("daemon is NULL");
00280 return;
00281 }
00282
00283 SPDYF_run(daemon);
00284 }
00285
00286
00287 int
00288 SPDY_get_timeout (struct SPDY_Daemon *daemon,
00289 unsigned long long *timeout)
00290 {
00291 if(NULL == daemon)
00292 {
00293 SPDYF_DEBUG("daemon is NULL");
00294 return SPDY_INPUT_ERROR;
00295 }
00296
00297 return SPDYF_get_timeout(daemon,timeout);
00298 }
00299
00300
00301 int
00302 SPDY_get_fdset (struct SPDY_Daemon *daemon,
00303 fd_set *read_fd_set,
00304 fd_set *write_fd_set,
00305 fd_set *except_fd_set)
00306 {
00307 if(NULL == daemon
00308 || NULL == read_fd_set
00309 || NULL == write_fd_set
00310 || NULL == except_fd_set)
00311 {
00312 SPDYF_DEBUG("a parameter is NULL");
00313 return SPDY_INPUT_ERROR;
00314 }
00315
00316 return SPDYF_get_fdset(daemon,
00317 read_fd_set,
00318 write_fd_set,
00319 except_fd_set,
00320 false);
00321 }
00322
00323
00324 struct SPDY_Daemon *
00325 SPDY_start_daemon (uint16_t port,
00326 const char *certfile,
00327 const char *keyfile,
00328 SPDY_NewSessionCallback nscb,
00329 SPDY_SessionClosedCallback sccb,
00330 SPDY_NewRequestCallback nrcb,
00331 SPDY_NewDataCallback npdcb,
00332 void * cls,
00333 ...)
00334 {
00335 struct SPDY_Daemon *daemon;
00336 va_list valist;
00337
00338 if(SPDY_IO_SUBSYSTEM_NONE == spdyf_io_initialized)
00339 {
00340 SPDYF_DEBUG("library not initialized");
00341 return NULL;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 va_start(valist, cls);
00358 daemon = SPDYF_start_daemon_va ( port,
00359 certfile,
00360 keyfile,
00361 nscb,
00362 sccb,
00363 nrcb,
00364 npdcb,
00365 &spdy_handler_new_stream,
00366 &spdy_handler_new_data,
00367 cls,
00368 NULL,
00369 valist
00370 );
00371 va_end(valist);
00372
00373 return daemon;
00374 }
00375
00376
00377 void
00378 SPDY_stop_daemon (struct SPDY_Daemon *daemon)
00379 {
00380 if(NULL == daemon)
00381 {
00382 SPDYF_DEBUG("daemon is NULL");
00383 return;
00384 }
00385
00386 SPDYF_stop_daemon(daemon);
00387 }
00388
00389
00390 struct SPDY_Response *
00391 SPDY_build_response(int status,
00392 const char * statustext,
00393 const char * version,
00394 struct SPDY_NameValue * headers,
00395 const void * data,
00396 size_t size)
00397 {
00398 struct SPDY_Response *response = NULL;
00399 struct SPDY_NameValue ** all_headers = NULL;
00400 char *fullstatus = NULL;
00401 int ret;
00402 int num_hdr_containers = 1;
00403
00404 if(NULL == version)
00405 {
00406 SPDYF_DEBUG("version is NULL");
00407 return NULL;
00408 }
00409
00410 if(NULL == (response = malloc(sizeof(struct SPDY_Response))))
00411 goto free_and_fail;
00412 memset(response, 0, sizeof(struct SPDY_Response));
00413
00414 if(NULL != headers && !SPDYF_name_value_is_empty(headers))
00415 num_hdr_containers = 2;
00416
00417 if(NULL == (all_headers = malloc(num_hdr_containers * sizeof(struct SPDY_NameValue *))))
00418 goto free_and_fail;
00419 memset(all_headers, 0, num_hdr_containers * sizeof(struct SPDY_NameValue *));
00420
00421 if(2 == num_hdr_containers)
00422 all_headers[1] = headers;
00423
00424 if(NULL == (all_headers[0] = SPDY_name_value_create()))
00425 goto free_and_fail;
00426
00427 if(NULL == statustext)
00428 ret = asprintf(&fullstatus, "%i", status);
00429 else
00430 ret = asprintf(&fullstatus, "%i %s", status, statustext);
00431 if(-1 == ret)
00432 goto free_and_fail;
00433
00434 if(SPDY_YES != SPDY_name_value_add(all_headers[0], ":status", fullstatus))
00435 goto free_and_fail;
00436
00437 free(fullstatus);
00438 fullstatus = NULL;
00439
00440 if(SPDY_YES != SPDY_name_value_add(all_headers[0], ":version", version))
00441 goto free_and_fail;
00442
00443 if(0 >= (response->headers_size = SPDYF_name_value_to_stream(all_headers,
00444 num_hdr_containers,
00445 &(response->headers))))
00446 goto free_and_fail;
00447
00448 SPDY_name_value_destroy(all_headers[0]);
00449 free(all_headers);
00450 all_headers = NULL;
00451
00452 if(size > 0)
00453 {
00454
00455 if(NULL == (response->data = malloc(size)))
00456 {
00457 free(response->headers);
00458 goto free_and_fail;
00459 }
00460 memcpy(response->data, data, size);
00461 response->data_size = size;
00462 }
00463
00464 return response;
00465
00466
00467 free_and_fail:
00468
00469 free(fullstatus);
00470 if(NULL != all_headers)
00471 SPDY_name_value_destroy(all_headers[0]);
00472 free(all_headers);
00473 free(response);
00474
00475 return NULL;
00476 }
00477
00478
00479 struct SPDY_Response *
00480 SPDY_build_response_with_callback(int status,
00481 const char * statustext,
00482 const char * version,
00483 struct SPDY_NameValue * headers,
00484 SPDY_ResponseCallback rcb,
00485 void *rcb_cls,
00486 uint32_t block_size)
00487 {
00488 struct SPDY_Response *response;
00489
00490 if(NULL == rcb)
00491 {
00492 SPDYF_DEBUG("rcb is NULL");
00493 return NULL;
00494 }
00495 if(block_size > SPDY_MAX_SUPPORTED_FRAME_SIZE)
00496 {
00497 SPDYF_DEBUG("block_size is wrong");
00498 return NULL;
00499 }
00500
00501 if(0 == block_size)
00502 block_size = SPDY_MAX_SUPPORTED_FRAME_SIZE;
00503
00504 response = SPDY_build_response(status,
00505 statustext,
00506 version,
00507 headers,
00508 NULL,
00509 0);
00510
00511 if(NULL == response)
00512 {
00513 return NULL;
00514 }
00515
00516 response->rcb = rcb;
00517 response->rcb_cls = rcb_cls;
00518 response->rcb_block_size = block_size;
00519
00520 return response;
00521 }
00522
00523
00524 int
00525 SPDY_queue_response (struct SPDY_Request * request,
00526 struct SPDY_Response *response,
00527 bool closestream,
00528 bool consider_priority,
00529 SPDY_ResponseResultCallback rrcb,
00530 void * rrcb_cls)
00531 {
00532 struct SPDYF_Response_Queue *headers_to_queue;
00533 struct SPDYF_Response_Queue *body_to_queue;
00534 SPDYF_ResponseQueueResultCallback frqcb = NULL;
00535 void *frqcb_cls = NULL;
00536 int int_consider_priority = consider_priority ? SPDY_YES : SPDY_NO;
00537
00538 if(NULL == request)
00539 {
00540 SPDYF_DEBUG("request is NULL");
00541 return SPDY_INPUT_ERROR;
00542 }
00543 if(NULL == response)
00544 {
00545 SPDYF_DEBUG("request is NULL");
00546 return SPDY_INPUT_ERROR;
00547 }
00548
00549 if(request->stream->is_out_closed
00550 || SPDY_SESSION_STATUS_CLOSING == request->stream->session->status)
00551 return SPDY_NO;
00552
00553 if(NULL != rrcb)
00554 {
00555 frqcb_cls = request;
00556 frqcb = &spdy_handler_response_queue_result;
00557 }
00558
00559 if(response->data_size > 0)
00560 {
00561
00562
00563 if(NULL == (headers_to_queue = SPDYF_response_queue_create(false,
00564 response->headers,
00565 response->headers_size,
00566 response,
00567 request->stream,
00568 false,
00569 NULL,
00570 NULL,
00571 NULL,
00572 NULL)))
00573 {
00574 return SPDY_NO;
00575 }
00576
00577 if(NULL == (body_to_queue = SPDYF_response_queue_create(true,
00578 response->data,
00579 response->data_size,
00580 response,
00581 request->stream,
00582 closestream,
00583 frqcb,
00584 frqcb_cls,
00585 rrcb,
00586 rrcb_cls)))
00587 {
00588 SPDYF_response_queue_destroy(headers_to_queue);
00589 return SPDY_NO;
00590 }
00591
00592 SPDYF_queue_response (headers_to_queue,
00593 request->stream->session,
00594 int_consider_priority);
00595
00596 SPDYF_queue_response (body_to_queue,
00597 request->stream->session,
00598 int_consider_priority);
00599 }
00600 else if(NULL == response->rcb)
00601 {
00602
00603
00604 if(NULL == (headers_to_queue = SPDYF_response_queue_create(false,
00605 response->headers,
00606 response->headers_size,
00607 response,
00608 request->stream,
00609 closestream,
00610 frqcb,
00611 frqcb_cls,
00612 rrcb,
00613 rrcb_cls)))
00614 {
00615 return SPDY_NO;
00616 }
00617
00618 SPDYF_queue_response (headers_to_queue,
00619 request->stream->session,
00620 int_consider_priority);
00621 }
00622 else
00623 {
00624
00625
00626 if(NULL == (headers_to_queue = SPDYF_response_queue_create(false,
00627 response->headers,
00628 response->headers_size,
00629 response,
00630 request->stream,
00631 false,
00632 NULL,
00633 NULL,
00634 NULL,
00635 NULL)))
00636 {
00637 return SPDY_NO;
00638 }
00639
00640 if(NULL == (body_to_queue = SPDYF_response_queue_create(true,
00641 response->data,
00642 response->data_size,
00643 response,
00644 request->stream,
00645 closestream,
00646 frqcb,
00647 frqcb_cls,
00648 rrcb,
00649 rrcb_cls)))
00650 {
00651 SPDYF_response_queue_destroy(headers_to_queue);
00652 return SPDY_NO;
00653 }
00654
00655 SPDYF_queue_response (headers_to_queue,
00656 request->stream->session,
00657 int_consider_priority);
00658
00659 SPDYF_queue_response (body_to_queue,
00660 request->stream->session,
00661 int_consider_priority);
00662 }
00663
00664 return SPDY_YES;
00665 }
00666
00667
00668 socklen_t
00669 SPDY_get_remote_addr(struct SPDY_Session * session,
00670 struct sockaddr ** addr)
00671 {
00672 if(NULL == session)
00673 {
00674 SPDYF_DEBUG("session is NULL");
00675 return 0;
00676 }
00677
00678 *addr = session->addr;
00679
00680 return session->addr_len;
00681 }
00682
00683
00684 struct SPDY_Session *
00685 SPDY_get_session_for_request(const struct SPDY_Request * request)
00686 {
00687 if(NULL == request)
00688 {
00689 SPDYF_DEBUG("request is NULL");
00690 return NULL;
00691 }
00692
00693 return request->stream->session;
00694 }
00695
00696
00697 void *
00698 SPDY_get_cls_from_session(struct SPDY_Session * session)
00699 {
00700 if(NULL == session)
00701 {
00702 SPDYF_DEBUG("session is NULL");
00703 return NULL;
00704 }
00705
00706 return session->user_cls;
00707 }
00708
00709
00710 void
00711 SPDY_set_cls_to_session(struct SPDY_Session * session,
00712 void * cls)
00713 {
00714 if(NULL == session)
00715 {
00716 SPDYF_DEBUG("session is NULL");
00717 return;
00718 }
00719
00720 session->user_cls = cls;
00721 }
00722
00723
00724 void *
00725 SPDY_get_cls_from_request(struct SPDY_Request * request)
00726 {
00727 if(NULL == request)
00728 {
00729 SPDYF_DEBUG("request is NULL");
00730 return NULL;
00731 }
00732
00733 return request->user_cls;
00734 }
00735
00736
00737 void
00738 SPDY_set_cls_to_request(struct SPDY_Request * request,
00739 void * cls)
00740 {
00741 if(NULL == request)
00742 {
00743 SPDYF_DEBUG("request is NULL");
00744 return;
00745 }
00746
00747 request->user_cls = cls;
00748 }