~ubuntu-branches/ubuntu/trusty/keepalived/trusty

« back to all changes in this revision

Viewing changes to keepalived/check/check_http.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Wirt
  • Date: 2005-04-29 23:22:40 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 hoary)
  • Revision ID: james.westby@ubuntu.com-20050429232240-a8m3jtpi3cvuyyy2
Tags: 1.1.11-3
Added a warning about sarge kernels to README.Debian and 
the package description 

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *
6
6
 * Part:        WEB CHECK. Common HTTP/SSL checker primitives.
7
7
 *
8
 
 * Version:     $Id: check_http.c,v 1.1.7 2004/04/04 23:28:05 acassen Exp $
 
8
 * Version:     $Id: check_http.c,v 1.1.11 2005/03/01 01:22:13 acassen Exp $
9
9
 *
10
10
 * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
11
11
 *              Jan Holmberg, <jan@artech.net>
20
20
 *              as published by the Free Software Foundation; either version
21
21
 *              2 of the License, or (at your option) any later version.
22
22
 *
23
 
 * Copyright (C) 2001-2004 Alexandre Cassen, <acassen@linux-vs.org>
 
23
 * Copyright (C) 2001-2005 Alexandre Cassen, <acassen@linux-vs.org>
24
24
 */
25
25
 
26
26
#include <openssl/err.h>
38
38
void
39
39
free_url(void *data)
40
40
{
41
 
        url *url = data;
42
 
        FREE(url->path);
43
 
        FREE(url->digest);
44
 
        FREE(url);
 
41
        url *url_obj = data;
 
42
        FREE(url_obj->path);
 
43
        FREE(url_obj->digest);
 
44
        FREE(url_obj);
45
45
}
46
46
 
47
47
void
48
48
dump_url(void *data)
49
49
{
50
 
        url *url = data;
51
 
        syslog(LOG_INFO, "   Checked url = %s", url->path);
52
 
        if (url->digest)
 
50
        url *url_obj = data;
 
51
        syslog(LOG_INFO, "   Checked url = %s", url_obj->path);
 
52
        if (url_obj->digest)
53
53
                syslog(LOG_INFO, "           digest = %s",
54
 
                       url->digest);
55
 
        if (url->status_code)
 
54
                       url_obj->digest);
 
55
        if (url_obj->status_code)
56
56
                syslog(LOG_INFO, "           HTTP Status Code = %d",
57
 
                       url->status_code);
 
57
                       url_obj->status_code);
58
58
}
59
59
 
60
60
void
168
168
path_handler(vector strvec)
169
169
{
170
170
        http_get_checker *http_get_chk = CHECKER_GET();
171
 
        url *url = LIST_TAIL_DATA(http_get_chk->url);
 
171
        url *url_obj = LIST_TAIL_DATA(http_get_chk->url);
172
172
 
173
 
        url->path = CHECKER_VALUE_STRING(strvec);
 
173
        url_obj->path = CHECKER_VALUE_STRING(strvec);
174
174
}
175
175
 
176
176
void
177
177
digest_handler(vector strvec)
178
178
{
179
179
        http_get_checker *http_get_chk = CHECKER_GET();
180
 
        url *url = LIST_TAIL_DATA(http_get_chk->url);
 
180
        url *url_obj = LIST_TAIL_DATA(http_get_chk->url);
181
181
 
182
 
        url->digest = CHECKER_VALUE_STRING(strvec);
 
182
        url_obj->digest = CHECKER_VALUE_STRING(strvec);
183
183
}
184
184
 
185
185
void
186
186
status_code_handler(vector strvec)
187
187
{
188
188
        http_get_checker *http_get_chk = CHECKER_GET();
189
 
        url *url = LIST_TAIL_DATA(http_get_chk->url);
 
189
        url *url_obj = LIST_TAIL_DATA(http_get_chk->url);
190
190
 
191
 
        url->status_code = CHECKER_VALUE_INT(strvec);
 
191
        url_obj->status_code = CHECKER_VALUE_INT(strvec);
192
192
}
193
193
 
194
194
void
256
256
 */
257
257
 
258
258
uint16_t
259
 
get_service_port(checker * checker)
 
259
get_service_port(checker * checker_obj)
260
260
{
261
 
        http_get_checker *http_get_check = CHECKER_ARG(checker);
 
261
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
262
262
        uint16_t addr_port;
263
263
 
264
264
        /*
268
268
         *  then assume we want to use default ports for HTTP or HTTPS.
269
269
         *  Known as 'Layer3 stickyness'.
270
270
         */
271
 
        addr_port = CHECKER_RPORT(checker);
 
271
        addr_port = CHECKER_RPORT(checker_obj);
272
272
        if (!addr_port)
273
273
                addr_port =
274
274
                    htons((http_get_check->proto == PROTO_SSL) ? 443 : 80);
287
287
 * method == 2 => register a retry on url checker thread
288
288
 */
289
289
int
290
 
epilog(thread * thread, int method, int t, int c)
 
290
epilog(thread * thread_obj, int method, int t, int c)
291
291
{
292
 
        checker *checker = THREAD_ARG(thread);
293
 
        http_get_checker *http_get_check = CHECKER_ARG(checker);
294
 
        http_arg *http_arg = HTTP_ARG(http_get_check);
295
 
        REQ *req = HTTP_REQ(http_arg);
296
 
        uint16_t addr_port = get_service_port(checker);
 
292
        checker *checker_obj = THREAD_ARG(thread_obj);
 
293
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
 
294
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
 
295
        REQ *req = HTTP_REQ(http_arg_obj);
 
296
        uint16_t addr_port = get_service_port(checker_obj);
297
297
        long delay = 0;
298
298
 
299
299
        if (method) {
300
 
                http_arg->url_it += t ? t : -http_arg->url_it;
301
 
                http_arg->retry_it += c ? c : -http_arg->retry_it;
 
300
                http_arg_obj->url_it += t ? t : -http_arg_obj->url_it;
 
301
                http_arg_obj->retry_it += c ? c : -http_arg_obj->retry_it;
302
302
        }
303
303
 
304
304
        /*
307
307
         * html buffer. This is sometime needed with some applications
308
308
         * servers.
309
309
         */
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,
316
316
                                   "DOWN",
317
317
                                   "=> CHECK failed on service"
318
318
                                   " : MD5 digest mismatch <=");
319
 
                        update_svr_checker_state(DOWN, checker->id
320
 
                                                     , checker->vs
321
 
                                                     , checker->rs);
 
319
                        update_svr_checker_state(DOWN, checker_obj->id
 
320
                                                     , checker_obj->vs
 
321
                                                     , checker_obj->rs);
322
322
                }
323
323
 
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;
327
327
        }
328
328
 
329
329
        /* register next timer thread */
330
330
        switch (method) {
331
331
        case 1:
332
332
                if (req)
333
 
                        delay = checker->vs->delay_loop;
 
333
                        delay = checker_obj->vs->delay_loop;
334
334
                else
335
335
                        delay =
336
336
                            http_get_check->delay_before_retry;
337
337
                break;
338
338
        case 2:
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;
341
341
                else
342
342
                        delay = http_get_check->delay_before_retry;
343
343
                break;
350
350
                if (req->buffer)
351
351
                        FREE(req->buffer);
352
352
                FREE(req);
353
 
                http_arg->req = NULL;
354
 
                close(thread->u.fd);
 
353
                http_arg_obj->req = NULL;
 
354
                close(thread_obj->u.fd);
355
355
        }
356
356
 
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);
359
359
        return 0;
360
360
}
361
361
 
362
362
int
363
 
timeout_epilog(thread * thread, char *smtp_msg, char *debug_msg)
 
363
timeout_epilog(thread * thread_obj, char *smtp_msg, char *debug_msg)
364
364
{
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);
367
367
 
368
368
        syslog(LOG_INFO, "Timeout %s server [%s:%d].",
369
369
               debug_msg
370
 
               , inet_ntop2(CHECKER_RIP(checker))
 
370
               , inet_ntop2(CHECKER_RIP(checker_obj))
371
371
               , ntohs(addr_port));
372
372
 
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
378
 
                                             , checker->vs
379
 
                                             , checker->rs);
 
377
                update_svr_checker_state(DOWN, checker_obj->id
 
378
                                             , checker_obj->vs
 
379
                                             , checker_obj->rs);
380
380
        }
381
381
 
382
 
        return epilog(thread, 1, 0, 0);
 
382
        return epilog(thread_obj, 1, 0, 0);
383
383
}
384
384
 
385
385
/* return the url pointer of the current url iterator  */
386
386
url *
387
387
fetch_next_url(http_get_checker * http_get_check)
388
388
{
389
 
        http_arg *http_arg = HTTP_ARG(http_get_check);
 
389
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
390
390
 
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);
392
392
}
393
393
 
394
394
/* Handle response */
395
395
int
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)
398
398
{
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);
404
404
        int r, di = 0;
405
405
        unsigned char *digest_tmp;
406
406
        url *fetched_url = fetch_next_url(http_get_check);
407
407
 
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 ");
413
413
 
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)) {
419
419
                                syslog(LOG_INFO,
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,
426
426
                                           "DOWN",
427
427
                                           "=> CHECK failed on service"
428
428
                                           " : HTTP status code mismatch <=");
429
 
                                update_svr_checker_state(DOWN, checker->id
430
 
                                                             , checker->vs
431
 
                                                             , checker->rs);
 
429
                                update_svr_checker_state(DOWN, checker_obj->id
 
430
                                                             , checker_obj->vs
 
431
                                                             , checker_obj->rs);
432
432
                        } else {
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);
438
438
                                /*
439
439
                                 * We set retry iterator to max value to not retry
440
440
                                 * when service is already know as die.
441
441
                                 */
442
 
                                http_arg->retry_it = http_get_check->nb_get_retry;
 
442
                                http_arg_obj->retry_it = http_get_check->nb_get_retry;
443
443
                        }
444
 
                        return epilog(thread, 2, 0, 1);
 
444
                        return epilog(thread_obj, 2, 0, 1);
445
445
                } else {
446
 
                        if (!svr_checker_up(checker->id, checker->rs))
 
446
                        if (!svr_checker_up(checker_obj->id, checker_obj->rs))
447
447
                                syslog(LOG_INFO,
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;
453
453
                }
454
454
        }
455
455
 
464
464
 
465
465
                if (r) {
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)) {
468
468
                                syslog(LOG_INFO,
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,
473
473
                                       digest_tmp);
474
474
                        } else {
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
479
479
                                    , digest_tmp);
480
480
                                /*
481
481
                                 * We set retry iterator to max value to not retry
482
482
                                 * when service is already know as die.
483
483
                                 */
484
 
                                http_arg->retry_it = http_get_check->nb_get_retry;
 
484
                                http_arg_obj->retry_it = http_get_check->nb_get_retry;
485
485
                        }
486
486
                        FREE(digest_tmp);
487
 
                        return epilog(thread, 2, 0, 1);
 
487
                        return epilog(thread_obj, 2, 0, 1);
488
488
                } else {
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;
496
496
                }
497
497
        }
498
498
 
499
 
        return epilog(thread, 1, 0, 0) + 1;
 
499
        return epilog(thread_obj, 1, 0, 0) + 1;
500
500
}
501
501
 
502
502
/* Handle response stream performing MD5 updates */
510
510
                        req->status_code = extract_status_code(req->buffer, req->len);
511
511
                        r = req->len - (req->extracted - req->buffer);
512
512
                        if (r) {
513
 
                                memcpy(req->buffer, req->extracted, r);
514
 
                                MD5_Update(&req->context, req->buffer,
515
 
                                           r);
 
513
                                memmove(req->buffer, req->extracted, r);
 
514
                                MD5_Update(&req->context, req->buffer, r);
516
515
                                r = 0;
517
516
                        }
518
517
                        req->len = r;
519
518
                } else {
520
519
                        /* minimize buffer using no 2*CR/LF found yet */
521
 
                        if (req->len > 3) {
522
 
                                memcpy(req->buffer,
523
 
                                       req->buffer + req->len - 3, 3);
524
 
                                req->len = 3;
 
520
                        if (req->len > 4) {
 
521
                                memmove(req->buffer,
 
522
                                        req->buffer + req->len - 4, 4);
 
523
                                req->len = 4;
525
524
                        }
526
525
                }
527
526
        } else if (req->len) {
535
534
 
536
535
/* Asynchronous HTTP stream reader */
537
536
int
538
 
http_read_thread(thread * thread)
 
537
http_read_thread(thread * thread_obj)
539
538
{
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];
546
545
        int r = 0;
547
546
        int val;
548
547
 
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");
553
552
 
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);
557
556
 
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);
561
560
 
562
561
        /* restore descriptor flags */
563
 
        fcntl(thread->u.fd, F_SETFL, val);
 
562
        fcntl(thread_obj->u.fd, F_SETFL, val);
564
563
 
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);
573
572
                return 0;
574
573
        }
575
574
 
580
579
 
581
580
                if (r == -1) {
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,
589
588
                                           "DOWN",
590
589
                                           "=> HTTP CHECK failed on service"
591
590
                                           " : cannot receive data <=");
592
 
                                update_svr_checker_state(DOWN, checker->id
593
 
                                                             , checker->vs
594
 
                                                             , checker->rs);
 
591
                                update_svr_checker_state(DOWN, checker_obj->id
 
592
                                                             , checker_obj->vs
 
593
                                                             , checker_obj->rs);
595
594
                        }
596
 
                        return epilog(thread, 1, 0, 0);
 
595
                        return epilog(thread_obj, 1, 0, 0);
597
596
                }
598
597
 
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);
601
600
 
602
601
        } else {
603
602
 
608
607
                 * Register next http stream reader.
609
608
                 * Register itself to not perturbe global I/O multiplexer.
610
609
                 */
611
 
                thread_add_read(thread->master, http_read_thread, checker,
612
 
                                thread->u.fd, http_get_check->connection_to);
 
610
                thread_add_read(thread_obj->master, http_read_thread, checker_obj,
 
611
                                thread_obj->u.fd, http_get_check->connection_to);
613
612
        }
614
613
 
615
614
        return 0;
620
619
 * Apply trigger check to this result.
621
620
 */
622
621
int
623
 
http_response_thread(thread * thread)
 
622
http_response_thread(thread * thread_obj)
624
623
{
625
 
        checker *checker = THREAD_ARG(thread);
626
 
        http_get_checker *http_get_check = CHECKER_ARG(checker);
627
 
        http_arg *http_arg = HTTP_ARG(http_get_check);
628
 
        REQ *req = HTTP_REQ(http_arg);
 
624
        checker *checker_obj = THREAD_ARG(thread_obj);
 
625
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
 
626
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
 
627
        REQ *req = HTTP_REQ(http_arg_obj);
629
628
 
630
629
        /* Handle read timeout */
631
 
        if (thread->type == THREAD_READ_TIMEOUT)
632
 
                return timeout_epilog(thread, "=> CHECK failed on service"
 
630
        if (thread_obj->type == THREAD_READ_TIMEOUT)
 
631
                return timeout_epilog(thread_obj, "=> CHECK failed on service"
633
632
                                      " : recevice data <=\n\n", "WEB read");
634
633
 
635
634
        /* Allocate & clean the get buffer */
641
640
 
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);
646
645
        else
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);
649
648
        return 0;
650
649
}
651
650
 
652
651
/* remote Web server is connected, send it the get url query.  */
653
652
int
654
 
http_request_thread(thread * thread)
 
653
http_request_thread(thread * thread_obj)
655
654
{
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;
664
663
        int ret = 0;
 
664
        int val;
665
665
 
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");
671
671
 
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].",
681
 
            http_arg->url_it + 1
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));
684
684
 
 
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);
 
688
 
685
689
        /* Send the GET request to remote Web server */
686
 
        if (http_get_check->proto == PROTO_SSL)
687
 
                ret =
688
 
                    ssl_send_request(req->ssl, str_request,
689
 
                                     strlen(str_request));
690
 
        else
691
 
                ret =
692
 
                    (send(thread->u.fd, str_request, strlen(str_request), 0) !=
693
 
                     -1) ? 1 : 0;
 
690
        if (http_get_check->proto == PROTO_SSL) {
 
691
                ret = ssl_send_request(req->ssl, str_request,
 
692
                                       strlen(str_request));
 
693
        } else {
 
694
                ret = (send(thread_obj->u.fd, str_request, strlen(str_request), 0) !=
 
695
                       -1) ? 1 : 0;
 
696
        }
 
697
 
 
698
        /* restore descriptor flags */
 
699
        fcntl(thread_obj->u.fd, F_SETFL, val);
694
700
 
695
701
        FREE(str_request);
696
702
 
697
703
        if (!ret) {
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));
701
707
 
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,
705
711
                                   "DOWN",
706
712
                                   "=> CHECK failed on service"
707
713
                                   " : cannot send data <=");
708
 
                        update_svr_checker_state(DOWN, checker->id
709
 
                                                     , checker->vs
710
 
                                                     , checker->rs);
 
714
                        update_svr_checker_state(DOWN, checker_obj->id
 
715
                                                     , checker_obj->vs
 
716
                                                     , checker_obj->rs);
711
717
                }
712
 
                return epilog(thread, 1, 0, 0);
 
718
                return epilog(thread_obj, 1, 0, 0);
713
719
        }
714
720
 
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);
718
724
        return 1;
719
725
}
720
726
 
721
727
/* WEB checkers threads */
722
728
int
723
 
http_check_thread(thread * thread)
 
729
http_check_thread(thread * thread_obj)
724
730
{
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);
729
735
#ifdef _DEBUG_
730
 
        REQ *req = HTTP_REQ(http_arg);
 
736
        REQ *req = HTTP_REQ(http_arg_obj);
731
737
#endif
732
738
        int ret = 1;
733
739
        int status;
734
740
 
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,
745
751
                                   "DOWN",
746
752
                                   "=> CHECK failed on service"
747
753
                                   " : connection error <=");
748
 
                        update_svr_checker_state(DOWN, checker->id
749
 
                                                     , checker->vs
750
 
                                                     , checker->rs);
 
754
                        update_svr_checker_state(DOWN, checker_obj->id
 
755
                                                     , checker_obj->vs
 
756
                                                     , checker_obj->rs);
751
757
                }
752
 
                return epilog(thread, 1, 0, 0);
 
758
                return epilog(thread_obj, 1, 0, 0);
753
759
                break;
754
760
 
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");
759
765
                break;
760
766
 
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));
764
770
 
765
771
                        if (http_get_check->proto == PROTO_SSL)
766
 
                                ret = ssl_connect(thread);
 
772
                                ret = ssl_connect(thread_obj);
767
773
 
768
774
                        if (ret) {
769
775
                                /* Remote WEB server is connected.
770
776
                                 * Register the next step thread ssl_request_thread.
771
777
                                 */
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,
777
 
                                                 thread->u.fd,
 
781
                                thread_add_write(thread_obj->master,
 
782
                                                 http_request_thread, checker_obj,
 
783
                                                 thread_obj->u.fd,
778
784
                                                 http_get_check->connection_to);
779
785
                        } else {
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));
783
789
#ifdef _DEBUG_
784
790
                                if (http_get_check->proto == PROTO_SSL)
785
791
                                        ssl_printerr(SSL_get_error
786
792
                                                     (req->ssl, ret));
787
793
#endif
788
 
                                return epilog(thread, 1, 0, 0);
 
794
                                return epilog(thread_obj, 1, 0, 0);
789
795
                        }
790
796
                }
791
797
                break;
795
801
}
796
802
 
797
803
int
798
 
http_connect_thread(thread * thread)
 
804
http_connect_thread(thread * thread_obj)
799
805
{
800
 
        checker *checker = THREAD_ARG(thread);
801
 
        http_get_checker *http_get_check = CHECKER_ARG(checker);
802
 
        http_arg *http_arg = HTTP_ARG(http_get_check);
803
 
        uint16_t addr_port = get_service_port(checker);
 
806
        checker *checker_obj = THREAD_ARG(thread_obj);
 
807
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
 
808
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
 
809
        uint16_t addr_port = get_service_port(checker_obj);
804
810
        url *fetched_url;
805
811
        enum connect_result status;
806
812
        int fd;
809
815
         * Register a new checker thread & return
810
816
         * if checker is disabled
811
817
         */
812
 
        if (!CHECKER_ENABLED(checker)) {
813
 
                thread_add_timer(thread->master, http_connect_thread, checker,
814
 
                                 checker->vs->delay_loop);
 
818
        if (!CHECKER_ENABLED(checker_obj)) {
 
819
                thread_add_timer(thread_obj->master, http_connect_thread, checker_obj,
 
820
                                 checker_obj->vs->delay_loop);
815
821
                return 0;
816
822
        }
817
823
 
823
829
                 * Check completed.
824
830
                 * check if server is currently alive.
825
831
                 */
826
 
                if (!svr_checker_up(checker->id, checker->rs)) {
 
832
                if (!svr_checker_up(checker_obj->id, checker_obj->rs)) {
827
833
                        syslog(LOG_INFO, "Remote Web server [%s:%d] succeed on service.",
828
 
                               inet_ntop2(CHECKER_RIP(checker))
 
834
                               inet_ntop2(CHECKER_RIP(checker_obj))
829
835
                               , ntohs(addr_port));
830
 
                        smtp_alert(thread->master, checker->rs, NULL, NULL, "UP",
 
836
                        smtp_alert(checker_obj->rs, NULL, NULL, "UP",
831
837
                                   "=> CHECK succeed on service <=");
832
 
                        update_svr_checker_state(UP, checker->id
833
 
                                                   , checker->vs
834
 
                                                   , checker->rs);
 
838
                        update_svr_checker_state(UP, checker_obj->id
 
839
                                                   , checker_obj->vs
 
840
                                                   , checker_obj->rs);
835
841
                }
836
 
                http_arg->req = NULL;
837
 
                return epilog(thread, 1, 0, 0) + 1;
 
842
                http_arg_obj->req = NULL;
 
843
                return epilog(thread_obj, 1, 0, 0) + 1;
838
844
        }
839
845
 
840
846
        /* Create the socket */
843
849
                return 0;
844
850
        }
845
851
 
846
 
        status = tcp_bind_connect(fd, CHECKER_RIP(checker), addr_port
 
852
        status = tcp_bind_connect(fd, CHECKER_RIP(checker_obj), addr_port
847
853
                                  , http_get_check->bindto);
848
854
 
849
855
        /* handle tcp connection status & register check worker thread */
850
 
        tcp_connection_state(fd, status, thread, http_check_thread,
 
856
        tcp_connection_state(fd, status, thread_obj, http_check_thread,
851
857
                             http_get_check->connection_to);
852
858
        return 0;
853
859
}