307
307
* html buffer. This is sometime needed with some applications
310
if (http_arg->retry_it > http_get_check->nb_get_retry-1) {
311
if (svr_checker_up(checker->id, checker->rs)) {
310
if (http_arg_obj->retry_it > http_get_check->nb_get_retry-1) {
311
if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
312
312
syslog(LOG_INFO, "Check on service [%s:%d] failed after %d retry."
313
, inet_ntop2(CHECKER_RIP(checker))
314
, ntohs(addr_port), http_arg->retry_it);
315
smtp_alert(thread->master, checker->rs, NULL, NULL,
313
, inet_ntop2(CHECKER_RIP(checker_obj))
314
, ntohs(addr_port), http_arg_obj->retry_it);
315
smtp_alert(checker_obj->rs, NULL, NULL,
317
317
"=> CHECK failed on service"
318
318
" : MD5 digest mismatch <=");
319
update_svr_checker_state(DOWN, checker->id
319
update_svr_checker_state(DOWN, checker_obj->id
324
324
/* Reset it counters */
325
http_arg->url_it = 0;
326
http_arg->retry_it = 0;
325
http_arg_obj->url_it = 0;
326
http_arg_obj->retry_it = 0;
329
329
/* register next timer thread */
330
330
switch (method) {
333
delay = checker->vs->delay_loop;
333
delay = checker_obj->vs->delay_loop;
336
336
http_get_check->delay_before_retry;
339
if (http_arg->url_it == 0 && http_arg->retry_it == 0)
340
delay = checker->vs->delay_loop;
339
if (http_arg_obj->url_it == 0 && http_arg_obj->retry_it == 0)
340
delay = checker_obj->vs->delay_loop;
342
342
delay = http_get_check->delay_before_retry;
351
351
FREE(req->buffer);
353
http_arg->req = NULL;
353
http_arg_obj->req = NULL;
354
close(thread_obj->u.fd);
357
357
/* Register next checker thread */
358
thread_add_timer(thread->master, http_connect_thread, checker, delay);
358
thread_add_timer(thread_obj->master, http_connect_thread, checker_obj, delay);
363
timeout_epilog(thread * thread, char *smtp_msg, char *debug_msg)
363
timeout_epilog(thread * thread_obj, char *smtp_msg, char *debug_msg)
365
checker *checker = THREAD_ARG(thread);
366
uint16_t addr_port = get_service_port(checker);
365
checker *checker_obj = THREAD_ARG(thread_obj);
366
uint16_t addr_port = get_service_port(checker_obj);
368
368
syslog(LOG_INFO, "Timeout %s server [%s:%d].",
370
, inet_ntop2(CHECKER_RIP(checker))
370
, inet_ntop2(CHECKER_RIP(checker_obj))
371
371
, ntohs(addr_port));
373
373
/* check if server is currently alive */
374
if (svr_checker_up(checker->id, checker->rs)) {
375
smtp_alert(thread->master, checker->rs, NULL, NULL,
374
if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
375
smtp_alert(checker_obj->rs, NULL, NULL,
376
376
"DOWN", smtp_msg);
377
update_svr_checker_state(DOWN, checker->id
377
update_svr_checker_state(DOWN, checker_obj->id
382
return epilog(thread, 1, 0, 0);
382
return epilog(thread_obj, 1, 0, 0);
385
385
/* return the url pointer of the current url iterator */
387
387
fetch_next_url(http_get_checker * http_get_check)
389
http_arg *http_arg = HTTP_ARG(http_get_check);
389
http_arg *http_arg_obj = HTTP_ARG(http_get_check);
391
return list_element(http_get_check->url, http_arg->url_it);
391
return list_element(http_get_check->url, http_arg_obj->url_it);
394
394
/* Handle response */
396
http_handle_response(thread * thread, unsigned char digest[16]
396
http_handle_response(thread * thread_obj, unsigned char digest[16]
397
397
, int empty_buffer)
399
checker *checker = THREAD_ARG(thread);
400
http_get_checker *http_get_check = CHECKER_ARG(checker);
401
http_arg *http_arg = HTTP_ARG(http_get_check);
402
REQ *req = HTTP_REQ(http_arg);
403
uint16_t addr_port = get_service_port(checker);
399
checker *checker_obj = THREAD_ARG(thread_obj);
400
http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
401
http_arg *http_arg_obj = HTTP_ARG(http_get_check);
402
REQ *req = HTTP_REQ(http_arg_obj);
403
uint16_t addr_port = get_service_port(checker_obj);
405
405
unsigned char *digest_tmp;
406
406
url *fetched_url = fetch_next_url(http_get_check);
408
408
/* First check if remote webserver returned data */
409
409
if (empty_buffer)
410
return timeout_epilog(thread, "=> CHECK failed on service"
410
return timeout_epilog(thread_obj, "=> CHECK failed on service"
411
411
" : empty buffer received <=\n\n",
412
412
"Read, no data received from ");
415
415
if (fetched_url->status_code) {
416
416
if (req->status_code != fetched_url->status_code) {
417
417
/* check if server is currently alive */
418
if (svr_checker_up(checker->id, checker->rs)) {
418
if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
420
420
"HTTP status code error to [%s:%d] url(%s)"
421
421
", status_code [%d].",
422
inet_ntop2(CHECKER_RIP(checker)),
422
inet_ntop2(CHECKER_RIP(checker_obj)),
423
423
ntohs(addr_port), fetched_url->path,
424
424
req->status_code);
425
smtp_alert(thread->master, checker->rs, NULL, NULL,
425
smtp_alert(checker_obj->rs, NULL, NULL,
427
427
"=> CHECK failed on service"
428
428
" : HTTP status code mismatch <=");
429
update_svr_checker_state(DOWN, checker->id
429
update_svr_checker_state(DOWN, checker_obj->id
433
433
DBG("HTTP Status_code to [%s:%d] url(%d) = [%d].",
434
inet_ntop2(CHECKER_RIP(checker))
434
inet_ntop2(CHECKER_RIP(checker_obj))
435
435
, ntohs(addr_port)
436
, http_arg->url_it + 1
436
, http_arg_obj->url_it + 1
437
437
, req->status_code);
439
439
* We set retry iterator to max value to not retry
440
440
* when service is already know as die.
442
http_arg->retry_it = http_get_check->nb_get_retry;
442
http_arg_obj->retry_it = http_get_check->nb_get_retry;
444
return epilog(thread, 2, 0, 1);
444
return epilog(thread_obj, 2, 0, 1);
446
if (!svr_checker_up(checker->id, checker->rs))
446
if (!svr_checker_up(checker_obj->id, checker_obj->rs))
448
448
"HTTP status code success to [%s:%d] url(%d).",
449
inet_ntop2(CHECKER_RIP(checker))
449
inet_ntop2(CHECKER_RIP(checker_obj))
450
450
, ntohs(addr_port)
451
, http_arg->url_it + 1);
452
return epilog(thread, 1, 1, 0) + 1;
451
, http_arg_obj->url_it + 1);
452
return epilog(thread_obj, 1, 1, 0) + 1;
466
466
/* check if server is currently alive */
467
if (svr_checker_up(checker->id, checker->rs)) {
467
if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
469
469
"MD5 digest error to [%s:%d] url[%s]"
470
470
", MD5SUM [%s].",
471
inet_ntop2(CHECKER_RIP(checker)),
471
inet_ntop2(CHECKER_RIP(checker_obj)),
472
472
ntohs(addr_port), fetched_url->path,
475
475
DBG("MD5SUM to [%s:%d] url(%d) = [%s].",
476
inet_ntop2(CHECKER_RIP(checker))
476
inet_ntop2(CHECKER_RIP(checker_obj))
477
477
, ntohs(addr_port)
478
, http_arg->url_it + 1
478
, http_arg_obj->url_it + 1
481
481
* We set retry iterator to max value to not retry
482
482
* when service is already know as die.
484
http_arg->retry_it = http_get_check->nb_get_retry;
484
http_arg_obj->retry_it = http_get_check->nb_get_retry;
486
486
FREE(digest_tmp);
487
return epilog(thread, 2, 0, 1);
487
return epilog(thread_obj, 2, 0, 1);
489
if (!svr_checker_up(checker->id, checker->rs))
489
if (!svr_checker_up(checker_obj->id, checker_obj->rs))
490
490
syslog(LOG_INFO, "MD5 digest success to [%s:%d] url(%d).",
491
inet_ntop2(CHECKER_RIP(checker))
491
inet_ntop2(CHECKER_RIP(checker_obj))
492
492
, ntohs(addr_port)
493
, http_arg->url_it + 1);
493
, http_arg_obj->url_it + 1);
494
494
FREE(digest_tmp);
495
return epilog(thread, 1, 1, 0) + 1;
495
return epilog(thread_obj, 1, 1, 0) + 1;
499
return epilog(thread, 1, 0, 0) + 1;
499
return epilog(thread_obj, 1, 0, 0) + 1;
502
502
/* Handle response stream performing MD5 updates */
536
535
/* Asynchronous HTTP stream reader */
538
http_read_thread(thread * thread)
537
http_read_thread(thread * thread_obj)
540
checker *checker = THREAD_ARG(thread);
541
http_get_checker *http_get_check = CHECKER_ARG(checker);
542
http_arg *http_arg = HTTP_ARG(http_get_check);
543
REQ *req = HTTP_REQ(http_arg);
544
uint16_t addr_port = get_service_port(checker);
539
checker *checker_obj = THREAD_ARG(thread_obj);
540
http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
541
http_arg *http_arg_obj = HTTP_ARG(http_get_check);
542
REQ *req = HTTP_REQ(http_arg_obj);
543
uint16_t addr_port = get_service_port(checker_obj);
545
544
unsigned char digest[16];
549
548
/* Handle read timeout */
550
if (thread->type == THREAD_READ_TIMEOUT)
551
return timeout_epilog(thread, "=> HTTP CHECK failed on service"
549
if (thread_obj->type == THREAD_READ_TIMEOUT)
550
return timeout_epilog(thread_obj, "=> HTTP CHECK failed on service"
552
551
" : recevice data <=\n\n", "HTTP read");
554
553
/* Set descriptor non blocking */
555
val = fcntl(thread->u.fd, F_GETFL, 0);
556
fcntl(thread->u.fd, F_SETFL, val | O_NONBLOCK);
554
val = fcntl(thread_obj->u.fd, F_GETFL, 0);
555
fcntl(thread_obj->u.fd, F_SETFL, val | O_NONBLOCK);
558
557
/* read the HTTP stream */
559
r = read(thread->u.fd, req->buffer + req->len,
558
r = read(thread_obj->u.fd, req->buffer + req->len,
560
559
MAX_BUFFER_LENGTH - req->len);
562
561
/* restore descriptor flags */
563
fcntl(thread->u.fd, F_SETFL, val);
562
fcntl(thread_obj->u.fd, F_SETFL, val);
565
564
/* Test if data are ready */
566
if (r == -1 && errno == EAGAIN) {
565
if (r == -1 && (errno == EAGAIN || errno == EINTR)) {
567
566
syslog(LOG_INFO, "Read error with server [%s:%d]: %s",
568
inet_ntop2(CHECKER_RIP(checker))
567
inet_ntop2(CHECKER_RIP(checker_obj))
569
568
, ntohs(addr_port)
570
569
, strerror(errno));
571
thread_add_read(thread->master, http_read_thread, checker,
572
thread->u.fd, http_get_check->connection_to);
570
thread_add_read(thread_obj->master, http_read_thread, checker_obj,
571
thread_obj->u.fd, http_get_check->connection_to);
582
581
/* We have encourred a real read error */
583
if (svr_checker_up(checker->id, checker->rs)) {
582
if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
584
583
syslog(LOG_INFO, "Read error with server [%s:%d]: %s",
585
inet_ntop2(CHECKER_RIP(checker))
584
inet_ntop2(CHECKER_RIP(checker_obj))
586
585
, ntohs(addr_port)
587
586
, strerror(errno));
588
smtp_alert(thread->master, checker->rs, NULL, NULL,
587
smtp_alert(checker_obj->rs, NULL, NULL,
590
589
"=> HTTP CHECK failed on service"
591
590
" : cannot receive data <=");
592
update_svr_checker_state(DOWN, checker->id
591
update_svr_checker_state(DOWN, checker_obj->id
596
return epilog(thread, 1, 0, 0);
595
return epilog(thread_obj, 1, 0, 0);
599
598
/* Handle response stream */
600
http_handle_response(thread, digest, (!req->extracted) ? 1 : 0);
599
http_handle_response(thread_obj, digest, (!req->extracted) ? 1 : 0);
642
641
/* Register asynchronous http/ssl read thread */
643
642
if (http_get_check->proto == PROTO_SSL)
644
thread_add_read(thread->master, ssl_read_thread, checker,
645
thread->u.fd, http_get_check->connection_to);
643
thread_add_read(thread_obj->master, ssl_read_thread, checker_obj,
644
thread_obj->u.fd, http_get_check->connection_to);
647
thread_add_read(thread->master, http_read_thread, checker,
648
thread->u.fd, http_get_check->connection_to);
646
thread_add_read(thread_obj->master, http_read_thread, checker_obj,
647
thread_obj->u.fd, http_get_check->connection_to);
652
651
/* remote Web server is connected, send it the get url query. */
654
http_request_thread(thread * thread)
653
http_request_thread(thread * thread_obj)
656
checker *checker = THREAD_ARG(thread);
657
http_get_checker *http_get_check = CHECKER_ARG(checker);
658
http_arg *http_arg = HTTP_ARG(http_get_check);
659
REQ *req = HTTP_REQ(http_arg);
660
uint16_t addr_port = get_service_port(checker);
661
char *vhost = CHECKER_VHOST(checker);
655
checker *checker_obj = THREAD_ARG(thread_obj);
656
http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
657
http_arg *http_arg_obj = HTTP_ARG(http_get_check);
658
REQ *req = HTTP_REQ(http_arg_obj);
659
uint16_t addr_port = get_service_port(checker_obj);
660
char *vhost = CHECKER_VHOST(checker_obj);
662
661
char *str_request;
663
662
url *fetched_url;
666
666
/* Handle read timeout */
667
if (thread->type == THREAD_WRITE_TIMEOUT)
668
return timeout_epilog(thread, "=> CHECK failed on service"
667
if (thread_obj->type == THREAD_WRITE_TIMEOUT)
668
return timeout_epilog(thread_obj, "=> CHECK failed on service"
669
669
" : read timeout <=\n\n",
670
670
"Web read, timeout");
675
675
fetched_url = fetch_next_url(http_get_check);
676
676
snprintf(str_request, GET_BUFFER_LENGTH, REQUEST_TEMPLATE,
677
677
fetched_url->path,
678
(vhost) ? vhost : inet_ntop2(CHECKER_RIP(checker))
678
(vhost) ? vhost : inet_ntop2(CHECKER_RIP(checker_obj))
679
679
, ntohs(addr_port));
680
680
DBG("Processing url(%d) of [%s:%d].",
682
, inet_ntop2(CHECKER_RIP(checker))
681
http_arg_obj->url_it + 1
682
, inet_ntop2(CHECKER_RIP(checker_obj))
683
683
, ntohs(addr_port));
685
/* Set descriptor non blocking */
686
val = fcntl(thread_obj->u.fd, F_GETFL, 0);
687
fcntl(thread_obj->u.fd, F_SETFL, val | O_NONBLOCK);
685
689
/* Send the GET request to remote Web server */
686
if (http_get_check->proto == PROTO_SSL)
688
ssl_send_request(req->ssl, str_request,
689
strlen(str_request));
692
(send(thread->u.fd, str_request, strlen(str_request), 0) !=
690
if (http_get_check->proto == PROTO_SSL) {
691
ret = ssl_send_request(req->ssl, str_request,
692
strlen(str_request));
694
ret = (send(thread_obj->u.fd, str_request, strlen(str_request), 0) !=
698
/* restore descriptor flags */
699
fcntl(thread_obj->u.fd, F_SETFL, val);
695
701
FREE(str_request);
698
704
syslog(LOG_INFO, "Cannot send get request to [%s:%d].",
699
inet_ntop2(CHECKER_RIP(checker))
705
inet_ntop2(CHECKER_RIP(checker_obj))
700
706
, ntohs(addr_port));
702
708
/* check if server is currently alive */
703
if (svr_checker_up(checker->id, checker->rs)) {
704
smtp_alert(thread->master, checker->rs, NULL, NULL,
709
if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
710
smtp_alert(checker_obj->rs, NULL, NULL,
706
712
"=> CHECK failed on service"
707
713
" : cannot send data <=");
708
update_svr_checker_state(DOWN, checker->id
714
update_svr_checker_state(DOWN, checker_obj->id
712
return epilog(thread, 1, 0, 0);
718
return epilog(thread_obj, 1, 0, 0);
715
721
/* Register read timeouted thread */
716
thread_add_read(thread->master, http_response_thread, checker,
717
thread->u.fd, http_get_check->connection_to);
722
thread_add_read(thread_obj->master, http_response_thread, checker_obj,
723
thread_obj->u.fd, http_get_check->connection_to);
721
727
/* WEB checkers threads */
723
http_check_thread(thread * thread)
729
http_check_thread(thread * thread_obj)
725
checker *checker = THREAD_ARG(thread);
726
http_get_checker *http_get_check = CHECKER_ARG(checker);
727
uint16_t addr_port = get_service_port(checker);
728
http_arg *http_arg = HTTP_ARG(http_get_check);
731
checker *checker_obj = THREAD_ARG(thread_obj);
732
http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
733
uint16_t addr_port = get_service_port(checker_obj);
734
http_arg *http_arg_obj = HTTP_ARG(http_get_check);
730
REQ *req = HTTP_REQ(http_arg);
736
REQ *req = HTTP_REQ(http_arg_obj);
735
status = tcp_socket_state(thread->u.fd, thread, CHECKER_RIP(checker)
741
status = tcp_socket_state(thread_obj->u.fd, thread_obj, CHECKER_RIP(checker_obj)
736
742
, addr_port, http_check_thread);
737
743
switch (status) {
738
744
case connect_error:
739
745
/* check if server is currently alive */
740
if (svr_checker_up(checker->id, checker->rs)) {
746
if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
741
747
syslog(LOG_INFO, "Error connecting server [%s:%d].",
742
inet_ntop2(CHECKER_RIP(checker))
748
inet_ntop2(CHECKER_RIP(checker_obj))
743
749
, ntohs(addr_port));
744
smtp_alert(thread->master, checker->rs, NULL, NULL,
750
smtp_alert(checker_obj->rs, NULL, NULL,
746
752
"=> CHECK failed on service"
747
753
" : connection error <=");
748
update_svr_checker_state(DOWN, checker->id
754
update_svr_checker_state(DOWN, checker_obj->id
752
return epilog(thread, 1, 0, 0);
758
return epilog(thread_obj, 1, 0, 0);
755
761
case connect_timeout:
756
return timeout_epilog(thread, "==> CHECK failed on service"
762
return timeout_epilog(thread_obj, "==> CHECK failed on service"
757
763
" : connection timeout <=\n\n",
758
764
"connect, timeout");
761
767
case connect_success:{
762
768
/* Allocate & clean request struct */
763
http_arg->req = (REQ *) MALLOC(sizeof (REQ));
769
http_arg_obj->req = (REQ *) MALLOC(sizeof (REQ));
765
771
if (http_get_check->proto == PROTO_SSL)
766
ret = ssl_connect(thread);
772
ret = ssl_connect(thread_obj);
769
775
/* Remote WEB server is connected.
770
776
* Register the next step thread ssl_request_thread.
772
778
DBG("Remote Web server [%s:%d] connected.",
773
inet_ntop2(CHECKER_RIP(checker)),
779
inet_ntop2(CHECKER_RIP(checker_obj)),
774
780
ntohs(addr_port));
775
thread_add_write(thread->master,
776
http_request_thread, checker,
781
thread_add_write(thread_obj->master,
782
http_request_thread, checker_obj,
778
784
http_get_check->connection_to);
780
786
syslog(LOG_INFO, "Connection trouble to: [%s:%d].",
781
inet_ntop2(CHECKER_RIP(checker))
787
inet_ntop2(CHECKER_RIP(checker_obj))
782
788
, ntohs(addr_port));
784
790
if (http_get_check->proto == PROTO_SSL)
785
791
ssl_printerr(SSL_get_error
786
792
(req->ssl, ret));
788
return epilog(thread, 1, 0, 0);
794
return epilog(thread_obj, 1, 0, 0);