blob: 9808d17ad11993e85c10d7914524d9bee2820bed [file] [log] [blame] [raw]
// TODO : generalize this into a generic list module, with weight
typedef struct {
ngx_uint_t weight;
ngx_str_t s;
ngx_conf_t *cf;
} ndk_upstream_list_parse_t;
static ngx_int_t
ndk_upstream_list_parse_weight (ndk_upstream_list_parse_t *ulp)
{
size_t i;
ngx_str_t *s;
s = &ulp->s;
for (i=0; i<s->len; i++) {
if (s->data[i] < '0' || s->data[i] > '9')
break;
}
if (!i) {
ulp->weight = 1;
return NGX_OK;
}
if (i == s->len) {
ngx_conf_log_error (NGX_LOG_EMERG, ulp->cf, 0,
"upstream list just consists of number \"%V\"", s);
return NGX_ERROR;
}
if (s->data[i] != ':') {
ngx_conf_log_error (NGX_LOG_EMERG, ulp->cf, 0,
"upstream list not correct format \"%V\"", s);
return NGX_ERROR;
}
ulp->weight = ngx_atoi (s->data, i);
s->data += (i + 1);
s->len -= (i + 1);
return NGX_OK;
}
static char *
ndk_upstream_list (ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
// TODO : change this for getting upstream pointer if available
ngx_uint_t buckets, count, i, j;
ngx_str_t *value, **bucket, *us;
ngx_array_t *ula;
ndk_upstream_list_t *ul, *ule;
ndk_upstream_list_parse_t ulp;
ndk_http_main_conf_t *mcf;
mcf = ngx_http_conf_get_module_main_conf (cf, ndk_http_module);
ula = mcf->upstreams;
// create array of upstream lists it doesn't already exist
if (ula == NULL) {
ula = ngx_array_create (cf->pool, 4, sizeof (ndk_upstream_list_t));
if (ula == NULL)
return NGX_CONF_ERROR;
mcf->upstreams = ula;
}
// check to see if the list already exists
value = cf->args->elts;
value++;
ul = ula->elts;
ule = ul + ula->nelts;
for ( ; ul<ule; ul++) {
if (ul->name.len == value->len &&
ngx_strncasecmp (ul->name.data, value->data, value->len) == 0) {
ngx_conf_log_error (NGX_LOG_EMERG, cf, 0,
"duplicate upstream list name \"%V\"", value);
return NGX_CONF_ERROR;
}
}
// create a new list
ul = ngx_array_push (ula);
if (ul == NULL)
return NGX_CONF_ERROR;
ul->name = *value;
// copy all the upstream names
count = cf->args->nelts - 2;
us = ngx_palloc (cf->pool, count * sizeof (ngx_str_t));
if (us == NULL)
return NGX_CONF_ERROR;
ngx_memcpy (us, value + 1, count * sizeof (ngx_str_t));
// calculate the total number of buckets
buckets = 0;
ulp.cf = cf;
for (i=0; i<count; i++, us++) {
ulp.s = *us;
if (ndk_upstream_list_parse_weight (&ulp) != NGX_OK)
return NGX_CONF_ERROR;
buckets += ulp.weight;
}
// allocate space for all buckets
bucket = ngx_palloc (cf->pool, buckets * sizeof (ngx_str_t **));
if (bucket == NULL)
return NGX_CONF_ERROR;
ul->elts = bucket;
ul->nelts = buckets;
// set values for each bucket
us -= count;
for (i=0; i<count; i++, us++) {
ulp.s = *us;
if (ndk_upstream_list_parse_weight (&ulp) != NGX_OK)
return NGX_CONF_ERROR;
us->data = ulp.s.data;
us->len = ulp.s.len;
// TODO : check format of upstream
// TODO : add automatic adding of http:// in upstreams?
for (j=0; j<ulp.weight; j++, bucket++) {
*bucket = us;
}
}
return NGX_CONF_OK;
}
ndk_upstream_list_t *
ndk_get_upstream_list (ndk_http_main_conf_t *mcf, u_char *data, size_t len)
{
ndk_upstream_list_t *ul, *ule;
ngx_array_t *ua = mcf->upstreams;
if (ua == NULL) {
return NULL;
}
ul = ua->elts;
ule = ul + ua->nelts;
for (; ul < ule; ul++) {
if (ul->name.len == len && ngx_strncasecmp(ul->name.data, data, len) == 0)
{
return ul;
}
}
return NULL;
}