Beispiel #1
0
ngx_int_t
ngx_mysql_connect(ngx_mysql_t *m)
{
    ngx_int_t  rc;

#if 0
    if (cached) {
        return NGX_OK;
    }
#endif

    m->peer.log->action = "connecting to mysql server";

    rc = ngx_event_connect_peer(&m->peer);

    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        return rc;
    }

    m->peer.connection->data = m;

    m->peer.connection->read->handler = ngx_mysql_read_server_greeting;
    m->peer.connection->write->handler = ngx_mysql_empty_handler;

    ngx_add_timer(m->peer.connection->read, /* STUB */ 5000);

    return NGX_OK;
}
static void
ngx_stream_proxy_connect(ngx_stream_session_t *s)
{
    ngx_int_t                     rc;
    ngx_connection_t             *c, *pc;
    ngx_stream_upstream_t        *u;
    ngx_stream_proxy_srv_conf_t  *pscf;

    c = s->connection;

    c->log->action = "connecting to upstream";

    u = s->upstream;

    rc = ngx_event_connect_peer(&u->peer);

    ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "proxy connect: %i", rc);

    pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);

    if (rc == NGX_ERROR) {
        ngx_stream_proxy_finalize(s, NGX_ERROR);
        return;
    }

    if (rc == NGX_BUSY) {
        ngx_log_error(NGX_LOG_ERR, c->log, 0, "no live upstreams");
        ngx_stream_proxy_finalize(s, NGX_DECLINED);
        return;
    }

    if (rc == NGX_DECLINED) {
        ngx_stream_proxy_next_upstream(s);
        return;
    }

    /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */

    pc = u->peer.connection;

    pc->data = s;
    pc->log = c->log;
    pc->pool = c->pool;
    pc->read->log = c->log;
    pc->write->log = c->log;

    if (rc != NGX_AGAIN) 
	{
        ngx_stream_proxy_init_upstream(s);
        return;
    }

    pc->read->handler = ngx_stream_proxy_connect_handler;
    pc->write->handler = ngx_stream_proxy_connect_handler;

    ngx_add_timer(pc->write, pscf->connect_timeout);
}
static void 
ngx_tcp_check_connect_handler(ngx_event_t *event) 
{
    ngx_int_t                      rc;
    ngx_connection_t              *c;
    ngx_tcp_check_peer_conf_t     *peer_conf;
    ngx_tcp_upstream_srv_conf_t   *uscf;

    if (ngx_tcp_check_need_exit()) {
        return;
    }

    peer_conf = event->data;
    uscf = peer_conf->conf;

    ngx_memzero(&peer_conf->pc, sizeof(ngx_peer_connection_t));

    peer_conf->pc.sockaddr = peer_conf->peer->sockaddr;
    peer_conf->pc.socklen = peer_conf->peer->socklen;
    peer_conf->pc.name = &peer_conf->peer->name;

    peer_conf->pc.get = ngx_event_get_peer;
    peer_conf->pc.log = event->log;
    peer_conf->pc.log_error = NGX_ERROR_ERR; 

    peer_conf->pc.cached = 0;
    peer_conf->pc.connection = NULL;

    rc = ngx_event_connect_peer(&peer_conf->pc);

    if (rc == NGX_ERROR || rc == NGX_DECLINED) {
        ngx_tcp_check_status_update(peer_conf, 0);
        return;
    }

    /*NGX_OK or NGX_AGAIN*/
    c = peer_conf->pc.connection;
    c->data = peer_conf;
    c->log = peer_conf->pc.log;
    c->sendfile = 0;
    c->read->log = c->log;
    c->write->log = c->log;
    c->pool = peer_conf->pool;

    peer_conf->state = NGX_TCP_CHECK_CONNECT_DONE;

    c->write->handler = peer_conf->send_handler;
    c->read->handler = peer_conf->recv_handler;

    ngx_add_timer(&peer_conf->check_timeout_ev, uscf->check_timeout);

    /* The kqueue's loop interface need it. */
    if (rc == NGX_OK) {
        c->write->handler(c->write);
    }
}
void ngx_imap_proxy_init(ngx_imap_session_t *s)
{
    ngx_int_t              rc;
    ngx_peers_t           *peers;
    ngx_imap_proxy_ctx_t  *p;

    if (!(p = ngx_pcalloc(s->connection->pool, sizeof(ngx_imap_proxy_ctx_t)))) {
        ngx_imap_close_connection(s->connection);
        return;
    }

    s->proxy = p;

    /**/

    if (!(peers = ngx_pcalloc(s->connection->pool, sizeof(ngx_peers_t)))) {
        ngx_imap_close_connection(s->connection);
        return;
    }

    p->upstream.peers = peers;
    p->upstream.log = s->connection->log;
    p->upstream.log_error = NGX_ERROR_ERR;

    peers->number = 1;
    peers->max_fails = 1;
#if 0
    peers->peers[0].addr = inet_addr("81.19.69.70");
    peers->peers[0].addr_port_text.len = sizeof("81.19.69.70:110") - 1;
    peers->peers[0].addr_port_text.data = (u_char *) "81.19.69.70:110";
    peers->peers[0].port = htons(110);
#else
    peers->peers[0].addr = inet_addr("81.19.64.101");
    peers->peers[0].addr_port_text.len = sizeof("81.19.64.101:110") - 1;
    peers->peers[0].addr_port_text.data = (u_char *) "81.19.64.101:110";
    peers->peers[0].port = htons(110);
#endif

    rc = ngx_event_connect_peer(&p->upstream);

    if (rc == NGX_ERROR) {
        ngx_imap_proxy_close_session(s);
        return;
    }

    p->upstream.connection->data = s;
    p->upstream.connection->pool = s->connection->pool;

    s->connection->read->event_handler = ngx_imap_proxy_block_read;
    p->upstream.connection->read->event_handler = ngx_imap_proxy_auth_handler;
    p->upstream.connection->write->event_handler = ngx_imap_proxy_dummy_handler;
}
static void
ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
{
    ngx_int_t    rc;

    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
                   "ssl ocsp connect");

    /* TODO: use all ip addresses */

    ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
    ctx->peer.socklen = ctx->addrs[0].socklen;
    ctx->peer.name = &ctx->addrs[0].name;
    ctx->peer.get = ngx_event_get_peer;
    ctx->peer.log = ctx->log;
    ctx->peer.log_error = NGX_ERROR_ERR;

    rc = ngx_event_connect_peer(&ctx->peer);

    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
                   "ssl ocsp connect peer done");

    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        ngx_ssl_ocsp_error(ctx);
        return;
    }

    ctx->peer.connection->data = ctx;
    ctx->peer.connection->pool = ctx->pool;

    ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
    ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;

    ctx->process = ngx_ssl_ocsp_process_status_line;

    ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
    ngx_add_timer(ctx->peer.connection->write, ctx->timeout);

    if (rc == NGX_OK) {
        ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
        return;
    }
}
static void
ngx_http_gettoken_connect(ngx_http_gettoken_connection_t *c)
{
    ngx_peer_connection_t *pconn;
    ngx_connection_t *conn;
    ngx_addr_t *addr;
    ngx_int_t rc;

    addr = &c->server->parsed_url.addrs[ngx_random() % c->server->parsed_url.naddrs];

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_gettoken: Connecting to LDAP server \"%V\".",
        &addr->name);

    pconn = &c->conn;
    pconn->sockaddr = addr->sockaddr;
    pconn->socklen = addr->socklen;
    pconn->name = &addr->name;
    pconn->get = ngx_event_get_peer;
    pconn->log = c->log;
    pconn->log_error = NGX_ERROR_ERR;

    rc = ngx_event_connect_peer(pconn);
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_gettoken: ngx_event_connect_peer() -> %d.", rc);
    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        ngx_log_error(NGX_LOG_ERR, c->log, 0, "http_gettoken: Unable to connect to LDAP server \"%V\".",
            &addr->name);
        ngx_add_timer(&c->reconnect_event, c->server->reconnect_timeout);
        return;
    }

    conn = pconn->connection;
    conn->data = c;

    conn->write->handler = ngx_http_gettoken_connect_handler;
    conn->read->handler = ngx_http_gettoken_read_handler;
    ngx_add_timer(conn->read, c->server->connect_timeout);
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_gettoken: connect_timeout=%d.", c->server->connect_timeout);


    c->state = STATE_CONNECTING;
}
LIBCOUCHBASE_API
void ngx_lcb_connect_peer(lcb_io_opt_t io,
                          lcb_socket_t sock,
                          void *event,
                          void *cb_data,
                          lcb_io_plugin_connect_cb handler)
{
    ngx_lcb_context_t *ctx = from_socket(sock);
    ngx_peer_connection_t *peer = ctx->peer;
    ngx_int_t rc;

    if (peer->sockaddr == NULL) {
        if (ngx_lcb_connect(io, sock, ctx->curr_ai->ai_addr,
                            ctx->curr_ai->ai_addrlen) != 0) {
            handler(LCB_CONNECT_ERROR, cb_data);
            return;
        }
    }
    rc = ngx_event_connect_peer(peer);
    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        io->v.v0.error = ngx_socket_errno;
        handler(LCB_CONNECT_ERROR, cb_data);
        return;
    }
    peer->connection->data = ctx;
    if (rc == NGX_AGAIN) {
        peer->connection->write->handler = ngx_lcb_connect_handler_thunk;
        peer->connection->read->handler = ngx_lcb_connect_handler_thunk;
        ctx->conn_data = cb_data;
        ctx->conn_handler = handler;
        ngx_add_timer(peer->connection->write, 300); /* ms */
        return;
    }
    peer->connection->read->handler = ngx_lcb_handler_thunk;
    peer->connection->write->handler = ngx_lcb_handler_thunk;
    handler(LCB_SUCCESS, cb_data);
    (void)event;
}
ngx_int_t
ngx_rtmp_netcall_create(ngx_rtmp_session_t *s, ngx_rtmp_netcall_init_t *ci)
{
    ngx_rtmp_netcall_ctx_t         *ctx;
    ngx_peer_connection_t          *pc;
    ngx_rtmp_netcall_session_t     *cs;
    ngx_rtmp_netcall_app_conf_t    *cacf;
    ngx_connection_t               *c, *cc;
    ngx_pool_t                     *pool;
    ngx_int_t                       rc;

    pool = NULL;
    c = s->connection;

    cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_netcall_module);
    if (cacf == NULL) {
        goto error;
    }

    /* get module context */
    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_netcall_module);
    if (ctx == NULL) {
        ctx = ngx_pcalloc(c->pool, 
                sizeof(ngx_rtmp_netcall_ctx_t));
        if (ctx == NULL) {
            return NGX_ERROR;
        }
        ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_netcall_module);
    }

    /* Create netcall pool, connection, session.
     * Note we use shared (app-wide) log because
     * s->connection->log might be unavailable
     * in detached netcall when it's being closed */
    pool = ngx_create_pool(4096, cacf->log);
    if (pool == NULL) {
        goto error;
    }

    pc = ngx_pcalloc(pool, sizeof(ngx_peer_connection_t));
    if (pc == NULL) {
        goto error;
    }

    cs = ngx_pcalloc(pool, sizeof(ngx_rtmp_netcall_session_t));
    if (cs == NULL) {
        goto error;
    }

    /* copy arg to connection pool */
    if (ci->argsize) {
        cs->arg = ngx_pcalloc(pool, ci->argsize);
        if (cs->arg == NULL) {
            goto error;
        }
        ngx_memcpy(cs->arg, ci->arg, ci->argsize);
    }

    cs->timeout = cacf->timeout;
    cs->bufsize = cacf->bufsize;
    cs->url = ci->url;
    cs->session = s;
    cs->filter = ci->filter;
    cs->sink = ci->sink;
    cs->handle = ci->handle;
    if (cs->handle == NULL) {
        cs->detached = 1;
    }

    pc->log = cacf->log;
    pc->get = ngx_rtmp_netcall_get_peer;
    pc->free = ngx_rtmp_netcall_free_peer;
    pc->data = cs;

    /* connect */
    rc = ngx_event_connect_peer(pc);
    if (rc != NGX_OK && rc != NGX_AGAIN ) {
        ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, 
                "netcall: connection failed");
        goto error;
    }

    cc = pc->connection;
    cc->data = cs;
    cc->pool = pool;
    cs->pc = pc;

    cs->out = ci->create(s, ci->arg, pool);
    if (cs->out == NULL) {
        ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, 
                "netcall: creation failed");
        ngx_close_connection(pc->connection);
        goto error;
    }

    cc->write->handler = ngx_rtmp_netcall_send;
    cc->read->handler = ngx_rtmp_netcall_recv;

    if (!cs->detached) {
        cs->next = ctx->cs;
        ctx->cs = cs;
    }

    ngx_rtmp_netcall_send(cc->write);

    return c->destroyed ? NGX_ERROR : NGX_OK;

error:
    if (pool) {
        ngx_destroy_pool(pool);
    }

    return NGX_ERROR;
}
static int 
ngx_http_php_socket_resolve_retval_handler(ngx_http_request_t *r, 
    ngx_http_php_socket_upstream_t *u)
{
    ngx_int_t                       rc;
    ngx_http_php_ctx_t              *ctx;
    ngx_peer_connection_t           *peer;
    ngx_connection_t                *c;
    ngx_http_upstream_resolved_t    *ur;

    ctx = ngx_http_get_module_ctx(r, ngx_http_php_module);

    peer = &u->peer;

    ngx_php_debug("%p", peer);

    ur = u->resolved;

    if (ur->sockaddr) {
        peer->sockaddr = ur->sockaddr;
        peer->socklen = ur->socklen;
        peer->name = &ur->host;
    }else {
        return NGX_ERROR;
    }

    peer->get = ngx_http_php_socket_get_peer;

    rc = ngx_event_connect_peer(peer);

    ngx_php_debug("rc: %d %p", (int)rc, ctx->generator_closure);

    if (rc == NGX_ERROR) {

        return NGX_ERROR;
    }

    if (rc == NGX_BUSY) {
        return NGX_ERROR;
    }

    if (rc == NGX_DECLINED) {
        return NGX_ERROR;
    }

    /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */

    //ctx->phase_status = NGX_AGAIN;

    c = peer->connection;
    c->data = u;
    u->request = r;

    c->write->handler = ngx_http_php_socket_handler;
    c->read->handler = ngx_http_php_socket_handler;

    u->write_event_handler = (ngx_http_php_socket_upstream_handler_pt )ngx_http_php_socket_connected_handler;
    u->read_event_handler = (ngx_http_php_socket_upstream_handler_pt )ngx_http_php_socket_connected_handler;

    c->sendfile &= r->connection->sendfile;

    if (c->pool == NULL) {

        /* we need separate pool here to be able to cache SSL connections */

        c->pool = ngx_create_pool(128, r->connection->log);
        if (c->pool == NULL) {
            return NGX_ERROR;
        }
    }

    c->log = r->connection->log;
    c->pool->log = c->log;
    c->read->log = c->log;
    c->write->log = c->log;

    /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */

    if (rc == NGX_OK) {
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 
                       "php socket connected: fd:%d", (int) c->fd);
        ngx_php_debug("php socket connected: fd:%d", (int) c->fd);

        ctx->phase_status = NGX_OK;

        if (ngx_handle_write_event(c->write, 0) != NGX_OK) {

            return NGX_ERROR;
        }

        if (ngx_handle_read_event(c->read, 0) != NGX_OK) {

            return NGX_ERROR;
        }

        u->read_event_handler = (ngx_http_php_socket_upstream_handler_pt) ngx_http_php_socket_dummy_handler;
        u->write_event_handler = (ngx_http_php_socket_upstream_handler_pt) ngx_http_php_socket_dummy_handler;
    
        return NGX_OK;
    }

    // rc == NGX_AGAIN
    
    ctx->phase_status = NGX_AGAIN;
    
    ngx_add_timer(c->write, 5 * 1000);

    return NGX_AGAIN;
}
void
ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer)
{
    ngx_int_t                  rc;
    ngx_mail_proxy_ctx_t      *p;
    ngx_mail_proxy_conf_t     *pcf;
    ngx_mail_core_srv_conf_t  *cscf;

    s->connection->log->action = "connecting to upstream";

    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

    p = ngx_pcalloc(s->connection->pool, sizeof(ngx_mail_proxy_ctx_t));
    if (p == NULL) {
        ngx_mail_session_internal_server_error(s);
        return;
    }

    s->proxy = p;

    p->upstream.sockaddr = peer->sockaddr;
    p->upstream.socklen = peer->socklen;
    p->upstream.name = &peer->name;
    p->upstream.get = ngx_event_get_peer;
    p->upstream.log = s->connection->log;
    p->upstream.log_error = NGX_ERROR_ERR;

    rc = ngx_event_connect_peer(&p->upstream);

    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        ngx_mail_proxy_internal_server_error(s);
        return;
    }

    ngx_add_timer(p->upstream.connection->read, cscf->timeout, NGX_FUNC_LINE);

    p->upstream.connection->data = s;
    p->upstream.connection->pool = s->connection->pool;

    s->connection->read->handler = ngx_mail_proxy_block_read;
    p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler;

    pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);

    s->proxy->buffer = ngx_create_temp_buf(s->connection->pool,
                                           pcf->buffer_size);
    if (s->proxy->buffer == NULL) {
        ngx_mail_proxy_internal_server_error(s);
        return;
    }

    s->out.len = 0;

    switch (s->protocol) {

    case NGX_MAIL_POP3_PROTOCOL:
        p->upstream.connection->read->handler = ngx_mail_proxy_pop3_handler;
        s->mail_state = ngx_pop3_start;
        break;

    case NGX_MAIL_IMAP_PROTOCOL:
        p->upstream.connection->read->handler = ngx_mail_proxy_imap_handler;
        s->mail_state = ngx_imap_start;
        break;

    default: /* NGX_MAIL_SMTP_PROTOCOL */
        p->upstream.connection->read->handler = ngx_mail_proxy_smtp_handler;
        s->mail_state = ngx_smtp_start;
        break;
    }
}
/* 启动nginx与上游邮件服务器间的交互 */
void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer)
{
    int                        keepalive;
    ngx_int_t                  rc;
    ngx_mail_proxy_ctx_t      *p;
    ngx_mail_proxy_conf_t     *pcf;
    ngx_mail_core_srv_conf_t  *cscf;

    s->connection->log->action = "connecting to upstream";

    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

    if (cscf->so_keepalive) {
        keepalive = 1;

        if (setsockopt(s->connection->fd, SOL_SOCKET, SO_KEEPALIVE,
                       (const void *) &keepalive, sizeof(int))
                == -1)
        {
            ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno,
                          "setsockopt(SO_KEEPALIVE) failed");
        }
    }

    p = ngx_pcalloc(s->connection->pool, sizeof(ngx_mail_proxy_ctx_t));//创建ngx_mail_proxy_t结构体
    if (p == NULL) {
        ngx_mail_session_internal_server_error(s);
        return;
    }

    s->proxy = p;

    p->upstream.sockaddr = peer->sockaddr;
    p->upstream.socklen = peer->socklen;
    p->upstream.name = &peer->name;
    p->upstream.get = ngx_event_get_peer;
    p->upstream.log = s->connection->log;
    p->upstream.log_error = NGX_ERROR_ERR;

    rc = ngx_event_connect_peer(&p->upstream);//向上游邮件服务器发起无阻塞的TCP连接

    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        ngx_mail_proxy_internal_server_error(s);
        return;
    }

	/* 需要监控接收邮件服务器的响应是否超时,于是把与上游连接的读事件添加到定时器中 */
    ngx_add_timer(p->upstream.connection->read, cscf->timeout);

    p->upstream.connection->data = s;//设置连接的data成员指向ngx_mail_session_t结构体
    p->upstream.connection->pool = s->connection->pool;

	/* 设置nginx于客户端间连接读事件的回调方法为不会读取内容的ngx_mail_proxy_block_read方法,因为当前阶段nginx不会与客户端交互 */ 
    s->connection->read->handler = ngx_mail_proxy_block_read;

	/* 设置nginx与上游间的连接写事件回调方法为什么都不做的ngx_mail_proxy_dummy_handler方法,这意味着
	接下来向上游发送TCP流时,将不再通过epoll这个事件框架来调度*/
    p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler;

    pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);

	/* 建立nginx与邮件服务器间的内存缓冲区 */
    s->proxy->buffer = ngx_create_temp_buf(s->connection->pool,pcf->buffer_size);
    if (s->proxy->buffer == NULL) {
        ngx_mail_proxy_internal_server_error(s);
        return;
    }

    s->out.len = 0;//设置out为空,表示不会通过out向客户端发送响应

	/* 根据用户请求的协议设置实际的邮件认证方法 */
    switch (s->protocol) 
	{
    case NGX_MAIL_POP3_PROTOCOL://设置POP3协议进行邮件交互认证的方法
        p->upstream.connection->read->handler = ngx_mail_proxy_pop3_handler;
        s->mail_state = ngx_pop3_start;
        break;

    case NGX_MAIL_IMAP_PROTOCOL:
        p->upstream.connection->read->handler = ngx_mail_proxy_imap_handler;
        s->mail_state = ngx_imap_start;
        break;

    default: /* NGX_MAIL_SMTP_PROTOCOL */
        p->upstream.connection->read->handler = ngx_mail_proxy_smtp_handler;
        s->mail_state = ngx_smtp_start;
        break;
    }
}
Beispiel #12
0
static ngx_int_t
ngx_nats_connect_loop(ngx_nats_data_t *nd)
{
    ngx_nats_core_conf_t   *nccf;
    ngx_nats_connection_t  *nc;
    ngx_nats_server_t      *ns;
    ngx_addr_t             *a;
    ngx_int_t               rc, n;
    ngx_connection_t       *c = NULL;

    nccf = nd->nccf;

    n = nccf->servers->nelts;

    if (nd->curr_index < 0) {

        /* new reconnect loop */
        nd->curr_index = nd->last_index;
        nd->nconnects++;

    } else {

        if (++nd->curr_index >= n) {
            nd->curr_index = 0;
        }

        if (nd->curr_index == nd->last_index) {

            /*
             * means we tried each server and could not connect
             * to any of them, now sleep and then repeat.
             */

            if (!ngx_nats_conn_err_reported) {

                ngx_nats_conn_err_reported = 1;

                ngx_log_error(NGX_LOG_ERR, nd->log, 0,
                    "cannot connect to NATS server%s, "
                    "will try every %d milliseconds",
                    (u_char*)(n > 1 ? "s" : ""),
                    (int)nccf->reconnect_interval);
            }

            ngx_nats_add_reconnect_timer(nd);

            return NGX_DECLINED;
        }
    }

    ngx_reset_pool(nd->nc_pool);
    ngx_nats_buf_reset(nd->nc_read_buf);
    ngx_nats_buf_reset(nd->nc_write_buf);

    nc = ngx_pcalloc(nd->nc_pool, sizeof(ngx_nats_connection_t));
    if (nc == NULL) {
        return NGX_ERROR;
    }

    nd->nc = nc;
    nc->nd = nd;

    ns = (ngx_nats_server_t *) nccf->servers->elts;
    ns = ns + nd->curr_index;

    a = ns->addrs;  /* TODO: handle multiple addrs? */

    nc->pc.data     = nd;
    nc->pool        = nd->nc_pool;
    nc->read_buf    = nd->nc_read_buf;
    nc->write_buf   = nd->nc_write_buf;
    nc->pc.log      = nccf->log;
#if (NGX_HAVE_KQUEUE)
    /* This prevents Nginx printing:
     * kevent() reported about an closed connection (61: Connection refused)
     * every time connection to NATS fails, it prints only if the error
     * log level is set to INFO which we don't.
     */
    nc->pc.log_error = NGX_ERROR_INFO;
#endif
    nc->pc.sockaddr = a->sockaddr;
    nc->pc.socklen  = a->socklen;
    nc->pc.name     = &ns->url;
    nc->pc.tries    = 1;
    nc->pc.get      = ngx_nats_get_peer;
    nc->pc.free     = ngx_nats_free_peer;

    nc->server = ns;

    rc = ngx_event_connect_peer(&nc->pc);

    if (rc == NGX_BUSY || rc == NGX_ERROR || rc == NGX_DECLINED) {
        return NGX_AGAIN;
    }

    if (rc == NGX_OK || rc == NGX_AGAIN) {

        c = nc->pc.connection;

        c->data = nc;

        c->write->handler   = ngx_nats_connection_handler;
        c->read->handler    = ngx_nats_connection_handler;

        c->log              = nd->log;

        c->read->log        = c->log;
        c->write->log       = c->log;
        /* TODO: do I need SSL? c->pool is for SSL only. */
        if (c->pool != NULL)
            c->pool->log = c->log;
    }

    if (rc == NGX_AGAIN) {
        ngx_add_timer(c->write, 5000);  /* TODO: configurable? */
        return NGX_OK;
    }

    if (rc == NGX_OK) {
        /* Connected right here. */
        ngx_nats_connection_init(nc);
        ngx_nats_flush(nc);
        return NGX_OK;
    }

    return NGX_OK;
}
static void
ngx_http_upstream_dbd_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
    ngx_int_t          rc;
    ngx_time_t        *tp;
    ngx_connection_t  *c;

    r->connection->log->action = "connecting to upstream";

    r->connection->single_connection = 0;

    if (u->state && u->state->response_sec) {
        tp = ngx_timeofday();
        u->state->response_sec = tp->sec - u->state->response_sec;
        u->state->response_msec = tp->msec - u->state->response_msec;
    }

    u->state = ngx_array_push(r->upstream_states);
    if (u->state == NULL) {
        ngx_http_upstream_drizzle_finalize_request(r, u,
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
        return;
    }

    ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));

    tp = ngx_timeofday();
    u->state->response_sec = tp->sec;
    u->state->response_msec = tp->msec;

    rc = ngx_event_connect_peer(&u->peer);

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http upstream connect: %i", rc);

    if (rc == NGX_ERROR) {
        ngx_http_upstream_drizzle_finalize_request(r, u,
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
        return;
    }

    u->state->peer = u->peer.name;

    if (rc == NGX_BUSY) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
        ngx_http_upstream_drizzle_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE);
        return;
    }

    if (rc == NGX_DECLINED) {
        ngx_http_upstream_drizzle_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
        return;
    }

    /* rc == NGX_OK || rc == NGX_AGAIN */

    c = u->peer.connection;

    c->data = r;

    c->write->handler = ngx_http_upstream_dbd_handler;
    c->read->handler = ngx_http_upstream_dbd_handler;

    u->write_event_handler = ngx_http_drizzle_wev_handler;
    u->read_event_handler = ngx_http_drizzle_rev_handler;

    c->sendfile &= r->connection->sendfile;
    u->output.sendfile = c->sendfile;

    c->pool = r->pool;
    c->log = r->connection->log;
    c->read->log = c->log;
    c->write->log = c->log;

    /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */

    u->writer.out = NULL;
    u->writer.last = &u->writer.out;
    u->writer.connection = c;
    u->writer.limit = 0;

    if (u->request_sent) {
        if (ngx_http_upstream_dbd_reinit(r, u) != NGX_OK) {
            ngx_http_upstream_drizzle_finalize_request(r, u,
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
            return;
        }
    }

    if (r->request_body
        && r->request_body->buf
        && r->request_body->temp_file
        && r == r->main)
    {
        /*
         * the r->request_body->buf can be reused for one request only,
         * the subrequests should allocate their own temporay bufs
         */

        u->output.free = ngx_alloc_chain_link(r->pool);
        if (u->output.free == NULL) {
            ngx_http_upstream_drizzle_finalize_request(r, u,
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
            return;
        }

        u->output.free->buf = r->request_body->buf;
        u->output.free->next = NULL;
        u->output.allocated = 1;

        r->request_body->buf->pos = r->request_body->buf->start;
        r->request_body->buf->last = r->request_body->buf->start;
        r->request_body->buf->tag = u->output.tag;
    }

    u->request_sent = 0;

    if (rc == NGX_AGAIN) {
        ngx_add_timer(c->write, u->conf->connect_timeout);
        return;
    }

#if 0 /* libdrizzle doesn't support SSL, was: (NGX_HTTP_SSL) */

    if (u->ssl && c->ssl == NULL) {
        ngx_http_upstream_ssl_init_connection(r, u, c);
        return;
    }

#endif

#if 0
    ngx_http_upstream_send_request(r, u);
#endif

    dd("connection error: %d", c->error);

    ngx_http_drizzle_set_libdrizzle_ready(r);

    (void) ngx_http_drizzle_process_events(r);
}
void
ngx_mail_auth_http_init(ngx_mail_session_t *s)
{
    ngx_int_t                   rc;
    ngx_pool_t                 *pool;
    ngx_mail_auth_http_ctx_t   *ctx;
    ngx_mail_auth_http_conf_t  *ahcf;

    s->connection->log->action = "in http auth state";

    pool = ngx_create_pool(2048, s->connection->log);
    if (pool == NULL) {
        ngx_mail_session_internal_server_error(s);
        return;
    }

    ctx = ngx_pcalloc(pool, sizeof(ngx_mail_auth_http_ctx_t));
    if (ctx == NULL) {
        ngx_destroy_pool(pool);
        ngx_mail_session_internal_server_error(s);
        return;
    }

    ctx->pool = pool;

    ahcf = ngx_mail_get_module_srv_conf(s, ngx_mail_auth_http_module);

    ctx->request = ngx_mail_auth_http_create_request(s, pool, ahcf);
    if (ctx->request == NULL) {
        ngx_destroy_pool(ctx->pool);
        ngx_mail_session_internal_server_error(s);
        return;
    }

    ngx_mail_set_ctx(s, ctx, ngx_mail_auth_http_module);

    ctx->peer.sockaddr = ahcf->peer->sockaddr;
    ctx->peer.socklen = ahcf->peer->socklen;
    ctx->peer.name = &ahcf->peer->name;
    ctx->peer.get = ngx_event_get_peer;
    ctx->peer.log = s->connection->log;
    ctx->peer.log_error = NGX_ERROR_ERR;

    rc = ngx_event_connect_peer(&ctx->peer);

    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        if (ctx->peer.connection) {
            ngx_close_connection(ctx->peer.connection);
        }

        ngx_destroy_pool(ctx->pool);
        ngx_mail_session_internal_server_error(s);
        return;
    }

    ctx->peer.connection->data = s;
    ctx->peer.connection->pool = s->connection->pool;

    s->connection->read->handler = ngx_mail_auth_http_block_read;
    ctx->peer.connection->read->handler = ngx_mail_auth_http_read_handler;
    ctx->peer.connection->write->handler = ngx_mail_auth_http_write_handler;

    ctx->handler = ngx_mail_auth_http_ignore_status_line;

    ngx_add_timer(ctx->peer.connection->read, ahcf->timeout);
    ngx_add_timer(ctx->peer.connection->write, ahcf->timeout);

    if (rc == NGX_OK) {
        ngx_mail_auth_http_write_handler(ctx->peer.connection->write);
        return;
    }
}
Beispiel #15
0
void
ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_peer_addr_t *peer)
{
    int                        keepalive;
    ngx_int_t                  rc;
    ngx_mail_proxy_ctx_t      *p;
    ngx_mail_proxy_conf_t     *pcf;
    ngx_mail_core_srv_conf_t  *cscf;

    s->connection->log->action = "connecting to upstream";

    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

    if (cscf->so_keepalive) {
        keepalive = 1;

        if (setsockopt(s->connection->fd, SOL_SOCKET, SO_KEEPALIVE,
                       (const void *) &keepalive, sizeof(int))
                == -1)
        {
            ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno,
                          "setsockopt(SO_KEEPALIVE) failed");
        }
    }

    p = ngx_pcalloc(s->connection->pool, sizeof(ngx_mail_proxy_ctx_t));
    if (p == NULL) {
        ngx_mail_session_internal_server_error(s);
        return;
    }

    s->proxy = p;

    p->upstream.sockaddr = peer->sockaddr;
    p->upstream.socklen = peer->socklen;
    p->upstream.name = &peer->name;
    p->upstream.get = ngx_event_get_peer;
    p->upstream.log = s->connection->log;
    p->upstream.log_error = NGX_ERROR_ERR;

    rc = ngx_event_connect_peer(&p->upstream);

    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        ngx_mail_proxy_internal_server_error(s);
        return;
    }

    ngx_add_timer(p->upstream.connection->read, cscf->timeout);

    p->upstream.connection->data = s;
    p->upstream.connection->pool = s->connection->pool;

    s->connection->read->handler = ngx_mail_proxy_block_read;
    p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler;

    pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);

    s->proxy->buffer = ngx_create_temp_buf(s->connection->pool,
                                           pcf->buffer_size);
    if (s->proxy->buffer == NULL) {
        ngx_mail_proxy_internal_server_error(s);
        return;
    }

    s->out.len = 0;

    switch (s->protocol) {

    case NGX_MAIL_POP3_PROTOCOL:
        p->upstream.connection->read->handler = ngx_mail_proxy_pop3_handler;
        s->mail_state = ngx_pop3_start;
        break;

    case NGX_MAIL_IMAP_PROTOCOL:
        p->upstream.connection->read->handler = ngx_mail_proxy_imap_handler;
        s->mail_state = ngx_imap_start;
        break;

    default: /* NGX_MAIL_SMTP_PROTOCOL */
        p->upstream.connection->read->handler = ngx_mail_proxy_smtp_handler;
        s->mail_state = ngx_smtp_start;
        break;
    }
}
static void
ngx_tcp_upstream_connect(ngx_tcp_session_t *s, ngx_tcp_upstream_t *u) 
{
    int                       tcp_nodelay;
    ngx_int_t                 rc;
    ngx_connection_t         *c;
    ngx_tcp_core_srv_conf_t  *cscf;

    s->connection->log->action = "connecting to upstream";

    cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module);

    rc = ngx_event_connect_peer(&u->peer);

    ngx_log_debug1(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "tcp upstream connect: %d", rc);

    if (rc != NGX_OK && rc != NGX_AGAIN) {

        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, 
                "upstream servers error or busy!");

        ngx_tcp_upstream_finalize_session(s, u, 0);

        return;
    }

    /* rc == NGX_OK or rc == NGX_AGAIN */

    if (u->peer.check_index != NGX_INVALID_INDEX) {
        ngx_tcp_check_get_peer(u->peer.check_index);
    }

    c = u->peer.connection;

    c->data = s;
    c->pool = s->connection->pool;
    c->log = s->connection->log;
    c->read->log = c->log;
    c->write->log = c->log;

    c->write->handler = ngx_tcp_upstream_handler;
    c->read->handler = ngx_tcp_upstream_handler;

    if (cscf->tcp_nodelay) {
        tcp_nodelay = 1;

        if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
                    (const void *) &tcp_nodelay, sizeof(int)) == -1)
        {
            ngx_connection_error(c, ngx_socket_errno,
                    "setsockopt(TCP_NODELAY) failed");
            ngx_tcp_upstream_finalize_session(s, u, 0);
            return;
        }

        c->tcp_nodelay = NGX_TCP_NODELAY_SET;
    }

    if (rc == NGX_AGAIN) {
        /*connect busy*/
        ngx_add_timer(c->write, u->conf->connect_timeout);
        return;
    }
    else {
        ngx_add_timer(c->read, u->conf->read_timeout);
        ngx_add_timer(c->write, u->conf->send_timeout);

        c->write->handler(c->write);
    }
}
void
ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer)
{
    int                        keepalive;
    ngx_int_t                  rc;
    ngx_int_t                  secured = 0;
    ngx_mail_proxy_ctx_t      *p;
    ngx_mail_proxy_conf_t     *pcf;
    ngx_mail_core_srv_conf_t  *cscf;
    ngx_mail_ssl_conf_t       *sslcf;

    s->connection->log->action = "connecting to upstream";

    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

    if (cscf->so_keepalive) {
        keepalive = 1;

        if (setsockopt(s->connection->fd, SOL_SOCKET, SO_KEEPALIVE,
                       (const void *) &keepalive, sizeof(int))
                == -1)
        {
            ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno,
                          "setsockopt(SO_KEEPALIVE) failed");
        }
    }

    p = ngx_pcalloc(s->connection->pool, sizeof(ngx_mail_proxy_ctx_t));
    if (p == NULL) {
        ngx_mail_session_internal_server_error(s);
        return;
    }

    s->proxy = p;

    p->upstream.sockaddr = peer->sockaddr;
    p->upstream.socklen = peer->socklen;
    p->upstream.name = &peer->name;
    p->upstream.get = ngx_event_get_peer;
    p->upstream.log = s->connection->log;
    p->upstream.log_error = NGX_ERROR_ERR;

    rc = ngx_event_connect_peer(&p->upstream);

    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        ngx_mail_proxy_internal_server_error(s);
        return;
    }

    ngx_add_timer(p->upstream.connection->read, cscf->timeout);

    p->upstream.connection->data = s;
    p->upstream.connection->pool = s->connection->pool;

    s->connection->read->handler = ngx_mail_proxy_block_read;
    p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler;

#if (NGX_MAIL_SSL)
    if (s->auth_security) {
        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);

        if (sslcf->ssl.ctx) {
            s->connection->log->action = "SSL handshaking";

            ngx_mail_ssl_init_connection(&sslcf->ssl,
                                         p->upstream.connection,
                                         NGX_MAIL_SECURE_DIR_OUT);
            secured = 1;
        } else {
            ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                          "failed to get SSL context;");
            ngx_mail_proxy_internal_server_error(s);

            return;
        }
    }
#endif

    pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);

    s->proxy->buffer = ngx_create_temp_buf(s->connection->pool,
                                           pcf->buffer_size);
    if (s->proxy->buffer == NULL) {
        ngx_mail_proxy_internal_server_error(s);
        return;
    }

    s->out.len = 0;

    /* state will be changed in the ssl init routine */
    if (!secured)
        ngx_mail_proxy_start(p->upstream.connection);
}
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_healthcheck_begin_healthcheck(ngx_event_t *event) {
    ngx_http_healthcheck_status_t * stat;
    ngx_connection_t        *c;
    ngx_int_t rc;

    stat = event->data;
    if (stat->state != NGX_HEALTH_WAITING) {
        ngx_log_error(NGX_LOG_WARN, event->log, 0,
                "healthcheck: State not waiting, is %d", stat->state);
    }
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, event->log, 0,
            "healthcheck: begun healthcheck of index %i", stat->index);

    ngx_memzero(stat->pc, sizeof(ngx_peer_connection_t));
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, event->log, 0,
            "healthcheck: Memzero done", stat->index);

    stat->pc->get = ngx_event_get_peer;

    stat->pc->sockaddr = stat->peer->sockaddr;
    stat->pc->socklen = stat->peer->socklen;
    stat->pc->name = &stat->peer->name;

    stat->pc->log = event->log;
    stat->pc->log_error = NGX_ERROR_ERR; // Um I guess (???)

    stat->pc->cached = 0;
    stat->pc->connection = NULL;
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, event->log, 0,
            "healthcheck: Connecting peer", stat->index);

    rc = ngx_event_connect_peer(stat->pc);
    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
      ngx_log_error(NGX_LOG_CRIT, event->log, 0,
        "healthcheck: Could not connect to peer.  This is"
        " pretty bad and probably means your health checks won't"
        " work anymore: %i", rc);
      if (stat->pc->connection) {
          ngx_close_connection(stat->pc->connection);
      }
      // Try to do it again later, but if you're getting errors when you
      // try to connect to a peer, this probably won't work
      ngx_add_timer(&stat->health_ev, stat->conf->health_delay);
      return;
    }
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, event->log, 0,
      "healthcheck: connected so far");


    c = stat->pc->connection;
    c->data = stat;
    c->log = stat->pc->log;
    c->write->handler = ngx_http_healthcheck_write_handler;
    c->read->handler = ngx_http_healthcheck_read_handler;
    c->sendfile = 0;
    c->read->log = c->log;
    c->write->log = c->log;

    stat->state = NGX_HEALTH_SENDING_CHECK;
    stat->shm->action_time = ngx_current_msec;
    stat->read_pos = 0;
    stat->send_pos = 0;
    stat->body_read_pos = 0;
    stat->read_buffer->pos = stat->read_buffer->start;
    stat->read_buffer->last = stat->read_buffer->start;
    stat->check_start_time = ngx_current_msec;
    ngx_add_timer(c->read, stat->conf->health_timeout);
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, event->log, 0,
            "healthcheck: Peer connected", stat->index);

    ngx_http_healthcheck_send_request(c);
}
ngx_int_t
ngx_stream_upm_connect(ngx_stream_session_t *s)
{
    ngx_int_t                     rc;
    ngx_connection_t             *c, *pc;
    ngx_stream_upm_ctx_t         *ctx;
    ngx_stream_upstream_t        *u;
    //ngx_stream_upm_main_conf_t    *ummcf;

    //ummcf = ngx_stream_get_module_srv_conf(s, ngx_stream_upm_module);
    c = s->connection;

    u = s->upstream;

    ctx = ngx_stream_get_module_ctx(s, ngx_stream_upm_module);
    ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "upm connect: %i", rc);

    rc = ngx_event_connect_peer(&u->peer);
    if (rc == NGX_ERROR) {
        return rc;
    }

    if (rc == NGX_BUSY) {
        ngx_log_error(NGX_LOG_ERR, c->log, 0, "no live upstreams");
        return NGX_ERROR;
    }

    if (rc == NGX_DECLINED) {
        //FIXME: just return NGX_ERROR;
        return NGX_ERROR;
    }

    /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */

    pc = u->peer.connection;

    pc->data = s;
    pc->log = c->log;
    pc->pool = c->pool;
    pc->read->log = c->log;
    pc->write->log = c->log;

    pc->recv = ngx_recv;
    pc->send = ngx_send;
    pc->recv_chain = ngx_recv_chain;
    pc->send_chain = ngx_send_chain;

    pc->sendfile = 1;

    pc->read->handler = ngx_stream_upm_upstream_handler;
    pc->write->handler = ngx_stream_upm_upstream_handler;
    //ngx_add_timer(pc->write, ummcf->connect_timeout);

    ctx->state = CREATE_REQUEST;
    rc = ngx_stream_upm_create_request(s);
    if (rc != NGX_OK) {
        //return ngx_stream_upm_finalize(s); 
        return NGX_ERROR;
    }

    ctx->state = SEND_REQUEST;
    return ngx_stream_upm_send_request(s);
}
static ngx_rtmp_relay_ctx_t *
ngx_rtmp_relay_create_remote_ctx(ngx_rtmp_session_t *s, ngx_str_t* name,
        ngx_rtmp_relay_target_t *target)
{
    ngx_rtmp_relay_ctx_t           *rctx;
    ngx_rtmp_addr_conf_t           *addr_conf;
    ngx_rtmp_conf_ctx_t            *addr_ctx;
    ngx_rtmp_session_t             *rs;
    ngx_rtmp_relay_app_conf_t      *racf;
    ngx_peer_connection_t          *pc;
    ngx_connection_t               *c;
    ngx_pool_t                     *pool;
    ngx_int_t                       rc;
    ngx_str_t                       v, *uri;
    u_char                         *first, *last, *p;


    racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_relay_module);

    pool = NULL;
    pool = ngx_create_pool(4096, racf->log);
    if (pool == NULL) {
        return NULL;
    }

    rctx = ngx_pcalloc(pool, sizeof(ngx_rtmp_relay_ctx_t));
    if (rctx == NULL) {
        goto clear;
    }

    if (ngx_rtmp_relay_copy_str(pool, &rctx->name, name) != NGX_OK ||
        ngx_rtmp_relay_copy_str(pool, &rctx->url, &target->url.url) != NGX_OK)
    {
        goto clear;
    }

    rctx->tag = target->tag;
    rctx->data = target->data;

#define NGX_RTMP_RELAY_STR_COPY(to, from)                                     \
    if (ngx_rtmp_relay_copy_str(pool, &rctx->to, &target->from) != NGX_OK) {  \
        goto clear;                                                           \
    }

    NGX_RTMP_RELAY_STR_COPY(app,        app);
    NGX_RTMP_RELAY_STR_COPY(tc_url,     tc_url);
    NGX_RTMP_RELAY_STR_COPY(page_url,   page_url);
    NGX_RTMP_RELAY_STR_COPY(swf_url,    swf_url);
    NGX_RTMP_RELAY_STR_COPY(flash_ver,  flash_ver);
    NGX_RTMP_RELAY_STR_COPY(play_path,  play_path);

    rctx->live  = target->live;
    rctx->start = target->start;
    rctx->stop  = target->stop;

#undef NGX_RTMP_RELAY_STR_COPY

    if (rctx->app.len == 0 || rctx->play_path.len == 0) {
        /* parse uri */
        uri = &target->url.uri;
        first = uri->data;
        last  = uri->data + uri->len;
        if (first != last && *first == '/') {
            ++first;
        }

        if (first != last) {

            /* deduce app */
            p = ngx_strlchr(first, last, '/');
            if (rctx->app.len == 0 && first != p) {
                v.data = first;
                v.len = p - first;
                if (ngx_rtmp_relay_copy_str(pool, &rctx->app, &v) != NGX_OK) {
                    goto clear;
                }
            }

            /* deduce play_path */
            ++p;
            if (rctx->play_path.len == 0 && p != last) {
                v.data = p;
                v.len = last - p;
                if (ngx_rtmp_relay_copy_str(pool, &rctx->play_path, &v) 
                        != NGX_OK) 
                {
                    goto clear;
                }
            }
        }
    }

    rctx->relay = 1;

    pc = ngx_pcalloc(pool, sizeof(ngx_peer_connection_t));
    if (pc == NULL) {
        goto clear;
    }
    /* copy log to keep shared log unchanged */
    rctx->log = *racf->log;
    pc->log = &rctx->log;
    pc->get = ngx_rtmp_relay_get_peer;
    pc->free = ngx_rtmp_relay_free_peer;
    pc->name = &target->url.host;
    pc->socklen = target->url.socklen;
    pc->sockaddr = (struct sockaddr *)ngx_palloc(pool, pc->socklen);
    if (pc->sockaddr == NULL) {
        goto clear;
    }
    ngx_memcpy(pc->sockaddr, &target->url.sockaddr, pc->socklen);

    rc = ngx_event_connect_peer(pc);
    if (rc != NGX_OK && rc != NGX_AGAIN ) {
        ngx_log_debug0(NGX_LOG_DEBUG_RTMP, racf->log, 0, 
                "relay: connection failed");
        goto clear;
    }
    c = pc->connection;
    c->pool = pool;
    c->addr_text = rctx->url;

    addr_conf = ngx_pcalloc(pool, sizeof(ngx_rtmp_addr_conf_t));
    if (addr_conf == NULL) {
        goto clear;
    }
    addr_ctx = ngx_pcalloc(pool, sizeof(ngx_rtmp_conf_ctx_t));
    if (addr_ctx == NULL) {
        goto clear;
    }
    addr_conf->ctx = addr_ctx;
    addr_ctx->main_conf = s->main_conf;
    addr_ctx->srv_conf  = s->srv_conf;
    ngx_str_set(&addr_conf->addr_text, "ngx-relay");

    rs = ngx_rtmp_init_session(c, addr_conf);
    if (rs == NULL) {
        /* no need to destroy pool */
        return NULL;
    }
    rs->app_conf = s->app_conf;
    rctx->session = rs;
    ngx_rtmp_set_ctx(rs, rctx, ngx_rtmp_relay_module);
    ngx_str_set(&rs->flashver, "ngx-local-relay");
    
    ngx_rtmp_client_handshake(rs, 1);
    return rctx;

clear:
    if (pool) {
        ngx_destroy_pool(pool);
    }
    return NULL;
}
static void ngx_http_clojure_socket_upstream_connect_inner(ngx_http_clojure_socket_upstream_t *u) {
	ngx_int_t rc;
	ngx_connection_t  *c;
	ngx_peer_connection_t *pc = &u->peer;

/*	if (!u->free_bufs) {
		if (!ngx_http_clojure_socket_upstream_make_unset_to_default(u)) {
			ngx_http_clojure_socket_upstream_connect_handler(u, NGX_HTTP_CLOJURE_SOCKET_ERR_OUTOFMEMORY);
			return;
		}
	}*/

	if (u->peer.connection) {
		ngx_http_clojure_socket_upstream_close_connection(u);
	}

	pc->sockaddr = u->resolved->sockaddr;
	pc->socklen = u->resolved->socklen;
	/*TODO:keepalive peer*/
	pc->get = ngx_event_get_peer; /*do nothing!*/
	pc->free = NULL;
	pc->log = u->pool->log;
	pc->rcvbuf = u->buffer_size ? u->buffer_size : ngx_pagesize;
	pc->data = u;
	pc->name = &u->resolved->host;

	u->connect_event_sent = 0;
	rc = ngx_event_connect_peer(pc);

	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, u->pool->log, 0,
	                   "clojure_socket_upstream connect: %i", rc);

	if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
		ngx_http_clojure_socket_upstream_connect_handler(u, NGX_HTTP_CLOJURE_SOCKET_ERR_CONNECT);
		return;
	}

	c = u->peer.connection;
	c->data = u;

	if (c->tcp_nodelay != NGX_TCP_NODELAY_DISABLED && u->tcp_nodelay) {
		int tcp_nodelay = u->tcp_nodelay;
		if (setsockopt(u->peer.connection->fd, IPPROTO_TCP, TCP_NODELAY, (const void *) &tcp_nodelay, sizeof(int)) == -1) {
			u->tcp_nodelay = 0;
		}
	}

	if (u->so_keepalive) {
		int so_keepalive = u->so_keepalive;
		if (setsockopt(u->peer.connection->fd, SOL_SOCKET, SO_KEEPALIVE, (const void *) &so_keepalive, sizeof(int)) == -1) {
			u->so_keepalive = 0;
		}
	}

	c->write->handler = c->read->handler = ngx_http_clojure_socket_upstream_handler;


	if (rc == NGX_AGAIN) {
		if (u->connect_timeout > 0) {
			ngx_add_timer(c->write, u->connect_timeout);
		}
		return;
	}

	/*connected immediately successfully*/
	c->write->ready = 1;
	//ngx_http_clojure_socket_upstream_connect_handler(u, NGX_HTTP_CLOJURE_SOCKET_OK);
	ngx_http_clojure_socket_upstream_handler(c->write);
}
ngx_rtmpt_proxy_session_t 
	*ngx_rtmpt_proxy_create_session(ngx_http_request_t *r) 
{
	ngx_rtmpt_proxy_session_t 		*session;
	ngx_peer_connection_t     		*pc;
	ngx_rtmpt_proxy_loc_conf_t  	*plcf;
	ngx_pool_t                     	*pool = NULL;
	ngx_url_t                   	url;
	int 							rc;
	
	
	plcf = ngx_http_get_module_loc_conf(r, ngx_rtmpt_proxy_module);
	
	if (!plcf) {
		goto error;
	}
	
	
	pool = ngx_create_pool(4096, plcf->log);
	if (pool == NULL) {
		ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: cannot create pool for session");
		goto error;
	}
	
	
	session = (ngx_rtmpt_proxy_session_t *) ngx_pcalloc(pool, sizeof(ngx_rtmpt_proxy_session_t));
	if (session == NULL) {
		ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: cannot allocate memory for session");
		goto error;
	}
	
	session->name.data=NULL;
	session->name.len=0;
	
	ngx_str_set(&session->name, "1234567890123456");
	session->name.data = ngx_pstrdup(pool, &session->name);
	session_name_create(session->name.data,session->name.len);
		 
	session->log = plcf->log;
	session->pool = pool;
	session->sequence = 0;   
	session->on_finish_send = NULL;
	session->chain_from_http_request = NULL;   
	session->chain_from_nginx = NULL;
	session->out_pool = NULL;
	session->interval_check_time=0;
	session->interval_check_att=0;
	session->interval_check_count=0;
	session->interval_position=1;
	session->created_at = ngx_cached_time->sec;
	session->http_requests_count = 0;
	session->bytes_from_http = session->bytes_to_http = 0;
	
	session->create_request_ip.data=ngx_pstrdup(pool,&r->connection->addr_text);
	session->create_request_ip.len=r->connection->addr_text.len;
	
        bzero(session->waiting_requests,NGX_RTMPT_PROXY_REQUESTS_DELAY_SIZE*sizeof(ngx_http_request_t *));
        session->in_process = 0;

	put_session_in_hash(session);
	
	pc = ngx_pcalloc(pool, sizeof(ngx_peer_connection_t));
	if (pc == NULL) {
		ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: cannot allocate for peer connection");
		goto error;
	} 
	
	ngx_memzero(&url, sizeof(ngx_url_t));
	url.url.data = plcf->target.data;
	url.url.len = plcf->target.len;
	url.default_port = 1935;
	url.uri_part = 1;
	
	if (ngx_parse_url(pool, &url) != NGX_OK) {
		ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: error [%s] failed to parse server name: %V", url.err, &url.url);
		goto error;
	}
	
	
	session->target_url.data=ngx_pstrdup(pool,&url.url);
	session->target_url.len=url.url.len;
	
	ngx_memzero(pc, sizeof(ngx_peer_connection_t));
	pc->log = session->log;
    pc->get = ngx_rtmpt_proxy_session_get_peer;
    pc->free = ngx_rtmpt_proxy_session_free_peer;
	
	pc->sockaddr = url.addrs[0].sockaddr;
	pc->socklen = url.addrs[0].socklen;
	pc->name = &url.addrs[0].name;
    

    rc = ngx_event_connect_peer(pc);
	if (rc != NGX_OK && rc != NGX_AGAIN ) {
		ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: error in connect peer");
		goto error;
	}

	pc->connection->data = session;
	pc->connection->read->handler = ngx_rtmpt_read_from_rtmp;
	pc->connection->write->handler = ngx_rtmpt_send_chain_to_rtmp; 
	pc->connection->idle = 0;
	pc->connection->log = session->log;
	pc->connection->pool = session->pool;
	pc->connection->pool->log = session->log;
	pc->connection->read->log = session->log;
	pc->connection->write->log = session->log;
	
	
	
	
	session->connection = pc->connection;
	
   	return session;
	
error:
	if (pool) {
		ngx_destroy_pool(pool);
	}
	return NULL;
}
static int
ngx_lua_smtp_send(lua_State *l)
{
    char                        *errstr;
    ngx_int_t                    rc;
    ngx_pool_t                  *pool;
    ngx_lua_thread_t            *thr;
    ngx_pool_cleanup_t          *cln;
    ngx_lua_smtp_ctx_t          *ctx;
    ngx_peer_connection_t       *peer;
    ngx_lua_smtp_cleanup_ctx_t  *cln_ctx;

    thr = ngx_lua_thread(l);

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, thr->log, 0, "lua smtp send");

    pool = ngx_create_pool(ngx_pagesize, ngx_cycle->log);
    if (pool == NULL) {
        errstr = "ngx_create_pool() failed";
        goto error;
    }

    ctx = ngx_pcalloc(pool, sizeof(ngx_lua_smtp_ctx_t));
    if (ctx == NULL) {
        ngx_destroy_pool(pool);
        errstr = "ngx_pcalloc() failed";
        goto error;
    }

    ctx->pool = pool;

    if (ngx_array_init(&ctx->to, pool, 16, sizeof(ngx_str_t)) == NGX_ERROR) {
        ngx_destroy_pool(pool);
        errstr = "ngx_array_init() failed";
        goto error;
    }

    cln_ctx = ngx_pcalloc(thr->pool, sizeof(ngx_lua_smtp_cleanup_ctx_t));
    if (cln_ctx == NULL) {
        ngx_destroy_pool(pool);
        errstr = "ngx_pcalloc() failed";
        goto error;
    }

    cln_ctx->ctx = ctx;

    cln = ngx_pool_cleanup_add(thr->pool, 0);
    if (cln == NULL) {
        ngx_destroy_pool(pool);
        errstr = "ngx_pool_cleanup_add() failed";
        goto error;
    }

    cln->handler = ngx_lua_smtp_cleanup;
    cln->data = cln_ctx;

    ctx->thr = thr;
    ctx->cln_ctx = cln_ctx;

    if (ngx_lua_smtp_parse_args(l, thr, ctx) == NGX_ERROR) {
        return 2;
    }

    ctx->u.default_port = 25;
    ctx->u.one_addr = 1;

    if (ngx_parse_url(pool, &ctx->u) != NGX_OK) {
        if (ctx->u.err) {
            ngx_log_error(NGX_LOG_EMERG, thr->log, 0,
                          "%s in url \"%V\"", ctx->u.err, &ctx->u.url);
        }

        errstr = ctx->u.err;
        goto error;
    }

    peer = &ctx->peer;

#if (NGX_UDT)
    peer->type = SOCK_STREAM;
#endif
    peer->sockaddr = ctx->u.addrs->sockaddr;
    peer->socklen = ctx->u.addrs->socklen;
    peer->name = &ctx->u.addrs->name;
    peer->get = ngx_event_get_peer;
    peer->log = ngx_cycle->log;
    peer->log_error = NGX_ERROR_ERR;
#if (NGX_THREADS)
    peer->lock = &thr->c->lock;
#endif

    rc = ngx_event_connect_peer(peer);

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, thr->log, 0,
                   "lua smtp connecting to server: %i", rc);

    if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
        errstr = "ngx_event_connect_peer() failed";
        goto error;
    }

    peer->connection->data = ctx;
    peer->connection->pool = pool;

    peer->connection->read->handler = ngx_lua_smtp_dummy_handler;
    peer->connection->write->handler = ngx_lua_smtp_connect_handler;

    if (rc == NGX_AGAIN) {
        ngx_add_timer(peer->connection->write, ctx->connect_timeout);
        return lua_yield(l, 0);
    }

    /* rc == NGX_OK */

    ctx->rc = 0;
    ctx->not_event = 1;

    ngx_lua_smtp_connect_handler(peer->connection->write);

    ctx->not_event = 0;

    rc = ctx->rc;

    if (rc == NGX_AGAIN) {
        return lua_yield(l, 0);
    }

    cln_ctx->ctx = NULL;

    ngx_destroy_pool(ctx->pool);

    return rc;

error:

    lua_pushboolean(l, 0);
    lua_pushstring(l, errstr);

    return 2;
}