1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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);
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
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
192 r = handle_request(request,
NULL,
NULL);
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
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
248 log_ereport(
LOG_FAILURE,
"Cannot enqueue connection");
249 evt_request_error(h, event);
250 }
else {
251
252 io->watch.intdata =
1;
253 io->watch.created = time(
NULL);
254 io->watch.expire = io->watch.created +
240;
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
297
298
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
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
336
337
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
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
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
462
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
470 fatal_error(request,
400);
471 log_ereport(
LOG_VERBOSE,
"http parser: bad request");
472
473
474 event->finish = evt_request_error;
475 io->error =
2;
476 return 0;
477 }
else if(state ==
1) {
478
479
480
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
488
489
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
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
512
513
514
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
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
542
543
544
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
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;
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
629
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;
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
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
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
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
676
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