View | Details | Raw Unified | Return to bug 57439
Collapse All | Expand All

(-)modules/filters/mod_reqtimeout.c (-27 / +117 lines)
Lines 48-53 Link Here
48
    apr_time_t body_rate_factor;
48
    apr_time_t body_rate_factor;
49
} reqtimeout_srv_cfg;
49
} reqtimeout_srv_cfg;
50
50
51
typedef struct
52
{
53
    int body_timeout;       /* timeout for reading the req body in secs */
54
    int body_max_timeout;   /* max timeout for req body in secs */
55
    int body_min_rate;      /* min rate for reading req body in bytes/s */
56
    apr_time_t body_rate_factor;
57
} reqtimeout_dir_cfg;
58
51
/* this struct is used both as conn_config and as filter context */
59
/* this struct is used both as conn_config and as filter context */
52
typedef struct
60
typedef struct
53
{
61
{
Lines 417-422 Link Here
417
    reqtimeout_srv_cfg *cfg;
425
    reqtimeout_srv_cfg *cfg;
418
    reqtimeout_con_cfg *ccfg =
426
    reqtimeout_con_cfg *ccfg =
419
        ap_get_module_config(r->connection->conn_config, &reqtimeout_module);
427
        ap_get_module_config(r->connection->conn_config, &reqtimeout_module);
428
    reqtimeout_dir_cfg *dcfg =
429
        ap_get_module_config(r->per_dir_config, &reqtimeout_module);
420
430
421
    if (ccfg == NULL || r->method_number == M_CONNECT) {
431
    if (ccfg == NULL || r->method_number == M_CONNECT) {
422
        /* either disabled for this connection or a CONNECT request */
432
        /* either disabled for this connection or a CONNECT request */
Lines 429-435 Link Here
429
    ccfg->timeout_at = 0;
439
    ccfg->timeout_at = 0;
430
    ccfg->max_timeout_at = 0;
440
    ccfg->max_timeout_at = 0;
431
    ccfg->type = "body";
441
    ccfg->type = "body";
432
    if (cfg->body_timeout != UNSET) {
442
443
    if (dcfg->body_timeout != UNSET) {
444
        ccfg->new_timeout     = dcfg->body_timeout;
445
        ccfg->new_max_timeout = dcfg->body_max_timeout;
446
        ccfg->min_rate        = dcfg->body_min_rate;
447
        ccfg->rate_factor     = dcfg->body_rate_factor;
448
    }
449
    else if (cfg->body_timeout != UNSET) {
433
        ccfg->new_timeout     = cfg->body_timeout;
450
        ccfg->new_timeout     = cfg->body_timeout;
434
        ccfg->new_max_timeout = cfg->body_max_timeout;
451
        ccfg->new_max_timeout = cfg->body_max_timeout;
435
        ccfg->min_rate        = cfg->body_min_rate;
452
        ccfg->min_rate        = cfg->body_min_rate;
Lines 479-484 Link Here
479
    return cfg;
496
    return cfg;
480
}
497
}
481
498
499
static void *reqtimeout_create_dir_config(apr_pool_t *p, char *dir)
500
{
501
    reqtimeout_dir_cfg *dcfg = apr_pcalloc(p, sizeof(reqtimeout_dir_cfg));
502
503
    dcfg->body_timeout = UNSET;
504
    dcfg->body_max_timeout = UNSET;
505
    dcfg->body_min_rate = UNSET;
506
507
    return dcfg;
508
}
509
510
static void *reqtimeout_merge_dir_config(apr_pool_t *p, void *base_, void *add_)
511
{
512
    reqtimeout_dir_cfg *base = base_;
513
    reqtimeout_dir_cfg *add  = add_;
514
    reqtimeout_dir_cfg *dcfg  = apr_pcalloc(p, sizeof(reqtimeout_dir_cfg));
515
516
    MERGE_INT(dcfg, base, add, body_timeout);
517
    MERGE_INT(dcfg, base, add, body_max_timeout);
518
    MERGE_INT(dcfg, base, add, body_min_rate);
519
520
    dcfg->body_rate_factor = (dcfg->body_min_rate == UNSET) ?
521
                             base->body_rate_factor : add->body_rate_factor;
522
523
    return dcfg;
524
}
525
482
static const char *parse_int(apr_pool_t *p, const char *arg, int *val) {
526
static const char *parse_int(apr_pool_t *p, const char *arg, int *val) {
483
    char *endptr;
527
    char *endptr;
484
    *val = strtol(arg, &endptr, 10);
528
    *val = strtol(arg, &endptr, 10);
Lines 495-524 Link Here
495
    return NULL;
539
    return NULL;
496
}
540
}
497
541
498
static const char *set_reqtimeout_param(reqtimeout_srv_cfg *conf,
542
static const char *parse_setting(apr_pool_t *p, const char *val, int *initial,
499
                                      apr_pool_t *p,
543
                                 int *max, int *rate)
500
                                      const char *key,
501
                                      const char *val)
502
{
544
{
503
    const char *ret = NULL;
545
    const char *ret = NULL;
504
    char *rate_str = NULL, *initial_str, *max_str = NULL;
546
    char *rate_str = NULL, *initial_str, *max_str = NULL;
505
    int rate = 0, initial = 0, max = 0;
506
    enum { PARAM_HEADER, PARAM_BODY } type;
507
547
508
    if (!strcasecmp(key, "header")) {
509
        type = PARAM_HEADER;
510
    }
511
    else if (!strcasecmp(key, "body")) {
512
        type = PARAM_BODY;
513
    }
514
    else {
515
        return "Unknown RequestReadTimeout parameter";
516
    }
517
518
    if ((rate_str = ap_strcasestr(val, ",minrate="))) {
548
    if ((rate_str = ap_strcasestr(val, ",minrate="))) {
519
        initial_str = apr_pstrndup(p, val, rate_str - val);
549
        initial_str = apr_pstrndup(p, val, rate_str - val);
520
        rate_str += strlen(",minrate=");
550
        rate_str += strlen(",minrate=");
521
        ret = parse_int(p, rate_str, &rate);
551
        ret = parse_int(p, rate_str, rate);
522
        if (ret)
552
        if (ret)
523
            return ret;
553
            return ret;
524
554
Lines 527-552 Link Here
527
557
528
        if ((max_str = strchr(initial_str, '-'))) {
558
        if ((max_str = strchr(initial_str, '-'))) {
529
            *max_str++ = '\0';
559
            *max_str++ = '\0';
530
            ret = parse_int(p, max_str, &max);
560
            ret = parse_int(p, max_str, max);
531
            if (ret)
561
            if (ret)
532
                return ret;
562
                return ret;
533
        }
563
        }
534
564
535
        ret = parse_int(p, initial_str, &initial);
565
        ret = parse_int(p, initial_str, initial);
536
    }
566
    }
537
    else {
567
    else {
538
        if (ap_strchr_c(val, '-'))
568
        if (ap_strchr_c(val, '-'))
539
            return "Must set MinRate option if using timeout range";
569
            return "Must set MinRate option if using timeout range";
540
        ret = parse_int(p, val, &initial);
570
        ret = parse_int(p, val, initial);
541
    }
571
    }
542
572
543
    if (ret)
573
    if (ret)
544
        return ret;
574
        return ret;
545
575
546
    if (max && initial >= max) {
576
    if (*max && *initial >= *max) {
547
        return "Maximum timeout must be larger than initial timeout";
577
        return "Maximum timeout must be larger than initial timeout";
548
    }
578
    }
549
579
580
    return NULL;
581
}
582
583
static const char *set_reqtimeout_srv_param(reqtimeout_srv_cfg *conf,
584
                                            apr_pool_t *p,
585
                                            const char *key,
586
                                            const char *val)
587
{
588
    const char *ret = NULL;
589
    int rate = 0, initial = 0, max = 0;
590
    enum { PARAM_HEADER, PARAM_BODY } type;
591
592
    if (!strcasecmp(key, "header")) {
593
        type = PARAM_HEADER;
594
    }
595
    else if (!strcasecmp(key, "body")) {
596
        type = PARAM_BODY;
597
    }
598
    else {
599
        return "Unknown RequestReadTimeout parameter";
600
    }
601
602
    ret = parse_setting(p, val, &initial, &max, &rate);
603
    if (ret)
604
        return ret;
605
550
    if (type == PARAM_HEADER) {
606
    if (type == PARAM_HEADER) {
551
        conf->header_timeout = initial;
607
        conf->header_timeout = initial;
552
        conf->header_max_timeout = max;
608
        conf->header_max_timeout = max;
Lines 561-569 Link Here
561
        if (rate)
617
        if (rate)
562
            conf->body_rate_factor = apr_time_from_sec(1) / rate;
618
            conf->body_rate_factor = apr_time_from_sec(1) / rate;
563
    }
619
    }
620
564
    return ret;
621
    return ret;
565
}
622
}
566
623
624
static const char *set_reqtimeout_dir_param(reqtimeout_dir_cfg *dcfg,
625
                                            apr_pool_t *p,
626
                                            const char *key,
627
                                            const char *val)
628
{
629
    const char *ret = NULL;
630
    int rate = 0, initial = 0, max = 0;
631
632
    if (!strcasecmp(key, "header")) {
633
        return "Header timeout can not be changed within a location or directory";
634
    }
635
    else if (strcasecmp(key, "body")) {
636
        return "Unknown RequestReadTimeout parameter";
637
    }
638
639
    ret = parse_setting(p, val, &initial, &max, &rate);
640
    if (ret)
641
        return ret;
642
643
    dcfg->body_timeout = initial;
644
    dcfg->body_max_timeout = max;
645
    dcfg->body_min_rate = rate;
646
    if (rate)
647
        dcfg->body_rate_factor = apr_time_from_sec(1) / rate;
648
649
    return ret;
650
}
651
567
static const char *set_reqtimeouts(cmd_parms *cmd, void *mconfig,
652
static const char *set_reqtimeouts(cmd_parms *cmd, void *mconfig,
568
                                   const char *arg)
653
                                   const char *arg)
569
{
654
{
Lines 584-590 Link Here
584
        else
669
        else
585
            *val++ = '\0';
670
            *val++ = '\0';
586
671
587
        err = set_reqtimeout_param(conf, cmd->pool, word, val);
672
        if (cmd->path == NULL) {
673
            err = set_reqtimeout_srv_param(conf, cmd->pool, word, val);
674
        }
675
        else {
676
            err = set_reqtimeout_dir_param(mconfig, cmd->pool, word, val);
677
        }
588
678
589
        if (err)
679
        if (err)
590
            return apr_psprintf(cmd->temp_pool, "RequestReadTimeout: %s=%s: %s",
680
            return apr_psprintf(cmd->temp_pool, "RequestReadTimeout: %s=%s: %s",
Lines 616-622 Link Here
616
706
617
    ap_hook_pre_read_request(reqtimeout_before_header, NULL, NULL,
707
    ap_hook_pre_read_request(reqtimeout_before_header, NULL, NULL,
618
                             APR_HOOK_MIDDLE);
708
                             APR_HOOK_MIDDLE);
619
    ap_hook_post_read_request(reqtimeout_before_body, NULL, NULL,
709
    ap_hook_post_perdir_config(reqtimeout_before_body, NULL, NULL,
620
                              APR_HOOK_MIDDLE);
710
                              APR_HOOK_MIDDLE);
621
711
622
#if MRT_DEFAULT_HEADER_MIN_RATE > 0
712
#if MRT_DEFAULT_HEADER_MIN_RATE > 0
Lines 628-634 Link Here
628
}
718
}
629
719
630
static const command_rec reqtimeout_cmds[] = {
720
static const command_rec reqtimeout_cmds[] = {
631
    AP_INIT_RAW_ARGS("RequestReadTimeout", set_reqtimeouts, NULL, RSRC_CONF,
721
    AP_INIT_RAW_ARGS("RequestReadTimeout", set_reqtimeouts, NULL, ACCESS_CONF|RSRC_CONF,
632
                     "Set various timeout parameters for reading request "
722
                     "Set various timeout parameters for reading request "
633
                     "headers and body"),
723
                     "headers and body"),
634
    {NULL}
724
    {NULL}
Lines 636-643 Link Here
636
726
637
AP_DECLARE_MODULE(reqtimeout) = {
727
AP_DECLARE_MODULE(reqtimeout) = {
638
    STANDARD20_MODULE_STUFF,
728
    STANDARD20_MODULE_STUFF,
639
    NULL,                           /* create per-dir config structures */
729
    reqtimeout_create_dir_config,   /* create per-dir config structures */
640
    NULL,                           /* merge  per-dir config structures */
730
    reqtimeout_merge_dir_config,    /* merge  per-dir config structures */
641
    reqtimeout_create_srv_config,   /* create per-server config structures */
731
    reqtimeout_create_srv_config,   /* create per-server config structures */
642
    reqtimeout_merge_srv_config,    /* merge per-server config structures */
732
    reqtimeout_merge_srv_config,    /* merge per-server config structures */
643
    reqtimeout_cmds,                /* table of config file commands */
733
    reqtimeout_cmds,                /* table of config file commands */

Return to bug 57439