X-Git-Url: https://git.r.bdr.sh/rbdr/ngx_http_office_hours_filter_module/blobdiff_plain/fa2b280d41f583da217a5bdccea67e87cdadffb6..fbdf81df0fdd519191caf70deca4e2918655bdb1:/ngx_http_office_hours_filter_module.c diff --git a/ngx_http_office_hours_filter_module.c b/ngx_http_office_hours_filter_module.c index 5175364..773b6d2 100644 --- a/ngx_http_office_hours_filter_module.c +++ b/ngx_http_office_hours_filter_module.c @@ -20,6 +20,11 @@ * Declarations */ +/* Constants */ + +const ngx_uint_t WEEK_LENGTH = 7; +const char * CLOSED_TOKEN = "closed"; + /* Main Configuration Structure */ typedef struct { @@ -42,6 +47,13 @@ static char *ngx_http_office_hours(ngx_conf_t * cf, ngx_command_t * cmd, static ngx_http_output_body_filter_pt ngx_http_next_body_filter; +/* Utility Functions */ +static ngx_uint_t ** parse_office_hours(ngx_array_t * office_hours); +static ngx_uint_t * parse_office_hours_string(ngx_str_t office_hours); +static ngx_flag_t within_office_hours(ngx_uint_t ** office_hours); +static ngx_uint_t get_day_of_week(time_t time); +static ngx_uint_t get_seconds_of_day(time_t time); + /* * Module Definitions */ @@ -51,7 +63,7 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_command_t ngx_http_office_hours_commands[] = { { ngx_string("office_hours"), - NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_1MORE, + NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1 | NGX_CONF_TAKE2 | NGX_CONF_TAKE3 | NGX_CONF_TAKE4 | NGX_CONF_TAKE5 | NGX_CONF_TAKE6 | NGX_CONF_TAKE7, ngx_http_office_hours, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_office_hours_conf_t, office_hours), @@ -107,30 +119,31 @@ static ngx_int_t ngx_http_office_hours_body_filter(ngx_http_request_t * r, ngx_chain_t * in) { + ngx_uint_t ** parsed_office_hours; ngx_http_office_hours_conf_t *conf; - ngx_uint_t i; - ngx_str_t *hours; conf = ngx_http_get_module_loc_conf(r, ngx_http_office_hours_filter_module); + if (conf->office_hours == NULL) { ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "Within office hours"); + "Office hours disabled"); return ngx_http_next_body_filter(r, in); } - ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "Outside office hours"); + parsed_office_hours = parse_office_hours(conf->office_hours); - hours = conf->office_hours->elts; - - for (i = 0; i < conf->office_hours->nelts; ++i) { + if (within_office_hours(parsed_office_hours)) { ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - (const char *) hours[i].data); + "Within office hours"); + return ngx_http_next_body_filter(r, in); } + ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, + "Outside office hours"); + r->keepalive = 0; return NGX_HTTP_FORBIDDEN; } @@ -147,9 +160,8 @@ static char *ngx_http_office_hours(ngx_conf_t * cf, ngx_command_t * cmd, char *conf_structure = conf; + ngx_str_t *hours, *value; ngx_array_t **office_hours; - ngx_str_t *hours; - ngx_str_t *value; ngx_uint_t i; /* Gets the array from the config structure using the defined @@ -232,3 +244,102 @@ static ngx_int_t ngx_http_office_hours_init(ngx_conf_t * cf) return NGX_OK; } + +/* + * Parse the office hour strings in the configuration file + * to fill out the hours array (in seconds) + */ + +static ngx_uint_t ** parse_office_hours(ngx_array_t * office_hours) +{ + + ngx_str_t *hours; + ngx_uint_t ** parsed_office_hours; + ngx_uint_t i, j; + + parsed_office_hours = malloc(7 * sizeof(ngx_uint_t *)); + + hours = office_hours->elts; + + /* + * On the configuration file, the leftmost element + * always applies to all remaining days, all others + * are read from right to left. So first we will apply + * the initial override, and then iterate based on the + * number of overrides + */ + + for (i = 0; i < WEEK_LENGTH + 1 - office_hours->nelts; ++i) { + parsed_office_hours[i] = parse_office_hours_string(hours[0]); + } + + for (i = 1; i < office_hours->nelts; ++i) { + j = WEEK_LENGTH - office_hours->nelts + i; + parsed_office_hours[j] = parse_office_hours_string(hours[i]); + } + + return parsed_office_hours; +} + +/* + * Given a time string or the closed token, return a tuple + * of numbers representing opening and closing hours + */ + +static ngx_uint_t * parse_office_hours_string(ngx_str_t office_hours) +{ + + ngx_uint_t * parsed_hours; + + parsed_hours = malloc(2 * sizeof(ngx_uint_t)); + + if(ngx_strcmp(office_hours.data, CLOSED_TOKEN) == 0) { + parsed_hours[0] = 0; + parsed_hours[1] = 0; + return parsed_hours; + } + + parsed_hours[0] = 0; + parsed_hours[1] = 86400; + return parsed_hours; +} + +/* + * Given an office hours array, it returns whether or not + * it is currently within office hours. + */ + +static ngx_flag_t within_office_hours(ngx_uint_t ** office_hours) +{ + + time_t now; + ngx_uint_t day_of_week, seconds_of_day; + ngx_uint_t * current_hours; + + ngx_time_update(); + now = ngx_time(); + day_of_week = get_day_of_week(now); + seconds_of_day = get_seconds_of_day(now); + current_hours = office_hours[day_of_week]; + + return seconds_of_day >= current_hours[0] && seconds_of_day <= current_hours[1]; +} + +/* + * Calculate the day of the week given a timestamp + */ +static ngx_uint_t get_day_of_week(time_t time) +{ + + /* Epoch was thursday, so add 3 so we start on monday */ + return (time / 86400 + 3) % 7; +} + +/* + * Calculate the number of seconds elapsed today + */ +static ngx_uint_t get_seconds_of_day(time_t time) +{ + + return time - (time / 86400) * 86400; +}