UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <errno.h> 32 33 #include "../public/nsapi.h" 34 35 #include "sessionhandler.h" 36 #include "httprequest.h" 37 #include "httpparser.h" 38 #include "log.h" 39 #include "error.h" 40 #include "httplistener.h" 41 42 struct EventHttpIO { 43 HTTPRequest *request; 44 HttpParser *parser; 45 EVWatchList watch; 46 Event *io_event; 47 int error; 48 }; 49 50 51 int connection_read(Connection *conn, void *buf, int len) { 52 return (int)read(conn->fd, buf, len); 53 } 54 55 int connection_write(Connection *conn, const void *buf, int len) { 56 return (int)write(conn->fd, buf, len); 57 } 58 59 void connection_close(Connection *conn) { 60 while(close(conn->fd)) { 61 if(errno != EINTR) { 62 log_ereport(LOG_VERBOSE, "connection close failed: %s", strerror(errno)); 63 break; 64 } 65 log_ereport(LOG_VERBOSE, "connection close: EINTR"); 66 } 67 } 68 69 int connection_ssl_read(Connection *conn, void *buf, int len) { 70 int ret = SSL_read(conn->ssl, buf, len); 71 if(ret <= 0) { 72 conn->ssl_error = SSL_get_error(conn->ssl, ret); 73 } 74 return ret; 75 } 76 77 int connection_ssl_write(Connection *conn, const void *buf, int len) { 78 int ret = SSL_write(conn->ssl, buf, len); 79 if(ret <= 0) { 80 conn->ssl_error = SSL_get_error(conn->ssl, ret); 81 } 82 return ret; 83 } 84 85 void connection_ssl_close(Connection *conn) { 86 if(!conn->ssl_error) { 87 int ret = SSL_shutdown(conn->ssl); 88 if(ret != 1) { 89 conn->ssl_error = SSL_get_error(conn->ssl, ret); 90 log_ereport(LOG_VERBOSE, "SSL_shutdown failed: %d", conn->ssl_error); 91 } 92 } 93 while(close(conn->fd)) { 94 if(errno != EINTR) { 95 log_ereport(LOG_VERBOSE, "connection close failed: %s", strerror(errno)); 96 break; 97 } 98 log_ereport(LOG_VERBOSE, "connection close: EINTR"); 99 } 100 } 101 102 void connection_destroy(Connection *conn) { 103 log_ereport(LOG_DEBUG, "trace reqid: %016llx connection_destroy", (unsigned long long int)conn->id); 104 cfg_unref(conn->listener->cfg); 105 conn->close(conn); 106 if(conn->ssl) { 107 SSL_free(conn->ssl); 108 } 109 free(conn); 110 } 111 112 IOStream* create_connection_iostream( 113 SessionHandler *sh, 114 Connection *conn, 115 pool_handle_t *pool, 116 WSBool *ssl) 117 { 118 IOStream *io = NULL; 119 if(conn->ssl) { 120 io = sslstream_new(pool, conn->ssl); 121 *ssl = 1; 122 } else { 123 io = Sysstream_new(pool, conn->fd); 124 *ssl = 0; 125 } 126 return io; 127 } 128 129 130 SessionHandler* create_basic_session_handler(pool_handle_t *pool) { 131 BasicSessionHandler *handler = pool_malloc(pool, sizeof(BasicSessionHandler)); 132 handler->threadpool = threadpool_new(4, 8); 133 threadpool_start(handler->threadpool); // TODO: handle error 134 handler->sh.enqueue_connection = basic_enq_conn; 135 handler->sh.keep_alive = basic_keep_alive; 136 handler->sh.create_iostream = create_connection_iostream; 137 138 return (SessionHandler*)handler; 139 } 140 141 void basic_enq_conn(SessionHandler *handler, Connection *conn) { 142 BasicSessionHandler *sh = (BasicSessionHandler*)handler; 143 conn->session_handler = handler; 144 threadpool_run(sh->threadpool, basic_run_session, conn); 145 } 146 147 void* basic_run_session(void *data) { 148 Connection *conn = (Connection*)data; 149 150 HTTPRequest *request = malloc(sizeof(HTTPRequest)); 151 http_request_init(request); 152 request->connection = conn; 153 154 // read request 155 netbuf *buf = malloc(sizeof(netbuf)); 156 buf->rdtimeout = 120; 157 buf->pos = 0; 158 buf->cursize = 0; 159 buf->maxsize = 2048; 160 buf->sd = &conn->fd; 161 buf->inbuf = malloc(2048); 162 buf->errmsg = NULL; 163 164 request->netbuf = buf; 165 166 HttpParser *parser = http_parser_new(request); 167 int state; 168 int r; 169 r = conn->read(conn, buf->inbuf + buf->pos, buf->maxsize - buf->pos); 170 171 if(r > 0) { 172 int err = 0; 173 buf->cursize += r; 174 while((state = http_parser_process(parser)) != 0) { 175 if(state == 2) { 176 log_ereport(LOG_FAILURE, "basic_run_session: invalid http request"); 177 err = 1; 178 break; 179 } 180 r = conn->read(conn, buf->inbuf + buf->pos, buf->maxsize - buf->pos); 181 if(r == -1) { 182 log_ereport(LOG_FAILURE, "basic_run_session: IO error: %s", strerror(errno)); 183 err = 1; 184 break; 185 } 186 buf->cursize += r; 187 } 188 189 if(!err) { 190 if(http_parser_validate(parser)) { 191 // process request 192 r = handle_request(request, NULL, NULL); // TODO: use correct thread pool 193 } else { 194 log_ereport(LOG_FAILURE, "basic_run_session: http parser validation failed"); 195 fatal_error(request, 400); 196 } 197 } 198 } else { 199 log_ereport(LOG_FAILURE, "basic_run_session: IO error: %s", strerror(errno)); 200 } 201 202 free(buf->inbuf); 203 free(buf); 204 connection_destroy(conn); 205 http_parser_free(parser); 206 http_request_cleanup(request); 207 208 return NULL; 209 } 210 211 void basic_keep_alive(SessionHandler *handler, Connection *conn) { 212 connection_destroy(conn); 213 } 214 215 216 /* ----- event session handler ----- */ 217 218 SessionHandler* create_event_session_handler(pool_handle_t *pool) { 219 EventSessionHandler *handler = pool_malloc(pool, sizeof(EventSessionHandler)); 220 handler->eventhandler = get_default_event_handler(); 221 handler->sh.enqueue_connection = evt_enq_conn; 222 handler->sh.keep_alive = evt_keep_alive; 223 handler->sh.create_iostream = create_connection_iostream; 224 return (SessionHandler*)handler; 225 } 226 227 void evt_request_timeout(EventHandler *h, EVWatchList *item) { 228 log_ereport(LOG_VERBOSE, "sessionhandler: request timeout"); 229 item->intdata = 0; 230 231 EventHttpIO *io = item->data1; 232 io->error = 4; 233 234 log_ereport(LOG_DEBUG, "trace reqid: %016llx request timeout", (unsigned long long int)io->request->connection->id); 235 236 if(ev_remove_poll(h, io->request->connection->fd)) { 237 log_ereport(LOG_FAILURE, "sessionhandler: request timeout: cannot remove poll"); 238 } 239 evt_request_error(h, io->io_event); 240 } 241 242 int evt_add_request(EventHandler *h, Event *event) { 243 EventHttpIO *io = event->cookie; 244 Connection *conn = io->request->connection; 245 246 if(ev_pollin(h, conn->fd, io->io_event) != 0) { 247 // TODO: ev_pollin should log, intercept some errors here 248 log_ereport(LOG_FAILURE, "Cannot enqueue connection"); 249 evt_request_error(h, event); 250 } else { 251 // add request timeout 252 io->watch.intdata = 1; 253 io->watch.created = time(NULL); 254 io->watch.expire = io->watch.created + 240; // TODO: config 255 io->watch.destroy = evt_request_timeout; 256 io->watch.data1 = io; 257 ev_watchlist_add(h, &io->watch); 258 } 259 260 return 0; 261 } 262 263 void evt_enq_conn(SessionHandler *handler, Connection *conn) { 264 log_ereport(LOG_DEBUG, "trace reqid: %016llx enqueue connection", (unsigned long long int)conn->id); 265 266 Event *start_request = malloc(sizeof(Event)); 267 if(!start_request) { 268 connection_destroy(conn); 269 return; 270 } 271 272 Event *event = malloc(sizeof(Event)); 273 if(!event) { 274 connection_destroy(conn); 275 free(start_request); 276 return; 277 } 278 279 EventHttpIO *io = evt_req_init(handler, conn); 280 if(!io) { 281 log_ereport(LOG_DEBUG, "trace reqid: %016llx connection destroyed | evt_req_init failed", (unsigned long long int)conn->id); 282 log_ereport(LOG_DEBUG, "trace reqid: %016llx free event", (unsigned long long int)conn->id); 283 connection_destroy(conn); 284 free(start_request); 285 free(event); 286 return; 287 } 288 289 ZERO(event, sizeof(Event)); 290 event->fn = conn->ssl && !conn->ssl_accepted ? evt_request_ssl_accept : evt_request_input; 291 event->finish = evt_request_finish; 292 event->cookie = io; 293 io->io_event = event; 294 295 /* 296 * to start the request handling, switch to the event handler 297 * 298 * evt_enq_conn() --> event handler --> handle_request() 299 */ 300 301 EventHandler *ev = ev_instance(((EventSessionHandler*)handler)->eventhandler); 302 303 ZERO(start_request, sizeof(Event)); 304 start_request->cookie = io; 305 start_request->fn = evt_add_request; 306 start_request->finish = ev_free_event; 307 start_request->error = 0; 308 if(event_send(ev, start_request)) { 309 log_ereport(LOG_DEBUG, "trace reqid: %016llx connection destroyed | event_send failed", (unsigned long long int)conn->id); 310 log_ereport(LOG_FAILURE, "Cannot start request timeout: event_send failed"); 311 evt_request_error(ev, event); 312 free(start_request); 313 } 314 } 315 316 EventHttpIO* evt_req_init(SessionHandler *handler, Connection *conn) { 317 // set socket non blocking 318 int flags; 319 if ((flags = fcntl(conn->fd, F_GETFL, 0)) == -1) { 320 flags = 0; 321 } 322 if (fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK) != 0) { 323 log_ereport(LOG_FAILURE, "sessionhandler: fcntl failed: %s", strerror(errno)); 324 return NULL; 325 } 326 327 HTTPRequest *request = malloc(sizeof(HTTPRequest)); 328 if(!request) { 329 return NULL; 330 } 331 http_request_init(request); 332 request->connection = conn; 333 conn->session_handler = handler; 334 335 // TODO: remove code redundancy (basic_run_session) 336 337 // read request 338 netbuf *buf = malloc(sizeof(netbuf)); 339 if(!buf) { 340 http_request_cleanup(request); 341 return NULL; 342 } 343 buf->rdtimeout = 120; 344 buf->pos = 0; 345 buf->cursize = 0; 346 buf->maxsize = 2048; 347 buf->sd = &conn->fd; 348 buf->errmsg = NULL; 349 buf->inbuf = malloc(2048); 350 if(!buf->inbuf) { 351 http_request_cleanup(request); 352 free(buf); 353 return NULL; 354 } 355 356 request->netbuf = buf; 357 358 HttpParser *parser = http_parser_new(request); 359 if(!parser) { 360 http_request_cleanup(request); 361 free(buf->inbuf); 362 free(buf); 363 return NULL; 364 } 365 366 EventHttpIO *io = malloc(sizeof(EventHttpIO)); 367 if(io == NULL) { 368 http_request_cleanup(request); 369 free(buf->inbuf); 370 free(buf); 371 http_parser_free(parser); 372 return NULL; 373 } 374 io->request = request; 375 io->parser = parser; 376 io->error = 0; 377 ZERO(&io->watch, sizeof(EVWatchList)); 378 379 return io; 380 } 381 382 int evt_request_ssl_accept(EventHandler *handler, Event *event) { 383 EventHttpIO *io = event->cookie; 384 Connection *conn = io->request->connection; 385 386 log_ereport(LOG_DEBUG, "trace reqid: %016llx ssl accept", (unsigned long long int)conn->id); 387 388 int ret = SSL_accept(conn->ssl); 389 if(ret <= 0) { 390 log_ereport(LOG_DEBUG, "trace reqid: %016llx ssl accept | error", (unsigned long long int)conn->id); 391 int error = SSL_get_error(conn->ssl, ret); 392 char *errstr; 393 switch(error) { 394 default: errstr = "unknown"; break; 395 case SSL_ERROR_WANT_READ: { 396 event->events = EVENT_POLLIN; 397 return 1; 398 } 399 case SSL_ERROR_WANT_WRITE: { 400 event->events = EVENT_POLLOUT; 401 return 1; 402 } 403 case SSL_ERROR_ZERO_RETURN: errstr = "SSL_ERROR_ZERO_RETURN"; break; 404 case SSL_ERROR_WANT_CONNECT: errstr = "SSL_ERROR_WANT_CONNECT"; break; 405 case SSL_ERROR_WANT_ACCEPT: errstr = "SSL_ERROR_WANT_ACCEPT"; break; 406 case SSL_ERROR_WANT_X509_LOOKUP: errstr = "SSL_ERROR_WANT_X509_LOOKUP"; break; 407 case SSL_ERROR_SYSCALL: errstr = "SSL_ERROR_SYSCALL"; break; 408 case SSL_ERROR_SSL: errstr = "SSL_ERROR_SSL"; break; 409 } 410 log_ereport(LOG_VERBOSE, "SSL accept error[%d]: %s", error, errstr); 411 event->finish = evt_request_error; 412 io->error = 1; 413 return 0; 414 } 415 conn->ssl_accepted = WS_TRUE; 416 417 // SSL_accept successful, start request input now 418 event->fn = evt_request_input; 419 return evt_request_input(handler, event); 420 } 421 422 int evt_request_input(EventHandler *handler, Event *event) { 423 EventHttpIO *io = event->cookie; 424 HttpParser *parser = io->parser; 425 HTTPRequest *request = io->request; 426 Connection *conn = io->request->connection; 427 netbuf *buf = request->netbuf; 428 429 int state; 430 int r; 431 r = conn->read( 432 conn, 433 buf->inbuf + buf->pos, 434 buf->maxsize - buf->pos); 435 436 log_ereport(LOG_DEBUG, "trace reqid: %016llx request input | r=%d", (unsigned long long int)conn->id, r); 437 438 if(r <= 0) { 439 if(conn->ssl) { 440 // SSL specific error handling 441 switch(conn->ssl_error) { 442 case SSL_ERROR_WANT_READ: { 443 event->events = EVENT_POLLIN; 444 log_ereport(LOG_DEBUG, "trace reqid: %016llx request input | ssl want read", (unsigned long long int)conn->id); 445 return 1; 446 } 447 case SSL_ERROR_WANT_WRITE: { 448 event->events = EVENT_POLLOUT; 449 log_ereport(LOG_DEBUG, "trace reqid: %016llx request input | ssl want write", (unsigned long long int)conn->id); 450 return 1; 451 } 452 } 453 } 454 455 log_ereport(LOG_DEBUG, "trace reqid: %016llx request input | error", (unsigned long long int)conn->id); 456 457 event->finish = evt_request_error; 458 io->error = 1; 459 return 0; 460 } 461 //fwrite(buf->inbuf + buf->pos, 1, r, stdout); 462 //printf("\n"); 463 464 buf->cursize += r; 465 state = http_parser_process(parser); 466 if(state == 2) { 467 log_ereport(LOG_DEBUG, "trace reqid: %016llx request input | http parser error", (unsigned long long int)conn->id); 468 469 // parse error 470 fatal_error(request, 400); 471 log_ereport(LOG_VERBOSE, "http parser: bad request"); 472 //printf("\n\n%.*s\n\n", parser->request->netbuf->cursize, parser->request->netbuf->inbuf); 473 //fflush(stdout); 474 event->finish = evt_request_error; 475 io->error = 2; 476 return 0; 477 } else if(state == 1) { 478 /* 479 * we need more data -> return 1 to tell the event handler to 480 * continue polling 481 */ 482 log_ereport(LOG_DEBUG, "trace reqid: %016llx request input | event_pollin", (unsigned long long int)conn->id); 483 event->events = EVENT_POLLIN; 484 return 1; 485 } 486 487 // we are done with reading 488 489 // set socket blocking 490 int flags; 491 if (-1 == (flags = fcntl(request->connection->fd, F_GETFL, 0))) { 492 flags = 0; 493 } 494 if (fcntl(request->connection->fd, F_SETFL, flags & ~O_NONBLOCK) != 0) { 495 // just close the connection if fcntl fails 496 log_ereport(LOG_DEBUG, "trace reqid: %016llx request input | fcntl error", (unsigned long long int)conn->id); 497 event->finish = evt_request_error; 498 io->error = 3; 499 return 0; 500 } 501 502 if(!http_parser_validate(parser)) { 503 log_ereport(LOG_DEBUG, "trace reqid: %016llx request input | http parser validate error", (unsigned long long int)conn->id); 504 log_ereport(LOG_FAILURE, "http_parser_validate failed"); 505 fatal_error(request, 400); 506 event->finish = evt_request_error; 507 return 0; 508 } 509 510 /* 511 * process request 512 * 513 * We return 0 to finish request input. The event handler than stops 514 * polling and executes event->finish (evt_request_input_finish) 515 */ 516 return 0; 517 } 518 519 int evt_request_finish(EventHandler *h, Event *event) { 520 EventHttpIO *io = event->cookie; 521 HttpParser *parser = io->parser; 522 HTTPRequest *request = io->request; 523 524 log_ereport(LOG_DEBUG, "trace reqid: %016llx request finish", (unsigned long long int)request->connection->id); 525 uint64_t reqid = request->connection->id; 526 527 // remove timeout 528 if(io->watch.intdata) { 529 ev_watchlist_remove(h, &io->watch); 530 } 531 532 int r = handle_request(request, NULL, h); 533 if(r != 0) { 534 log_ereport(LOG_DEBUG, "trace reqid: %016llx request finish | handle_request failed", (unsigned long long int)request->connection->id); 535 connection_destroy(request->connection); 536 free(request->netbuf->inbuf); 537 free(request->netbuf); 538 } 539 540 /* 541 * handle_request can return before the request is finished, but it copies 542 * all important data. We can free request, parser and event 543 * 544 * don't free request->netbuf and request->connection 545 */ 546 http_request_cleanup(request); 547 http_parser_free(parser); 548 549 free(io); 550 free(event); 551 log_ereport(LOG_DEBUG, "trace reqid: %016llx free event", (unsigned long long int)reqid); 552 553 return 0; 554 } 555 556 int evt_request_error(EventHandler *h, Event *event) { 557 EventHttpIO *io = event->cookie; 558 HttpParser *parser = io->parser; 559 HTTPRequest *request = io->request; 560 uint64_t reqid = request->connection->id; 561 562 log_ereport(LOG_DEBUG, "trace reqid: %016llx request error", (unsigned long long int)request->connection->id); 563 564 if(event->error) { 565 log_ereport(LOG_VERBOSE, "sessionhandler http io error: %d fd: %d", io->error, request->connection->fd); 566 } 567 568 // remove timeout 569 if(io->watch.intdata) { 570 ev_watchlist_remove(h, &io->watch); 571 } 572 573 free(request->netbuf->inbuf); 574 free(request->netbuf); 575 576 connection_destroy(request->connection); 577 578 http_request_cleanup(request); 579 http_parser_free(parser); 580 581 free(io); 582 free(event); 583 log_ereport(LOG_DEBUG, "trace reqid: %016llx free event", (unsigned long long int)reqid); 584 585 return 0; 586 } 587 588 void evt_keep_alive(SessionHandler *handler, Connection *conn) { 589 log_ereport(LOG_DEBUG, "trace reqid: %016llx keep alive", (unsigned long long int)conn->id); 590 591 conn->id++; 592 Event *event = malloc(sizeof(Event)); 593 if(!event) { 594 connection_destroy(conn); 595 return; 596 } 597 598 ZERO(event, sizeof(Event)); 599 event->fn = evt_keep_alive_enqueue; 600 event->finish = ev_free_event; // this will free the event obj at the end 601 event->cookie = conn; 602 603 EventHandler *ev = ev_instance(((EventSessionHandler*)handler)->eventhandler); 604 if(event_send(ev, event)) { 605 log_ereport(LOG_DEBUG, "trace reqid: %016llx connection destroyed | keep_alive event error", (unsigned long long int)conn->id); 606 log_ereport(LOG_FAILURE, "Keep-Alive: ev_send failed"); 607 connection_destroy(conn); 608 free(event); 609 } 610 } 611 612 int evt_keep_alive_enqueue(EventHandler *h, Event *event) { 613 Connection *conn = event->cookie; 614 615 EVWatchList *keepalive = malloc(sizeof(EVWatchList)); 616 if(!keepalive) { 617 connection_destroy(conn); 618 return 0; 619 } 620 621 Event *ioevent = malloc(sizeof(Event)); 622 if(!ioevent) { 623 connection_destroy(conn); 624 free(keepalive); 625 return 0; 626 } 627 628 // add keepalive object to the eventhandler watchlist 629 // the watchlist will check the timeout 630 ZERO(keepalive, sizeof(EVWatchList)); 631 keepalive->data1 = conn; 632 keepalive->data2 = ioevent; 633 keepalive->destroy = evt_keep_alive_destroy; 634 keepalive->created = time(NULL); 635 keepalive->expire = keepalive->created + 120; // TODO: config 636 ev_watchlist_add(h, keepalive); 637 638 log_ereport(LOG_DEBUG, "trace reqid: %016llx keep_alive add watch", (unsigned long long int)conn->id); 639 640 // wait for input 641 ZERO(ioevent, sizeof(Event)); 642 ioevent->fn = evt_keep_alive_input_event; 643 ioevent->finish = ev_free_event; 644 ioevent->cookie = keepalive; 645 if(ev_pollin(h, conn->fd, ioevent) != 0) { 646 log_ereport(LOG_DEBUG, "trace reqid: %016llx connection destroyed | keep_alive_enqueue", (unsigned long long int)conn->id); 647 log_ereport(LOG_DEBUG, "trace reqid: %016llx keep_alive free watch", (unsigned long long int)conn->id); 648 log_ereport(LOG_FAILURE, "Cannot enqueue connection"); 649 ev_watchlist_remove(h, keepalive); 650 connection_destroy(conn); 651 free(keepalive); 652 free(ioevent); 653 } 654 655 return 0; 656 } 657 658 int evt_keep_alive_input_event(EventHandler *h, Event *event) { 659 EVWatchList *keepalive = event->cookie; 660 Connection *conn = keepalive->data1; 661 662 // remove connection from the keep-alive list 663 ev_watchlist_remove(h, keepalive); 664 log_ereport(LOG_DEBUG, "trace reqid: %016llx keep_alive free watch", (unsigned long long int)conn->id); 665 free(keepalive); 666 667 // prepare http io 668 EventHttpIO *io = evt_req_init(conn->session_handler, conn); 669 if(!io) { 670 log_ereport(LOG_DEBUG, "trace reqid: %016llx connection destroyed | keep alive input", (unsigned long long int)conn->id); 671 connection_destroy(conn); 672 return 0; 673 } 674 675 // pass this event to the request input function 676 // the event object needs some adjustments for this (see evt_enq_conn) 677 event->cookie = io; 678 event->fn = conn->ssl && !conn->ssl_accepted ? evt_request_ssl_accept : evt_request_input; 679 event->finish = evt_request_finish; 680 return event->fn(h, event); 681 } 682 683 void evt_keep_alive_destroy(EventHandler *h, EVWatchList *item) { 684 Connection *conn = item->data1; 685 Event *ioevent = item->data2; 686 log_ereport(LOG_DEBUG, "sessionhandler: keep-alive timeout: close connection"); 687 688 if(ev_remove_poll(h, conn->fd)) { 689 log_ereport(LOG_FAILURE, "sessionhandler: keep-alive timeout: cannot remove poll"); 690 } 691 692 log_ereport(LOG_DEBUG, "trace reqid: %016llx keep_alive timeout", (unsigned long long int)conn->id); 693 log_ereport(LOG_DEBUG, "trace reqid: %016llx keep_alive free watch", (unsigned long long int)conn->id); 694 connection_destroy(conn); 695 free(ioevent); 696 free(item); 697 } 698