static ngx_int_t
ngx_lua_http_btt_check_args(ngx_http_request_t *r, ngx_btt_ctx_t *ctx)
{
    u_char              *p;
    struct sockaddr_in  *sin;

    /* TODO: IPv6 */

    ctx->external_ip = ngx_inet_addr(r->connection->addr_text.data,
                                     r->connection->addr_text.len);
    if (ctx->external_ip == INADDR_NONE) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "invalid external ip");
        return NGX_ERROR;
    }

    sin = (struct sockaddr_in *) r->connection->sockaddr;
    ctx->external_port = ntohs(sin->sin_port);

    if (ctx->internal_ip == 0) {
        ctx->internal_ip = ctx->external_ip;
    }

    /* TODO: connection_id */

    p = ngx_cpymem(&ctx->connection_id, &ctx->external_ip,
                   sizeof(ctx->external_ip));
    ngx_memcpy(p, &ctx->internal_port, sizeof(ctx->internal_port));

    return NGX_OK;
}
static in_addr_t
ngx_http_qqwry_real_addr(ngx_http_request_t *r, ngx_http_qqwry_ctx_t *qqwry)
{
    struct sockaddr_in         *sin;
    ngx_http_variable_value_t  *v;

    if (qqwry->index == -1) {
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "http qqwry started: %V", &r->connection->addr_text);

        if (r->connection->sockaddr->sa_family != AF_INET) {
            return 0;
        }

        sin = (struct sockaddr_in *) r->connection->sockaddr;
        return ntohl(sin->sin_addr.s_addr);
    }

    v = ngx_http_get_flushed_variable(r, qqwry->index);

    if (v == NULL || v->not_found) {
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "http qqwry not found");

        return 0;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http qqwry started: %v", v);

    return ntohl(ngx_inet_addr(v->data, v->len));
}
Ejemplo n.º 3
0
ngx_resolver_ctx_t *
ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
{
    in_addr_t            addr;
    ngx_resolver_ctx_t  *ctx;

    if (temp) {
        addr = ngx_inet_addr(temp->name.data, temp->name.len);

        if (addr != INADDR_NONE) {
            temp->resolver = r;
            temp->state = NGX_OK;
            temp->naddrs = 1;
            temp->addrs = &temp->addr;
            temp->addr = addr;
            temp->quick = 1;

            return temp;
        }
    }

    if (r->udp_connections.nelts == 0) {
        return NGX_NO_RESOLVER;
    }

    ctx = ngx_resolver_calloc(r, sizeof(ngx_resolver_ctx_t));

    if (ctx) {
        ctx->resolver = r;
    }

    return ctx;
}
static ngx_http_google_ctx_t *
ngx_http_google_create_ctx(ngx_http_request_t * r)
{
  ngx_http_google_loc_conf_t * glcf;
  glcf = ngx_http_get_module_loc_conf(r, ngx_http_google_filter_module);
  
  ngx_http_google_ctx_t * ctx;
  ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_google_ctx_t));
  
  if (!ctx)       return NULL;
  ctx->host = ngx_pcalloc(r->pool, sizeof(ngx_str_t));
  if (!ctx->host) return NULL;
  ctx->pass = ngx_pcalloc(r->pool, sizeof(ngx_str_t));
  if (!ctx->pass) return NULL;
  ctx->arg  = ngx_pcalloc(r->pool, sizeof(ngx_str_t));
  if (!ctx->arg)  return NULL;
  ctx->domain = ngx_pcalloc(r->pool, sizeof(ngx_str_t));
  if (!ctx->domain) return NULL;
  
  ctx->uri  = &r->unparsed_uri;
  ctx->host = &r->headers_in.host->value;
  ctx->lang = &glcf->language;
  ctx->type = ngx_http_google_type_main;
  
  ngx_str_t domain = *ctx->host;
  
  u_char * last = domain.data + domain.len, * find;
  if ((find = ngx_strlchr(domain.data, last, ':'))) {
    domain.len = find - domain.data;
  }
  
  ctx->domain->len  = domain.len + 1;
  ctx->domain->data = ngx_pcalloc(r->pool, ctx->domain->len);
  if (!ctx->domain->data) return NULL;
  
  ngx_snprintf(ctx->domain->data, ctx->domain->len, ".%V", &domain);
  
  if (ngx_inet_addr(domain.data, domain.len) != INADDR_NONE) {
    ctx->domain->data++;
    ctx->domain->len --;
  }
  
  // default language
  if (!ctx->lang->len) {
    ngx_str_set(ctx->lang, "zh-CN");
  }
  
  ctx->robots = (ctx->uri->len == 11 &&
                 !ngx_strncmp(ctx->uri->data, "/robots.txt", 11));
  
#if (NGX_HTTP_SSL)
  ngx_http_ssl_srv_conf_t * sscf;
  sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
  if (sscf->enable == 1) ctx->ssl = 1;
#endif
  
  return ctx;
}
static void ngx_http_authen_pass(ngx_http_authen_conf_t *cf, ngx_http_request_t *r)
{
//    pid_t pid;
    char address[64];
    struct sockaddr_in sa;
    socklen_t salen;
    ngx_str_t *addr;

    addr = &r->connection->addr_text;

    if (cf->addr.len == 0 || cf->addr.data == NULL) {
        ngx_log_stderr(NGX_OK, "Missing Authen IP address");
        return;
    }

    if (addr->len >= sizeof(address)) {
        ngx_log_stderr(NGX_OK, "%V too long", addr);
        return;
    }
    ngx_memcpy(address, (char *)addr->data, addr->len);
    address[addr->len] = '\0';

    salen = sizeof(sa);
    ngx_memzero(&sa, salen);
    sa.sin_family = AF_INET;
    if (cf->port == NGX_CONF_UNSET) {
        sa.sin_port = htons((uint16_t)NGX_HTTP_AUTHEN_PORT_DEFAULT);
    } else {
        sa.sin_port = htons((uint16_t)cf->port);
    }
    sa.sin_addr.s_addr = ngx_inet_addr(cf->addr.data, cf->addr.len);

//    if ((pid = fork()) < 0) {
//        ngx_log_stderr(NGX_OK, "Fork() failed.");
//        return;
//    } else if (pid == 0) {
//        /* 子进程,通知设备开启认证 */
        ngx_http_authen_pass_do(&sa, address, r);
//        exit(0);
//    } else {
//        /* 父进程无操作 */
//    }

    return;
}
static in_addr_t
ngx_http_qqwry_addr(ngx_http_request_t *r, ngx_http_qqwry_ctx_t *qqwry)
{
    u_char           *ip;
    u_char           *p;
    u_char           *pe;
    size_t            len;
    in_addr_t         addr;
    in_addr_t         addr_tmp;
    ngx_table_elt_t  *xfwd;

    addr = ngx_http_qqwry_real_addr(r, qqwry);
    //if (ngx_http_qqwry_is_public_addr(addr)) {
    //    return addr;
    //}

    xfwd = r->headers_in.x_forwarded_for;
    if (xfwd == NULL) {
        return addr;
    }

    for (pe = xfwd->value.data + xfwd->value.len; pe > xfwd->value.data && (*pe < '0' || *pe > '9'); pe--);
    p = pe - 1;
    while (p >= xfwd->value.data) {
        if ((*p < '0' || *p > '9') && *p != '.') {
            len = pe - p;
            ip = p + 1;
        } else if (p == xfwd->value.data) {
            len = pe - p + 1;
            ip = p;
        } else {
            p--;
            continue;
        }

        addr_tmp = ntohl(ngx_inet_addr(ip, len));
        if (ngx_http_qqwry_is_public_addr(addr_tmp)) {
            return addr_tmp;
        }
        for (pe = p; pe > xfwd->value.data && (*pe < '0' || *pe > '9'); pe--);
        p = pe - 1;
    }

    return addr;
}
static ngx_int_t
ngx_http_upstream_init_dynamic(ngx_conf_t *cf,
    ngx_http_upstream_srv_conf_t *us)
{
    ngx_uint_t                             i;
    ngx_http_upstream_dynamic_srv_conf_t  *dcf;
    ngx_http_upstream_server_t            *server;
    ngx_str_t                              host;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
                   "init dynamic resolve");

    dcf = ngx_http_conf_upstream_srv_conf(us,
                                          ngx_http_upstream_dynamic_module);

    if (dcf->original_init_upstream(cf, us) != NGX_OK) {
        return NGX_ERROR;
    }

    if (us->servers) {
        server = us->servers->elts;

        for (i = 0; i < us->servers->nelts; i++) {
            host = server[i].host;
            if (ngx_inet_addr(host.data, host.len) == INADDR_NONE) {
                break;
            }
        }

        if (i == us->servers->nelts) {
            dcf->enabled = 0;

            return NGX_OK;
        }
    }

    dcf->original_init_peer = us->peer.init;

    us->peer.init = ngx_http_upstream_init_dynamic_peer;

    dcf->enabled = 1;

    return NGX_OK;
}
static char *ngx_conf_set_authen_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_authen_conf_t *authencf = conf;
    ngx_str_t *value = cf->args->elts;

    if (cf->args->nelts > 1) {
        authencf->addr = value[1];
        if (ngx_inet_addr(authencf->addr.data, authencf->addr.len) == INADDR_NONE) {
            return "Invalid: Authen IP address";
        }
    }
    if (cf->args->nelts > 2) {
        authencf->port = ngx_atoi(value[2].data, value[2].len);
        if (authencf->port == NGX_ERROR) {
            return "Invalid: Authen UDP port";
        }
    }

    return NGX_CONF_OK;
}
Ejemplo n.º 9
0
static void
ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
    ngx_mail_auth_http_ctx_t *ctx)
{
    u_char              *p;
    time_t               timer;
    size_t               len, size;
    ngx_int_t            rc, port, n;
    ngx_addr_t          *peer;
    struct sockaddr_in  *sin;

    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                   "mail auth http process headers");

    for ( ;; ) {
        rc = ngx_mail_auth_http_parse_header_line(s, ctx);

        if (rc == NGX_OK) {

#if (NGX_DEBUG)
            {
            ngx_str_t  key, value;

            key.len = ctx->header_name_end - ctx->header_name_start;
            key.data = ctx->header_name_start;
            value.len = ctx->header_end - ctx->header_start;
            value.data = ctx->header_start;

            ngx_log_debug2(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                           "mail auth http header: \"%V: %V\"",
                           &key, &value);
            }
#endif

            len = ctx->header_name_end - ctx->header_name_start;

            if (len == sizeof("Auth-Status") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Status",
                                   sizeof("Auth-Status") - 1)
                   == 0)
            {
                len = ctx->header_end - ctx->header_start;

                if (len == 2
                    && ctx->header_start[0] == 'O'
                    && ctx->header_start[1] == 'K')
                {
                    continue;
                }

                if (len == 4
                    && ctx->header_start[0] == 'W'
                    && ctx->header_start[1] == 'A'
                    && ctx->header_start[2] == 'I'
                    && ctx->header_start[3] == 'T')
                {
                    s->auth_wait = 1;
                    continue;
                }

                ctx->errmsg.len = len;
                ctx->errmsg.data = ctx->header_start;

                switch (s->protocol) {

                case NGX_MAIL_POP3_PROTOCOL:
                    size = sizeof("-ERR ") - 1 + len + sizeof(CRLF) - 1;
                    break;

                case NGX_MAIL_IMAP_PROTOCOL:
                    size = s->tag.len + sizeof("NO ") - 1 + len
                           + sizeof(CRLF) - 1;
                    break;

                default: /* NGX_MAIL_SMTP_PROTOCOL */
                    ctx->err = ctx->errmsg;
                    continue;
                }

                p = ngx_pnalloc(s->connection->pool, size);
                if (p == NULL) {
                    ngx_close_connection(ctx->peer.connection);
                    ngx_destroy_pool(ctx->pool);
                    ngx_mail_session_internal_server_error(s);
                    return;
                }

                ctx->err.data = p;

                switch (s->protocol) {

                case NGX_MAIL_POP3_PROTOCOL:
                    *p++ = '-'; *p++ = 'E'; *p++ = 'R'; *p++ = 'R'; *p++ = ' ';
                    break;

                case NGX_MAIL_IMAP_PROTOCOL:
                    p = ngx_cpymem(p, s->tag.data, s->tag.len);
                    *p++ = 'N'; *p++ = 'O'; *p++ = ' ';
                    break;

                default: /* NGX_MAIL_SMTP_PROTOCOL */
                    break;
                }

                p = ngx_cpymem(p, ctx->header_start, len);
                *p++ = CR; *p++ = LF;

                ctx->err.len = p - ctx->err.data;

                continue;
            }

            if (len == sizeof("Auth-Server") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Server",
                                   sizeof("Auth-Server") - 1)
                    == 0)
            {
                ctx->addr.len = ctx->header_end - ctx->header_start;
                ctx->addr.data = ctx->header_start;

                continue;
            }

            if (len == sizeof("Auth-Port") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Port",
                                   sizeof("Auth-Port") - 1)
                   == 0)
            {
                ctx->port.len = ctx->header_end - ctx->header_start;
                ctx->port.data = ctx->header_start;

                continue;
            }

            if (len == sizeof("Auth-User") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-User",
                                   sizeof("Auth-User") - 1)
                   == 0)
            {
                s->login.len = ctx->header_end - ctx->header_start;

                s->login.data = ngx_pnalloc(s->connection->pool, s->login.len);
                if (s->login.data == NULL) {
                    ngx_close_connection(ctx->peer.connection);
                    ngx_destroy_pool(ctx->pool);
                    ngx_mail_session_internal_server_error(s);
                    return;
                }

                ngx_memcpy(s->login.data, ctx->header_start, s->login.len);

                continue;
            }

            if (len == sizeof("Auth-Pass") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Pass",
                                   sizeof("Auth-Pass") - 1)
                   == 0)
            {
                s->passwd.len = ctx->header_end - ctx->header_start;

                s->passwd.data = ngx_pnalloc(s->connection->pool,
                                             s->passwd.len);
                if (s->passwd.data == NULL) {
                    ngx_close_connection(ctx->peer.connection);
                    ngx_destroy_pool(ctx->pool);
                    ngx_mail_session_internal_server_error(s);
                    return;
                }

                ngx_memcpy(s->passwd.data, ctx->header_start, s->passwd.len);

                continue;
            }

            if (len == sizeof("Auth-Wait") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Wait",
                                   sizeof("Auth-Wait") - 1)
                   == 0)
            {
                n = ngx_atoi(ctx->header_start,
                             ctx->header_end - ctx->header_start);

                if (n != NGX_ERROR) {
                    ctx->sleep = n;
                }

                continue;
            }

            if (len == sizeof("Auth-Error-Code") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Error-Code",
                                   sizeof("Auth-Error-Code") - 1)
                   == 0)
            {
                ctx->errcode.len = ctx->header_end - ctx->header_start;

                ctx->errcode.data = ngx_pnalloc(s->connection->pool,
                                                ctx->errcode.len);
                if (ctx->errcode.data == NULL) {
                    ngx_close_connection(ctx->peer.connection);
                    ngx_destroy_pool(ctx->pool);
                    ngx_mail_session_internal_server_error(s);
                    return;
                }

                ngx_memcpy(ctx->errcode.data, ctx->header_start,
                           ctx->errcode.len);

                continue;
            }

            /* ignore other headers */

            continue;
        }

        if (rc == NGX_DONE) {
            ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                           "mail auth http header done");

            ngx_close_connection(ctx->peer.connection);

            if (ctx->err.len) {

                ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
                              "client login failed: \"%V\"", &ctx->errmsg);

                if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) {

                    if (ctx->errcode.len == 0) {
                        ctx->errcode = ngx_mail_smtp_errcode;
                    }

                    ctx->err.len = ctx->errcode.len + ctx->errmsg.len
                                   + sizeof(" " CRLF) - 1;

                    p = ngx_pnalloc(s->connection->pool, ctx->err.len);
                    if (p == NULL) {
                        ngx_close_connection(ctx->peer.connection);
                        ngx_destroy_pool(ctx->pool);
                        ngx_mail_session_internal_server_error(s);
                        return;
                    }

                    ctx->err.data = p;

                    p = ngx_cpymem(p, ctx->errcode.data, ctx->errcode.len);
                    *p++ = ' ';
                    p = ngx_cpymem(p, ctx->errmsg.data, ctx->errmsg.len);
                    *p++ = CR; *p = LF;
                }

                s->out = ctx->err;
                timer = ctx->sleep;

                ngx_destroy_pool(ctx->pool);

                if (timer == 0) {
                    s->quit = 1;
                    ngx_mail_send(s->connection->write);
                    return;
                }

                ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));

                s->connection->read->handler = ngx_mail_auth_sleep_handler;

                return;
            }

            if (s->auth_wait) {
                timer = ctx->sleep;

                ngx_destroy_pool(ctx->pool);

                if (timer == 0) {
                    ngx_mail_auth_http_init(s);
                    return;
                }

                ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));

                s->connection->read->handler = ngx_mail_auth_sleep_handler;

                return;
            }

            if (ctx->addr.len == 0 || ctx->port.len == 0) {
                ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                              "auth http server %V did not send server or port",
                              ctx->peer.name);
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            if (s->passwd.data == NULL
                && s->protocol != NGX_MAIL_SMTP_PROTOCOL)
            {
                ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                              "auth http server %V did not send password",
                              ctx->peer.name);
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_addr_t));
            if (peer == NULL) {
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            /* AF_INET only */

            sin = ngx_pcalloc(s->connection->pool, sizeof(struct sockaddr_in));
            if (sin == NULL) {
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            sin->sin_family = AF_INET;

            port = ngx_atoi(ctx->port.data, ctx->port.len);
            if (port == NGX_ERROR || port < 1 || port > 65535) {
                ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                              "auth http server %V sent invalid server "
                              "port:\"%V\"",
                              ctx->peer.name, &ctx->port);
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            sin->sin_port = htons((in_port_t) port);

            sin->sin_addr.s_addr = ngx_inet_addr(ctx->addr.data, ctx->addr.len);
            if (sin->sin_addr.s_addr == INADDR_NONE) {
                ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                              "auth http server %V sent invalid server "
                              "address:\"%V\"",
                              ctx->peer.name, &ctx->addr);
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            peer->sockaddr = (struct sockaddr *) sin;
            peer->socklen = sizeof(struct sockaddr_in);

            len = ctx->addr.len + 1 + ctx->port.len;

            peer->name.len = len;

            peer->name.data = ngx_pnalloc(s->connection->pool, len);
            if (peer->name.data == NULL) {
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            len = ctx->addr.len;

            ngx_memcpy(peer->name.data, ctx->addr.data, len);

            peer->name.data[len++] = ':';

            ngx_memcpy(peer->name.data + len, ctx->port.data, ctx->port.len);

            ngx_destroy_pool(ctx->pool);
            ngx_mail_proxy_init(s, peer);

            return;
        }

        if (rc == NGX_AGAIN ) {
            return;
        }

        /* rc == NGX_ERROR */

        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                      "auth http server %V sent invalid header in response",
                      ctx->peer.name);
        ngx_close_connection(ctx->peer.connection);
        ngx_destroy_pool(ctx->pool);
        ngx_mail_session_internal_server_error(s);

        return;
    }
}
static ngx_int_t
ngx_lua_http_btt_parse_args(ngx_http_request_t *r, ngx_btt_ctx_t *ctx)
{
    size_t   nlen, vlen;
    u_char  *p, *last, *name, *val, *dst, *src;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "lua http btt parse args");

    if (r->args.len == 0) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "invalid uri \"%V\"", &r->args);
        return NGX_ERROR;
    }

    p = r->args.data;
    last = p + r->args.len;

    for ( /* void */ ; p < last; p++) {

        name = p;

        p = ngx_strlchr(p, last, '&');

        if (p == NULL) {
            p = last;
        }

        val = ngx_strlchr(name, p, '=');

        if (val == NULL) {
            val = p;
        }

        nlen = val - name;
        vlen = (++val < p) ? p - val : 0;

        dst = ngx_pnalloc(r->pool, vlen);
        if (dst == NULL) {
            return NGX_ERROR;
        }

        src = val;
        val = dst;
        ngx_unescape_uri(&dst, &src, vlen, 0);
        vlen = dst - val;

        ngx_log_debug4(NGX_LOG_ALERT, r->connection->log, 0,
                       "%*s=%*s", nlen, name, vlen, val);

        /*
         * BT Client:
         *
         *   BitComet: localip, natmapped, port_type
         *   NetTransport: supportcrypto
         *   uTorrent: corrupt
         *   XunLei: ip
         */

        switch (nlen) {

        case 2:

            if (ngx_strncmp(name, "ip", nlen) == 0) {
                ctx->internal_ip = ngx_inet_addr(val, vlen);
                if (ctx->internal_ip == INADDR_NONE) {
                    goto invalid;
                }
                break;
            }

            break;

        case 3:

            if (ngx_strncmp(name, "key", nlen) == 0) {
                ngx_memcpy(ctx->key, val, vlen);
                break;
            }

            break;

        case 4:

            if (ngx_strncmp(name, "port", nlen) == 0) {
                ctx->internal_port = (in_port_t) ngx_atoi(val, vlen);
                if (ctx->internal_port == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            if (ngx_strncmp(name, "left", nlen) == 0) {
                ctx->left = ngx_atoof(val, vlen);
                if (ctx->left == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            break;

        case 5:

            if (ngx_strncmp(name, "event", nlen) == 0) {

                if (ngx_strncmp(val, "none", sizeof("none") - 1) == 0) {
                    ctx->event = NGX_BTT_EVENT_NONE;

                } else if (ngx_strncmp(val, "completed",
                                       sizeof("completed") - 1)
                           == 0)
                {
                    ctx->event = NGX_BTT_EVENT_COMPLETED;

                } else if (ngx_strncmp(val, "started", sizeof("started") - 1)
                           == 0)
                {
                    ctx->event = NGX_BTT_EVENT_STARTED;

                } else if (ngx_strncmp(val, "stopped", sizeof("stopped") - 1)
                           == 0)
                {
                    ctx->event = NGX_BTT_EVENT_STOPPED;

                } else {
                    goto invalid;
                }

                break;
            }

            break;

        case 7:

            if (ngx_strncmp(name, "peer_id", nlen) == 0) {
                ngx_memcpy(ctx->peer_id, val, vlen);
                break;
            }

            if (ngx_strncmp(name, "localip", nlen) == 0) {
                ctx->internal_ip = ngx_inet_addr(val, vlen);
                if (ctx->internal_ip == INADDR_NONE) {
                    goto invalid;
                }
                break;
            }

            if (ngx_strncmp(name, "numwant", nlen) == 0) {
                ctx->numwant = ngx_atoi(val, vlen);
                if (ctx->numwant == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            if (ngx_strncmp(name, "compact", nlen) == 0) {
                ctx->compact = ngx_atoi(val, vlen);
                if (ctx->compact == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            if (ngx_strncmp(name, "corrupt", nlen) == 0) {
                ctx->corrupt = ngx_atoi(val, vlen);
                if (ctx->corrupt == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            break;

        case 8:

            if (ngx_strncmp(name, "uploaded", nlen) == 0) {
                ctx->uploaded = ngx_atoof(val, vlen);
                if (ctx->uploaded == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            break;

        case 9:

            if (ngx_strncmp(name, "info_hash ", nlen) == 0) {
                ngx_memcpy(ctx->info_hash, val, vlen);
                break;
            }

            if (ngx_strncmp(name, "natmapped ", nlen) == 0) {
                ctx->natmapped = ngx_atoi(val, vlen);
                if (ctx->natmapped == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            if (ngx_strncmp(name, "port_type", nlen) == 0) {
                ngx_memcpy(ctx->port_type, val, vlen);
                break;
            }

            break;

        case 10:

            if (ngx_strncmp(name, "downloaded", nlen) == 0) {
                ctx->downloaded = ngx_atoof(val, vlen);
                if (ctx->downloaded == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            if (ngx_strncmp(name, "no_peer_id ", nlen) == 0) {
                ctx->no_peer_id = ngx_atoi(val, vlen);
                if (ctx->no_peer_id == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            break;

        case 13:

            if (ngx_strncmp(name, "supportcrypto", nlen) == 0) {
                ctx->supportcrypto = ngx_atoi(val, vlen);
                if (ctx->supportcrypto == NGX_ERROR) {
                    goto invalid;
                }
                break;
            }

            break;

        default:
            break;
        }
    }

    return NGX_OK;

invalid:

    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                  "invalid value \"%*s\" of the key \"%*s\"",
                  nlen, name, vlen, val);

    return NGX_ERROR;
}
Ejemplo n.º 11
0
static ngx_int_t
ngx_stream_proxy_ssl_name(ngx_stream_session_t *s)
{
    u_char                       *p, *last;
    ngx_str_t                     name;
    ngx_stream_upstream_t        *u;
    ngx_stream_proxy_srv_conf_t  *pscf;

    pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);

    u = s->upstream;

    name = pscf->ssl_name;

    if (name.len == 0) {
        name = pscf->upstream->host;
    }

    if (name.len == 0) {
        goto done;
    }

    /*
     * ssl name here may contain port, strip it for compatibility
     * with the http module
     */

    p = name.data;
    last = name.data + name.len;

    if (*p == '[') {
        p = ngx_strlchr(p, last, ']');

        if (p == NULL) {
            p = name.data;
        }
    }

    p = ngx_strlchr(p, last, ':');

    if (p != NULL) {
        name.len = p - name.data;
    }

    if (!pscf->ssl_server_name) {
        goto done;
    }

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME

    /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */

    if (name.len == 0 || *name.data == '[') {
        goto done;
    }

    if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) {
        goto done;
    }

    /*
     * SSL_set_tlsext_host_name() needs a null-terminated string,
     * hence we explicitly null-terminate name here
     */

    p = ngx_pnalloc(s->connection->pool, name.len + 1);
    if (p == NULL) {
        return NGX_ERROR;
    }

    (void) ngx_cpystrn(p, name.data, name.len + 1);

    name.data = p;

    ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
                   "upstream SSL server name: \"%s\"", name.data);

    if (SSL_set_tlsext_host_name(u->peer.connection->ssl->connection, name.data)
        == 0)
    {
        ngx_ssl_error(NGX_LOG_ERR, s->connection->log, 0,
                      "SSL_set_tlsext_host_name(\"%s\") failed", name.data);
        return NGX_ERROR;
    }

#endif

done:

    u->ssl_name = name;

    return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_get_dynamic_peer(ngx_peer_connection_t *pc, void *data)
{
    ngx_http_upstream_dynamic_peer_data_t  *bp = data;
    ngx_http_request_t                     *r;
    ngx_http_core_loc_conf_t               *clcf;
    ngx_resolver_ctx_t                     *ctx, temp;
    ngx_http_upstream_t                    *u;
    ngx_int_t                               rc;
    ngx_http_upstream_dynamic_srv_conf_t   *dscf;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                   "get dynamic peer");

    /* The "get" function will be called twice if
     * one host is resolved into an IP address.
     * (via 'ngx_http_upstream_connect' if resolved successfully)
     *
     * So here we need to determine if it is the first
     * time call or the second time call.
     */
    if (pc->resolved == NGX_HTTP_UPSTREAM_DR_OK) {
        return NGX_OK;
    }

    dscf = bp->conf;
    r = bp->request;
    u = r->upstream;

    if (pc->resolved == NGX_HTTP_UPSTREAM_DR_FAILED) {

        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                       "resolve failed! fallback: %ui", dscf->fallback);

        switch (dscf->fallback) {

        case NGX_HTTP_UPSTREAM_DYN_RESOLVE_STALE:
            return NGX_OK;

        case NGX_HTTP_UPSTREAM_DYN_RESOLVE_SHUTDOWN:
            ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
            return NGX_YIELD;

        default:
            /* default fallback action: check next upstream */
            return NGX_DECLINED;
        }

        return NGX_DECLINED;
    }

    if (dscf->fail_check
        && (ngx_time() - dscf->fail_check < dscf->fail_timeout))
    {
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                       "in fail timeout period, fallback: %ui", dscf->fallback);

        switch (dscf->fallback) {

        case NGX_HTTP_UPSTREAM_DYN_RESOLVE_STALE:
            return bp->original_get_peer(pc, bp->data);

        case NGX_HTTP_UPSTREAM_DYN_RESOLVE_SHUTDOWN:
            ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
            return NGX_YIELD;

        default:
            /* default fallback action: check next upstream, still need
             * to get peer in fail timeout period
             */
            return bp->original_get_peer(pc, bp->data);
        }

        return NGX_DECLINED;
    }

    /* NGX_HTTP_UPSTREAM_DYN_RESOLVE_INIT,  ask balancer */

    rc = bp->original_get_peer(pc, bp->data);

    if (rc != NGX_OK) {
        return rc;
    }

    /* resolve name */

    if (pc->host == NULL) {
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                       "load balancer doesn't support dyn resolve!");
        return NGX_OK;
    }

    if (ngx_inet_addr(pc->host->data, pc->host->len) != INADDR_NONE) {
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                       "host is an IP address, connect directly!");
        return NGX_OK;
    }

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    if (clcf->resolver == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "resolver has not been configured!");
        return NGX_OK;
    }

    temp.name = *pc->host;

    ctx = ngx_resolve_start(clcf->resolver, &temp);
    if (ctx == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "resolver start failed!");
        return NGX_OK;
    }

    if (ctx == NGX_NO_RESOLVER) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "resolver started but no resolver!");
        return NGX_OK;
    }

    ctx->name = *pc->host;
    /* TODO remove */
    // ctx->type = NGX_RESOLVE_A;
    /* END */
    ctx->handler = ngx_http_upstream_dynamic_handler;
    ctx->data = r;
    ctx->timeout = clcf->resolver_timeout;

    u->dyn_resolve_ctx = ctx;

    if (ngx_resolve_name(ctx) != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, pc->log, 0,
                      "resolver name failed!\n");

        u->dyn_resolve_ctx = NULL;

        return NGX_OK;
    }

    return NGX_YIELD;
}
ngx_int_t
ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
    ngx_http_upstream_srv_conf_t *us)
{
    ngx_url_t                      u;
    ngx_uint_t                     i, j, n, w, color;
    ngx_uint_t                     dyn_resolve = 0;
    ngx_http_upstream_server_t    *server;
    ngx_http_upstream_rr_peers_t  *peers, *backup;
    u_char                         addr6[NGX_INET6_ADDRSTRLEN];


    us->peer.init = ngx_http_upstream_init_round_robin_peer;

    if (us->servers) {
        server = us->servers->elts;

        n = 0;
        w = 0;

        for (i = 0; i < us->servers->nelts; i++) {
            if (server[i].backup) {
                continue;
            }

            n += server[i].naddrs;
            w += server[i].naddrs * server[i].weight;
        }

        if (n == 0) {
            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                          "no servers in upstream \"%V\" in %s:%ui",
                          &us->host, us->file_name, us->line);
            return NGX_ERROR;
        }

        peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
                              + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
        if (peers == NULL) {
            return NGX_ERROR;
        }

        peers->single = (n == 1);
        peers->number = n;
        peers->weighted = (w != n);
        peers->total_weight = w;
        peers->name = &us->host;

        n = 0;
        color = 1;

        for (i = 0; i < us->servers->nelts; i++) {
            if (server[i].backup) {
                continue;
            }

#if (NGX_HAVE_INET6)
            dyn_resolve = (ngx_inet6_addr(server[i].host.data,
                        server[i].host.len, addr6) == NGX_ERROR) ? 1 : 0;
            if (dyn_resolve)
                /* host is not an ipv6 address, check ipv4 */

#endif
            {
                dyn_resolve = (ngx_inet_addr(server[i].host.data,
                            server[i].host.len) == INADDR_NONE) ? 1 : 0;
            }

            for (j = 0; j < server[i].naddrs; j++) {
                peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
                peers->peer[n].socklen = server[i].addrs[j].socklen;
                peers->peer[n].name = server[i].addrs[j].name;
                peers->peer[n].host = server[i].host;
                peers->peer[n].weight = server[i].weight;
                peers->peer[n].effective_weight = server[i].weight;
                peers->peer[n].current_weight = 0;
                peers->peer[n].max_fails = server[i].max_fails;
                peers->peer[n].fail_timeout = server[i].fail_timeout;
                peers->peer[n].down = server[i].down;
                peers->peer[n].color = color;
                peers->peer[n].dyn_resolve = dyn_resolve;

#if (NGX_HTTP_UPSTREAM_CHECK)
                if (!server[i].down) {
                    peers->peer[n].check_index =
                        ngx_http_upstream_check_add_peer(cf, us,
                                &server[i].addrs[j]);
                } else {
                    peers->peer[n].check_index = (ngx_uint_t) NGX_ERROR;
                }
#endif

                n++;
            }

            color++;
        }

        us->peer.data = peers;

        /* backup servers */

        n = 0;
        w = 0;

        for (i = 0; i < us->servers->nelts; i++) {
            if (!server[i].backup) {
                continue;
            }

            n += server[i].naddrs;
            w += server[i].naddrs * server[i].weight;
        }

        if (n == 0) {
            return NGX_OK;
        }

        backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
                              + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
        if (backup == NULL) {
            return NGX_ERROR;
        }

        peers->single = 0;
        backup->single = 0;
        backup->number = n;
        backup->weighted = (w != n);
        backup->total_weight = w;
        backup->name = &us->host;

        n = 0;

        for (i = 0; i < us->servers->nelts; i++) {
            if (!server[i].backup) {
                continue;
            }

#if (NGX_HAVE_INET6)
                dyn_resolve = (ngx_inet6_addr(server[i].host.data,
                            server[i].host.len, addr6) == NGX_ERROR) ? 1 : 0;
                if (dyn_resolve)
                    /* host is not an ipv6 address, check ipv4 */

#endif
                {
                    dyn_resolve = (ngx_inet_addr(server[i].host.data,
                                server[i].host.len) == INADDR_NONE) ? 1 : 0;
                }

            for (j = 0; j < server[i].naddrs; j++) {
                backup->peer[n].sockaddr = server[i].addrs[j].sockaddr;
                backup->peer[n].socklen = server[i].addrs[j].socklen;
                backup->peer[n].name = server[i].addrs[j].name;
                backup->peer[n].host = server[i].host;
                backup->peer[n].weight = server[i].weight;
                backup->peer[n].effective_weight = server[i].weight;
                backup->peer[n].current_weight = 0;
                backup->peer[n].max_fails = server[i].max_fails;
                backup->peer[n].fail_timeout = server[i].fail_timeout;
                backup->peer[n].down = server[i].down;
                backup->peer[n].color = color;
                backup->peer[n].dyn_resolve = dyn_resolve;

#if (NGX_HTTP_UPSTREAM_CHECK)
                if (!server[i].down) {
                    backup->peer[n].check_index =
                        ngx_http_upstream_check_add_peer(cf, us,
                                &server[i].addrs[j]);
                } else {
                    backup->peer[n].check_index = (ngx_uint_t) NGX_ERROR;
                }
#endif

                n++;
            }

            color++;
        }

        peers->next = backup;

        return NGX_OK;
    }


    /* an upstream implicitly defined by proxy_pass, etc. */

    if (us->port == 0) {
        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                      "no port in upstream \"%V\" in %s:%ui",
                      &us->host, us->file_name, us->line);
        return NGX_ERROR;
    }

    ngx_memzero(&u, sizeof(ngx_url_t));

    u.host = us->host;
    u.port = us->port;

    if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
        if (u.err) {
            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                          "%s in upstream \"%V\" in %s:%ui",
                          u.err, &us->host, us->file_name, us->line);
        }

        return NGX_ERROR;
    }

    n = u.naddrs;

    peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
                              + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
    if (peers == NULL) {
        return NGX_ERROR;
    }

    peers->single = (n == 1);
    peers->number = n;
    peers->weighted = 0;
    peers->total_weight = n;
    peers->name = &us->host;

#if (NGX_HAVE_INET6)
    dyn_resolve = (ngx_inet6_addr(u.host.data,
                u.host.len, addr6) == NGX_ERROR) ? 1 : 0;
    if (dyn_resolve)
        /* host is not an ipv6 address, check ipv4 */

#endif
    {
        dyn_resolve = (ngx_inet_addr(u.host.data,
                    u.host.len) == INADDR_NONE) ? 1 : 0;
    }

    for (i = 0; i < u.naddrs; i++) {
        peers->peer[i].sockaddr = u.addrs[i].sockaddr;
        peers->peer[i].socklen = u.addrs[i].socklen;
        peers->peer[i].name = u.addrs[i].name;
        peers->peer[i].host = u.host;
        peers->peer[i].weight = 1;
        peers->peer[i].effective_weight = 1;
        peers->peer[i].current_weight = 0;
        peers->peer[i].max_fails = 1;
        peers->peer[i].fail_timeout = 10;
#if (NGX_HTTP_UPSTREAM_CHECK)
        peers->peer[i].check_index = (ngx_uint_t) NGX_ERROR;
#endif
        peers->peer[i].color = 0;
        peers->peer[i].dyn_resolve = dyn_resolve;
    }

    us->peer.data = peers;

    /* implicitly defined upstream has no backup servers */

    return NGX_OK;
}
void
ngx_http_cloudrouter_peer_preconnect(ngx_http_request_t *r, ngx_http_upstream_t *u) {
    ngx_int_t rc;
    ngx_peer_connection_t *c;
    struct sockaddr_in *sin;
    ngx_http_cloudrouter_peer_preconnect_data_t *pcd;
    ngx_http_cleanup_t *cln;
    ngx_http_cloudrouter_peer_t *peer;

    r->connection->log->action = "connecting to cloudrouter agent";

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "preconnect");

    c = ngx_pcalloc(r->connection->pool, sizeof(ngx_peer_connection_t));
    sin = ngx_pcalloc(r->connection->pool, sizeof(struct sockaddr_in));
    pcd = ngx_pcalloc(r->connection->pool, sizeof(ngx_http_cloudrouter_peer_preconnect_data_t));
    peer = (ngx_http_cloudrouter_peer_t*)u->peer.data;

    if (sin==NULL || c==NULL || pcd==NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "preconnect: cannot allocate sin/c/pcd");
        return;
    }

    /* FIXME: should cache this */
    sin->sin_family = AF_INET;
    sin->sin_port = htons(9091);
    ngx_str_t localhost;
    ngx_str_set(&localhost, "127.0.0.1");
    sin->sin_addr.s_addr = ngx_inet_addr(localhost.data, localhost.len);

    c->sockaddr = (struct sockaddr *)sin;
    c->socklen = sizeof(struct sockaddr_in);
    c->get = ngx_event_get_peer; // dummy method returning the peer itself.
    c->log = r->connection->log;
    c->log_error = r->connection->log_error;
    c->name = ngx_pcalloc(r->connection->pool, sizeof *c->name);
    if (c->name == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "preconnect: cannot allocate c->name");
        return;
    }
    ngx_str_set(c->name, "127.0.0.1:9091");

    rc = ngx_event_connect_peer(c);
    if (rc==NGX_ERROR || rc==NGX_BUSY || rc==NGX_DECLINED) {
        ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                      "preconnect very much unsuccessful.");
        if (c->connection) {
            ngx_close_connection(c->connection); c->connection->destroyed = 1;
        }
        ngx_http_upstream_next(r,u,NGX_HTTP_UPSTREAM_FT_ERROR);
        return;
    }

    r->main->count++;

    pcd->r = r;
    pcd->u = u;
    pcd->sendbufpos = 0;
    if (peer->route==NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "ROUTE is null in preconnect!");
        ngx_log_debug(NGX_LOG_ERR, r->connection->log, 0,
                      "ROUTE is null in preconnect!");
        ngx_http_upstream_next(r,u,NGX_HTTP_UPSTREAM_FT_ERROR);
        return;
    }
    (void)ngx_copy(&pcd->route,peer->route, sizeof(hs_route_t));
    pcd->c = c->connection;

    c->connection->data = pcd;
    c->connection->pool = r->connection->pool;

    c->connection->read->handler = ngx_http_cloudrouter_peer_preconnect_read;
    c->connection->write->handler = ngx_http_cloudrouter_peer_preconnect_write;

    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "preconnect successful.");

    ngx_add_timer(c->connection->read, 10000);
    ngx_add_timer(c->connection->write, 10000);

    cln = ngx_http_cleanup_add(r, 0);
    cln->data = pcd;
    cln->handler = ngx_http_cloudrouter_preconnect_cleanup;
}
static void
ngx_http_cloudrouter_peer_preconnect_read(ngx_event_t *rev) {
    ngx_connection_t    *c;
    ngx_http_cloudrouter_peer_preconnect_data_t *pcd;
    ngx_http_upstream_t *u;
    ngx_http_request_t  *r;
    int                 i;
    hs_route_t         *route;

    c   = rev->data;
    pcd = c->data;

    r   = pcd->r;
    u   = pcd->u;

    route = &pcd->route;

    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "preconnect: read");

    if (pcd->done>0) {
        return;
    }

    if (r->main==NULL||r->request_complete||r->pool==NULL||r!=r->main) {
        ngx_close_connection(c); c->destroyed = 1;
        return;
    }

    if (rev->timedout) {
        ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
                      "cloudrouter preconnect server timed out");
        return ngx_http_cloudrouter_peer_preconnect_close(c, pcd, NGX_ERROR);
    }

    if (pcd->buf==NULL) {
        int size = sizeof(char)*1000;
        ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "creating buf");
        pcd->buf = ngx_pcalloc(r->pool, size);
        pcd->bufend = pcd->buf+size;
        pcd->bufpos = pcd->buf;

        if (pcd->buf==NULL) {
            ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ENOMEM,
                          "preconnect: read: could not allocate buf");
            return ngx_http_cloudrouter_peer_preconnect_close(c, pcd, NGX_ERROR);
        }
    }

    /*
     * Protocol format:
     * IP1\nPORT1\n
     * (optional) IPz\nPORTz\n
     * --
     */

    int bufsize = pcd->bufend - pcd->bufpos;
    ngx_int_t received;
    if (bufsize > 0) {
        received = ngx_recv(c, pcd->bufpos, bufsize);
    } else {
        received = 0;
    }

    if (received==NGX_AGAIN) {
        return;
    } else if (received>=0) {
        pcd->bufpos += received;

        for (i=0;i<(pcd->bufpos-pcd->buf);i++) {
            if (*(pcd->buf + i )=='-') {
                pcd->end_marker_count++;
            }
        }

        if (pcd->end_marker_count>=2) {
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "CloudRouter preconnect: message complete");

            ngx_http_cloudrouter_peer_t *peer = (ngx_http_cloudrouter_peer_t *)u->peer.data;
            unsigned char* next = pcd->buf;
            int new_node = 0;

            ngx_shmtx_lock(&ngx_http_cloudrouter_shpool->mutex);

            ngx_http_cloudrouter_node_t *e = ngx_http_cloudrouter_get_locked(route);
            if (e == NULL) {
                /* likely() */

                e = ngx_slab_alloc_locked(ngx_http_cloudrouter_shpool, sizeof *e);
                new_node = 1;

                e->node.key = ngx_http_cloudrouter_hash_route(route);

                (void)ngx_copy(e->di_name, route->di_name, sizeof(route->di_name));
                e->di_nlen = route->di_nlen;
            } else {
                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "CloudRouter preconnect: reusing existing node");
            }

            e->timestamp = time(NULL);
            ngx_http_cloudrouter_clear_remotes_locked(e, rev->log);

            while (next < pcd->bufpos) {
                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "CloudRouter preconnect: parsing message");

                unsigned char *ip = NULL;
                unsigned char *port = NULL;
                ip = next;
                while (++next < pcd->bufpos) {
                    if (*(next-1) == '\n') {
                        if (ip && port)
                            break;
                        port = next;
                    }
                }

                if (ip && port) {
                    ngx_http_cloudrouter_remote_t *remote = ngx_http_cloudrouter_add_remote_locked(e);

                    int iplen = port-ip-1;
                    iplen = iplen > 16 ? 16 : iplen;

                    remote->inet_addr = ngx_inet_addr(ip, iplen);
                    if (remote->inet_addr == INADDR_NONE) {
                        ngx_log_error(NGX_LOG_ERR, rev->log, NGX_EINVAL,
                                      "CloudRouter preconnect: IP address from Agent invalid for route %s",
                                      e->di_name);
                        goto failure;
                    }

                    int portlen = next-port-1;
                    remote->port_n = htons(ngx_atoi(port,portlen));

                    ngx_log_debug7(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                                   "CloudRouter preconnect: cached values SET: e=%p rem=%p ts=%d %s[%d] %uxD:%d",
                                   e, remote, e->timestamp,
                                   e->di_name, e->di_nlen,
                                   remote->inet_addr, remote->port_n);
                }
            }

            if (!e->remote) {
                ngx_log_debug(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                              "CloudRouter preconnect: Agent sent no remotes");
                goto failure;
            }

            ngx_http_cloudrouter_set_hostandport(r, peer, e);
            if (new_node) {
                ngx_rbtree_insert(ngx_http_cloudrouter_rbtree, &e->node);
            }
            ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex);
            return ngx_http_cloudrouter_peer_preconnect_close(c, pcd, NGX_OK);

failure:
            if (!new_node) {
                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pcd->r->connection->log, 0, "peer_preconnect_read: calling rbtree_delete");
                ngx_rbtree_delete(ngx_http_cloudrouter_rbtree, &e->node);
            }
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pcd->r->connection->log, 0, "peer_preconnect_read: calling free_node_locked");
            ngx_http_cloudrouter_free_node_locked(e, rev->log);
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pcd->r->connection->log, 0, "peer_preconnect_read: calling shmtx_unlock");
            ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex);
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pcd->r->connection->log, 0, "peer_preconnect_read: calling peer_preconnect_close");
            return ngx_http_cloudrouter_peer_preconnect_close(c, pcd, NGX_ERROR);
        }
        return;
    }

    /* unknown error condition from ngx_recv */
    return;
}
static ngx_int_t
ngx_http_cloudrouter_init_upstream_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us) {
    struct sockaddr_in* sin;
    ngx_http_hs_main_conf_t    *hscf;
    ngx_http_cloudrouter_peer_t *peer;
    hs_route_t *route;
    int tcb_s;

    hscf = ngx_http_get_module_main_conf(r, ngx_http_hs_module);
    if (hscf == NULL || hscf->tcb_route_db == NULL) {
        return NGX_ERROR;
    }

    peer = ngx_pcalloc(r->pool, sizeof(ngx_http_cloudrouter_peer_t));
    if (peer == NULL) {
        ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "NULL peer");
        return NGX_ERROR;
    }

    peer->route = NULL;

    peer->socklen = sizeof(struct sockaddr_in);
    peer->sockaddr = (struct sockaddr*)ngx_pcalloc(r->pool, peer->socklen);
    if (peer->sockaddr == NULL) {
        ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "ALERT: peer->sockaddr alloc failed");
        return NGX_ERROR;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "init_peer");

    /* fallback = 404 host */
    ngx_str_set(&peer->name, "127.0.0.1");
    peer->inet_addr = ngx_inet_addr(peer->name.data, peer->name.len);
    peer->port_n = htons(8404);

    r->upstream->peer.data = peer;
    r->upstream->peer.free = ngx_http_cloudrouter_free_upstream_peer;
    r->upstream->peer.get = ngx_http_cloudrouter_get_upstream_peer;
    r->upstream->peer.tries = 1;

    // fetch config for client-supplied Host
    if (r->headers_in.server.len > 0) {
        route = (hs_route_t*)tcbdbget(hscf->tcb_route_db, r->headers_in.server.data, r->headers_in.server.len, &tcb_s);
    } else {
        route = NULL;
    }
    if (route == NULL) {
        // send user to 404 host
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "CloudRouter: no route matched");
        return NGX_OK;
    } else {
        /* copy route into peer, managed memory */
        peer->route = ngx_pcalloc(r->pool, sizeof(hs_route_t));
        if (peer->route==NULL) {
            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "ALERT: alloc failed");
            free(route);
            return NGX_ERROR;
        }
        (void)ngx_copy(peer->route, route, sizeof(hs_route_t));
        free(route); // gets malloc()'d by TC
        route = peer->route;

        peer->name.len = route->di_nlen;
        peer->name.data = ngx_pcalloc(r->pool, peer->name.len);
        (void)ngx_copy(peer->name.data, route->di_name, peer->name.len);

        ngx_shmtx_lock(&ngx_http_cloudrouter_shpool->mutex);

        ngx_http_cloudrouter_node_t *e = ngx_http_cloudrouter_get_locked(route);
        if (e && e->timestamp > (r->start_sec - NGX_HTTP_HS_CACHE_TIMEOUT)) {
            ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cache hit");
            ngx_http_cloudrouter_remote_t *remote = e->remote;

            ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                           "cached values READ: %p:%d:%s[%d],(%uxD,%d)", e, e->timestamp,
                           e->di_name,
                           e->di_nlen,
                           remote->inet_addr,
                           remote->port_n);

            ngx_http_cloudrouter_set_hostandport(r,peer,e);

            ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex);
        } else {
            /* entry has expired.
             * pretend it does not exist, the preconnect handler will overwrite it.
             */

            int current = 0;
            if (e) {
                ngx_http_cloudrouter_remote_t *remote = e->remote;
                while (remote != NULL) {
                    current += remote->current;
                    remote = remote->next;
                }
                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "CloudRouter: cache entry expired");
            } else {
                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "CloudRouter: no entry in cache");
            }
            ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex);

            peer->sendbuf.data = ngx_pcalloc(r->pool, NGX_HTTP_CLOUDROUTER_PRECONNECT_SENDBUFSIZE);
            if (peer->sendbuf.data == NULL) {
                ngx_log_error(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "alloc peer->sendbuf.data failed, aborting request");
                return NGX_ERROR;
            }

            peer->sendbuf.len = ngx_sprintf(peer->sendbuf.data, "BLNC %*s %ud", peer->route->di_nlen, peer->route->di_name, current) - peer->sendbuf.data;

            ngx_shmtx_unlock(&ngx_http_cloudrouter_shpool->mutex);

            r->upstream->peer.preconnect = (ngx_event_preconnect_pt)ngx_http_cloudrouter_peer_preconnect;
        }
        return NGX_OK;
    }
    /* never reached */
}
Ejemplo n.º 17
0
static ngx_int_t
ngx_http_repsheet_handler(ngx_http_request_t *r)
{
  char temp_address[INET_ADDRSTRLEN];
  repsheet_loc_conf_t *conf;
  int length;

  conf = ngx_http_get_module_loc_conf(r, ngx_http_repsheet_module);

  if (!conf->enabled) {
    return NGX_DECLINED;
  }

  if (r->main->internal) {
    return NGX_DECLINED;
  }

  r->main->internal = 1;

  redisContext *context = get_redis_context(r);

  if (context == NULL) {
    return NGX_DECLINED;
  }

  actor_t actor;
  repsheet_init_actor(&actor);

  ngx_table_elt_t *xfwd = NULL;

#if (nginx_version >= 1004000)
  ngx_array_t *ngx_array = &r->headers_in.x_forwarded_for;
  if (ngx_array != NULL && ngx_array->nelts > 0) {
     ngx_table_elt_t **first_elt = ngx_array->elts;
     xfwd = first_elt[0];
  }
#else 
  xfwd = r->headers_in.x_forwarded_for;
#endif

  if (xfwd != NULL && xfwd->value.data != NULL) {
    in_addr_t addr;
    u_char *p;

    /* Get the first value from the XFF list.
     * Note that xfwd->value.data already has any extra whitespace removed.
     */
    for (p=xfwd->value.data; p < (xfwd->value.data + xfwd->value.len); p++) {
      if (*p == ' ' || *p == ',')
        break;
    }

    /* Validate it is a valid IP */
    length = p - xfwd->value.data;
    addr = ngx_inet_addr(xfwd->value.data, length);
    if (addr != INADDR_NONE && length <= INET_ADDRSTRLEN) {
      strncpy(temp_address, (char *)xfwd->value.data, length);
      temp_address[length] = '\0';
      actor.address = temp_address;
    }
  }

  if (actor.address == NULL) {
    length = r->connection->addr_text.len;
    strncpy(temp_address, (char *)r->connection->addr_text.data, length);
    temp_address[length] = '\0';
    actor.address = temp_address;
  }


  if (actor.address) {
    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s address : %s", "[repsheet]", actor.address);
  } else {
    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s Could not fetch address", "[repsheet]");
  }

  repsheet_score_actor(context, &actor);

  if (actor.whitelisted) {
    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s %s was allowed by the repsheet whitelist", "[repsheet]", actor.address);
    redisFree(context);
    return NGX_DECLINED;
  }

  if (actor.blacklisted) {
    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s %s was blocked by the repsheet blacklist", "[repsheet]", actor.address);
    redisFree(context);
    return NGX_HTTP_FORBIDDEN;
  }

  if (actor.offender) {
    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s %s was found on the repsheet", "[repsheet]", actor.address);
    ngx_table_elt_t *h;
    ngx_str_t label = ngx_string("X-Repsheet");
    ngx_str_t val = ngx_string("true");
    h = ngx_list_push(&r->headers_in.headers);
    h->hash = 1;
    h->key = label;
    h->value = val;
  }

  redisFree(context);

  return NGX_DECLINED;
}