static ngx_int_t
ngx_rtmp_play_do_start(ngx_rtmp_session_t *s)
{
    ngx_rtmp_play_ctx_t            *ctx;

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);

    if (ctx == NULL) {
        return NGX_ERROR;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "play: start");

    if (ctx->fmt && ctx->fmt->start &&
        ctx->fmt->start(s, &ctx->file) != NGX_OK)
    {
        return NGX_ERROR;
    }

    ngx_post_event((&ctx->send_evt), &ngx_posted_events);

    ctx->playing = 1;

    return NGX_OK;
}
Ejemplo n.º 2
0
static void
ngx_event_busy_lock_handler(ngx_event_t *ev)
{
    ev->handler = ngx_event_busy_lock_posted_handler;

    ngx_post_event(ev, &ngx_posted_events);
}
static void
ngx_http_lua_ssl_sess_fetch_done(void *data)
{
    ngx_connection_t                *c;
    ngx_http_lua_ssl_ctx_t          *cctx = data;

    dd("lua ssl sess_fetch done");

    if (cctx->aborted) {
        return;
    }

    ngx_http_lua_assert(cctx->done == 0);

    cctx->done = 1;

    if (cctx->cleanup) {
        *cctx->cleanup = NULL;
    }

    c = cctx->connection;

    c->log->action = "SSL handshaking";

    ngx_post_event(c->write, &ngx_posted_events);
}
void
ngx_rtmp_proxy_protocol(ngx_rtmp_session_t *s)
{
    ngx_event_t       *rev;
    ngx_connection_t  *c;

    c = s->connection;
    rev = c->read;
    rev->handler =  ngx_rtmp_proxy_protocol_recv;

    ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "proxy_protocol: start");

    if (rev->ready) {
        /* the deferred accept(), rtsig, aio, iocp */

        if (ngx_use_accept_mutex) {
            ngx_post_event(rev, &ngx_posted_events);
            return;
        }

        rev->handler(rev);
        return;
    }

    ngx_add_timer(rev, s->timeout);

    if (ngx_handle_read_event(rev, 0) != NGX_OK) {
        ngx_rtmp_finalize_session(s);
        return;
    }
}
static ngx_int_t
ngx_rtmp_play_do_seek(ngx_rtmp_session_t *s, ngx_uint_t timestamp)
{
    ngx_rtmp_play_ctx_t            *ctx;

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);

    if (ctx == NULL) {
        return NGX_ERROR;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "play: seek timestamp=%ui", timestamp);

    if (ctx->fmt && ctx->fmt->seek &&
        ctx->fmt->seek(s, &ctx->file, timestamp) != NGX_OK)
    {
        return NGX_ERROR;
    }

    if (ctx->playing) {
        ngx_post_event((&ctx->send_evt), &ngx_posted_events);
    }

    return NGX_OK;
}
void
ngx_rtmp_client_handshake(ngx_rtmp_session_t *s, unsigned async)
{
    ngx_connection_t           *c;

    c = s->connection;
    c->read->handler =  ngx_rtmp_handshake_recv;
    c->write->handler = ngx_rtmp_handshake_send;

    ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
            "handshake: start client handshake");

    s->hs_buf = ngx_rtmp_alloc_handshake_buffer(s);
    s->hs_stage = NGX_RTMP_HANDSHAKE_CLIENT_SEND_CHALLENGE;

    if (ngx_rtmp_handshake_create_challenge(s, 
                ngx_rtmp_client_version,
                &ngx_rtmp_client_partial_key) != NGX_OK) 
    {
        ngx_rtmp_finalize_session(s);
        return;
    }

    if (async) {
        ngx_post_event(c->write, &ngx_posted_events);
        return;
    }

    ngx_rtmp_handshake_send(c->write);
}
static void exec_event_handler2(ngx_event_t* ev)
{
	ngx_connection_t   *c;
	navi_exec_mon_t    *s;
	int                 i;

	c = ev->data;
	s = c->data;

    for (i = 0; i < ngx_last_process; i++) {
        if (ngx_processes[i].pid == s->pid) {
			s->status = ngx_processes[i].status;
			ngx_processes[i].pid = -1;//reset
            break;
        }
    }

	if (i == ngx_last_process) {
        ngx_log_error(NGX_LOG_ALERT, pcycle->log, 0,
              "can not find process info of %d",
              s->pid);
        s->status = -128;
	}

	ngx_post_event(ev, &ngx_posted_events);
	ev->handler = cleanup_exec_driver;
	navi_exec_child_dead(s);
}
Ejemplo n.º 8
0
static void
ngx_rtmp_play_send(ngx_event_t *e)
{
    ngx_rtmp_session_t     *s = e->data;
    ngx_rtmp_play_ctx_t    *ctx;
    ngx_int_t               rc;

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);

    if (ctx == NULL || ctx->fmt == NULL || ctx->fmt->send == NULL) {
        return;
    }

    rc = ctx->fmt->send(s, &ctx->file);

    if (rc > 0) {
        ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                       "play: send schedule %i", rc);

        ngx_add_timer(e, rc);
        return;
    }

    if (rc == NGX_AGAIN) {
        ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                       "play: send buffer full");

        ngx_post_event(e, &s->posted_dry_events);
        return;
    }

    if (rc == NGX_OK) {
        ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                       "play: send restart");

        ngx_post_event(e, &ngx_posted_events);
        return;
    }


    ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "play: send done");

    ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_MSID);

    ngx_rtmp_send_status(s, "NetStream.Play.Stop", "status", "Stopped");
}
Ejemplo n.º 9
0
static ngx_int_t
ngx_ssl_handle_recv(ngx_connection_t *c, int n)
{

    if (n > 0) {
        if (c->ssl->saved_write_handler) {
            c->write->handler = c->ssl->saved_write_handler;
            c->ssl->saved_write_handler = NULL;
            c->write->ready = 1;

            if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
                return NGX_ERROR;
            }

            ngx_post_event(c->write, &ngx_posted_events);
        }

        return NGX_OK;
    }

    if (n == MBEDTLS_ERR_NET_WANT_READ) {
        c->read->ready = 0;
        return NGX_AGAIN;
    }

    if (n == MBEDTLS_ERR_NET_WANT_WRITE) {
        c->write->ready = 0;

        if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
            return NGX_ERROR;
        }

        /*
         * we do not set the timer because there is already the read event timer
         */

        if (c->ssl->saved_write_handler == NULL) {
            c->ssl->saved_write_handler = c->write->handler;
            c->write->handler = ngx_ssl_write_handler;
        }

        return NGX_AGAIN;
    }

    c->ssl->no_send_shutdown = 1;

    if (n == 0 || n == MBEDTLS_ERR_SSL_CONN_EOF ||
        n == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                       "peer shutdown SSL cleanly");
        return NGX_DONE;
    }

    ngx_mbedtls_error(NGX_LOG_ERR, c->log, 0, n, "ssl_read() failed %d ", n);

    return NGX_ERROR;
}
void
ngx_tcp_init_connection(ngx_connection_t *c)
{
    ngx_event_t         *rev;
    ngx_tcp_log_ctx_t   *ctx;

    ctx = ngx_palloc(c->pool, sizeof(ngx_tcp_log_ctx_t));
    if (ctx == NULL) {
        ngx_tcp_close_connection(c);
        return;
    }

    ctx->client = NULL;
    ctx->session = NULL;

    c->log->connection = c->number;
    c->log->handler = ngx_tcp_log_error;
    c->log->data = ctx;
    c->log->action = "client init tcp connection";

    c->log_error = NGX_ERROR_INFO;

    rev = c->read;
    rev->handler = ngx_tcp_init_session;
    c->write->handler = ngx_tcp_empty_handler;
/*
#if (NGX_STAT_STUB)
    (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
#endif
*/
    if (rev->ready) {
        /* the deferred accept(), rtsig, aio, iocp */

        if (ngx_use_accept_mutex) {
            ngx_post_event(rev, &ngx_posted_events);
            return;
        }

        ngx_tcp_init_session(rev);
        return;
    }

    ngx_add_timer(rev, c->listening->post_accept_timeout);

    if (ngx_handle_read_event(rev, 0) != NGX_OK) {
/*
#if (NGX_STAT_STUB)
        (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
#endif
*/
        ngx_tcp_close_connection(c);
        return;
    }

}
Ejemplo n.º 11
0
static void ngx_event_busy_lock_handler(ngx_event_t *ev)
{
    if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR)
    {
        return;
    }

    ngx_post_event(ev);

    ngx_mutex_unlock(ngx_posted_events_mutex);

    ev->event_handler = ngx_event_busy_lock_posted_handler;
}
static ngx_int_t
ngx_rtmp_relay_init_process(ngx_cycle_t *cycle)
{
#if !(NGX_WIN32)
    ngx_rtmp_core_main_conf_t  *cmcf = ngx_rtmp_core_main_conf;
    ngx_rtmp_core_srv_conf_t  **pcscf, *cscf;
    ngx_rtmp_core_app_conf_t  **pcacf, *cacf;
    ngx_rtmp_relay_app_conf_t  *racf;
    ngx_uint_t                  n, m, k;
    ngx_rtmp_relay_static_t    *rs;
    ngx_rtmp_listen_t          *lst;
    ngx_event_t               **pevent, *event;

    if (cmcf == NULL || cmcf->listen.nelts == 0) {
        return NGX_OK;
    }

    /* only first worker does static pulling */

    if (ngx_process_slot) {
        return NGX_OK;
    }

    lst = cmcf->listen.elts;

    pcscf = cmcf->servers.elts;
    for (n = 0; n < cmcf->servers.nelts; ++n, ++pcscf) {

        cscf = *pcscf;
        pcacf = cscf->applications.elts;

        for (m = 0; m < cscf->applications.nelts; ++m, ++pcacf) {

            cacf = *pcacf;
            racf = cacf->app_conf[ngx_rtmp_relay_module.ctx_index];
            pevent = racf->static_events.elts;

            for (k = 0; k < racf->static_events.nelts; ++k, ++pevent) {
                event = *pevent;

                rs = event->data;
                rs->cctx = *lst->ctx;
                rs->cctx.app_conf = cacf->app_conf;

                ngx_post_event(event, &ngx_rtmp_init_queue);
            }
        }
    }
#endif
    return NGX_OK;
}
static void
ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
{
    ngx_connection_t    *c;
    ngx_mail_session_t  *s;

    s = ctx->data;
    c = s->connection;

    if (ctx->state) {
        ngx_log_error(NGX_LOG_ERR, c->log, 0,
                      "%V could not be resolved (%i: %s)",
                      &c->addr_text, ctx->state,
                      ngx_resolver_strerror(ctx->state));

        if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
            s->host = smtp_unavailable;

        } else {
            s->host = smtp_tempunavail;
        }

        ngx_resolve_addr_done(ctx);

        ngx_mail_smtp_greeting(s, s->connection);

        return;
    }

    c->log->action = "in resolving client hostname";

    s->host.data = ngx_pstrdup(c->pool, &ctx->name);
    if (s->host.data == NULL) {
        ngx_resolve_addr_done(ctx);
        ngx_mail_close_connection(c);
        return;
    }

    s->host.len = ctx->name.len;

    ngx_resolve_addr_done(ctx);

    ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
                   "address resolved: %V", &s->host);

    c->read->handler = ngx_mail_smtp_resolve_name;

    ngx_post_event(c->read, &ngx_posted_events);
}
static ngx_int_t
ngx_event_limit_accept_filter(ngx_connection_t *c)
{
    ngx_event_t                 *aev;
    ngx_listening_t             *ls;
    ngx_connection_t            *lc;
    ngx_limit_tcp_listen_ctx_t  *lctx;
    ngx_limit_tcp_accept_ctx_t  *actx;

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "limit accept filter");

    ls = c->listening;
    lc = ls->connection;
    lctx = lc->data;

    if (lctx == NULL) {
        return ngx_event_next_accept_filter(lc);
    }

    aev = ngx_pcalloc(c->pool, sizeof(ngx_event_t));
    if (aev == NULL) {
        return NGX_ERROR;
    }

    actx = ngx_pcalloc(c->pool, sizeof(ngx_limit_tcp_accept_ctx_t));
    if (actx == NULL) {
        return NGX_ERROR;
    }

    ngx_log_error(NGX_LOG_DEBUG, c->log, 0, "limit accept effective %p", c);

    actx->connection = c;
    actx->lctx = lctx;

    aev->data = actx;
    aev->handler = ngx_limit_tcp_accepted;
    aev->log = c->log;

    if (ngx_use_accept_mutex) {
        ngx_post_event(aev, &ngx_posted_events);
        return NGX_DECLINED;
    }

    ngx_limit_tcp_accepted(aev);

    return NGX_DECLINED;
}
Ejemplo n.º 15
0
void
ngx_rtmp_finalize_session(ngx_rtmp_session_t *s)
{
    ngx_event_t        *e;
    ngx_connection_t   *c;

    c = s->connection;

    ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0, "finalize session");

    c->destroyed = 1;
    e = &s->close;
    e->data = s;
    e->handler = ngx_rtmp_close_session_handler;
    e->log = c->log;

    ngx_post_event(e, &ngx_posted_events);
}
Ejemplo n.º 16
0
static ngx_int_t
ngx_rtmp_exec_init_process(ngx_cycle_t *cycle)
{
    ngx_rtmp_core_main_conf_t  *cmcf = ngx_rtmp_core_main_conf;
    ngx_rtmp_core_srv_conf_t  **cscf;
    ngx_rtmp_conf_ctx_t        *cctx;
    ngx_rtmp_exec_main_conf_t  *emcf;
    ngx_rtmp_exec_t            *e;
    ngx_uint_t                  n;

    if (cmcf == NULL || cmcf->servers.nelts == 0) {
        return NGX_OK;
    }

    /* execs are always started by the first worker */
    if (ngx_pid != ngx_processes[0].pid) {
        return NGX_OK;
    }

    cscf = cmcf->servers.elts;
    cctx = (*cscf)->ctx;
    emcf = cctx->main_conf[ngx_rtmp_exec_module.ctx_index];

    /* FreeBSD note:
     * When worker is restarted, child process (ffmpeg) will
     * not be terminated if it's connected to another 
     * (still alive) worker. That leads to starting
     * another instance of exec_static process.
     * Need to kill previously started processes.
     *
     * On Linux "prctl" syscall is used to kill child
     * when nginx worker is terminated.
     */

    e = emcf->execs.elts;
    for (n = 0; n < emcf->execs.nelts; ++n, ++e) {
        e->respawn_evt.data = e;
        e->respawn_evt.log = e->log;
        e->respawn_evt.handler = ngx_rtmp_exec_respawn;
        ngx_post_event((&e->respawn_evt), &ngx_posted_events);
    }

    return NGX_OK;
}
void 
http_req_read_handler( ngx_http_request_t *r ) {

    ngx_http_auth_radius_ctx_t* ctx = ngx_http_get_module_ctx( r, ngx_http_auth_radius_module );
    
    ngx_connection_t* c = r->connection;
    ngx_event_t* rev = c->read;

    if ( rev->timedout ) {
        rev->timedout = 0;
        ctx->attempts--;
        ngx_log_error( NGX_LOG_ERR, r->connection->log, 0, "http_req_read_handler: timeout 0x%xd, attempt: %d", r, ctx->attempts );
        if ( ctx->attempts == 0 ) {
            ctx->done = 1;
            ngx_post_event( r->connection->write, &ngx_posted_events );
            return;
        }
        ngx_send_radius_request( r, ctx->n );
        return;
    }

    u_char buf[ 1 ];
    int n = recv( c->fd, buf, sizeof( buf ), MSG_PEEK );

    if ( n == 0 ) {
        rev->eof = 1;
        c->error = 1;
        if ( ctx->n != NULL ) {
            ctx->n->active = 0;
        } 
        ngx_http_finalize_request( r, 0 );
        return;
    } else if (n == -1) {
        int err = ngx_socket_errno;
        if ( err != NGX_EAGAIN ) {
            rev->eof = 1;
            c->error = 1;
        }
        ngx_http_finalize_request(r, 0);
        return;
    }

    ngx_http_block_reading( r );
}
ngx_int_t
ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
    ngx_uint_t flags)
{
    int                 events, revents, rc;
    size_t              n;
    ngx_fd_t            fd;
    ngx_err_t           err;
    ngx_int_t           i;
    ngx_uint_t          level, instance;
    ngx_event_t        *rev, *wev;
    ngx_queue_t        *queue;
    ngx_connection_t   *c;
    struct pollfd       pfd;
    struct dvpoll       dvp;

    /* NGX_TIMER_INFINITE == INFTIM */

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "devpoll timer: %M", timer);

    if (nchanges) {
        n = nchanges * sizeof(struct pollfd);
        if (write(dp, change_list, n) != (ssize_t) n) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "write(/dev/poll) failed");
            return NGX_ERROR;
        }

        nchanges = 0;
    }

    dvp.dp_fds = event_list;
    dvp.dp_nfds = (int) nevents;
    dvp.dp_timeout = timer;
    events = ioctl(dp, DP_POLL, &dvp);

    err = (events == -1) ? ngx_errno : 0;

    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
        ngx_time_update();
    }

    if (err) {
        if (err == NGX_EINTR) {

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

            level = NGX_LOG_INFO;

        } else {
            level = NGX_LOG_ALERT;
        }

        ngx_log_error(level, cycle->log, err, "ioctl(DP_POLL) failed");
        return NGX_ERROR;
    }

    if (events == 0) {
        if (timer != NGX_TIMER_INFINITE) {
            return NGX_OK;
        }

        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                      "ioctl(DP_POLL) returned no events without timeout");
        return NGX_ERROR;
    }

    for (i = 0; i < events; i++) {

        fd = event_list[i].fd;
        revents = event_list[i].revents;

        c = ngx_cycle->files[fd];

        if (c == NULL || c->fd == -1) {

            pfd.fd = fd;
            pfd.events = 0;
            pfd.revents = 0;

            rc = ioctl(dp, DP_ISPOLLED, &pfd);

            switch (rc) {

            case -1:
                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    "ioctl(DP_ISPOLLED) failed for socket %d, event %04Xd",
                    fd, revents);
                break;

            case 0:
                ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    "phantom event %04Xd for closed and removed socket %d",
                    revents, fd);
                break;

            default:
                ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    "unexpected event %04Xd for closed and removed socket %d, ",
                    "ioctl(DP_ISPOLLED) returned rc:%d, fd:%d, event %04Xd",
                    revents, fd, rc, pfd.fd, pfd.revents);

                pfd.fd = fd;
                pfd.events = POLLREMOVE;
                pfd.revents = 0;

                if (write(dp, &pfd, sizeof(struct pollfd))
                    != (ssize_t) sizeof(struct pollfd))
                {
                    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                                  "write(/dev/poll) for %d failed", fd);
                }

                if (close(fd) == -1) {
                    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                                  "close(%d) failed", fd);
                }

                break;
            }

            continue;
        }

        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "devpoll: fd:%d, ev:%04Xd, rev:%04Xd",
                       fd, event_list[i].events, revents);

        if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                          "ioctl(DP_POLL) error fd:%d ev:%04Xd rev:%04Xd",
                          fd, event_list[i].events, revents);
        }

        if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "strange ioctl(DP_POLL) events "
                          "fd:%d ev:%04Xd rev:%04Xd",
                          fd, event_list[i].events, revents);
        }

        if ((revents & (POLLERR|POLLHUP|POLLNVAL))
             && (revents & (POLLIN|POLLOUT)) == 0)
        {
            /*
             * if the error events were returned without POLLIN or POLLOUT,
             * then add these flags to handle the events at least in one
             * active handler
             */

            revents |= POLLIN|POLLOUT;
        }

        rev = c->read;

        if ((revents & POLLIN) && rev->active) {
            rev->ready = 1;

            if (flags & NGX_POST_EVENTS) {
                queue = rev->accept ? &ngx_posted_accept_events
                                    : &ngx_posted_events;

                ngx_post_event(rev, queue);

            } else {
                instance = rev->instance;

                rev->handler(rev);

                if (c->fd == -1 || rev->instance != instance) {
                    continue;
                }
            }
        }

        wev = c->write;

        if ((revents & POLLOUT) && wev->active) {
            wev->ready = 1;

            if (flags & NGX_POST_EVENTS) {
                ngx_post_event(wev, &ngx_posted_events);

            } else {
                wev->handler(wev);
            }
        }
    }

    return NGX_OK;
}
void 
radius_read_handler( ngx_event_t* rev ) {

    ngx_connection_t* c = rev->data;

    radius_server_t* rs = c->data;

    if ( rev->timedout ) {
        rev->timedout = 0;
    }

    if ( rev->timer_set ) {
        ngx_del_timer( rev );
    }

    radius_req_queue_node_t* n;
    n = radius_recv_request( rs );
    if ( n == NULL ) {
        // not found TODO
        ngx_log_error( NGX_LOG_ERR, rev->log, 0, "radius_read_handler: request not found" );
        return;
    }

    ngx_http_request_t *r = n->data;
    ngx_log_error( NGX_LOG_ERR, rev->log, 0, "radius_read_handler: rs: %d, 0x%xl, 0x%xl, id: %d, acc: %d", rs->id, r, n, n->ident, n->accepted );

    if ( r->connection->data != r ) {
        ngx_log_error( NGX_LOG_ERR, rev->log, 0, "radius_read_handler: GONE" );
        return;
    }

    ngx_http_auth_radius_ctx_t* ctx = ngx_http_get_module_ctx( r, ngx_http_auth_radius_module );
    if ( ctx == NULL || ctx->n != n ) {
        ngx_log_error( NGX_LOG_ERR, rev->log, 0, "radius_read_handler: GONE 1" );
        return;
    }

    if ( r->connection->read->timer_set ) {
        r->connection->read->timer_set = 0;
        ngx_del_timer( r->connection->read );
    }

    ctx->done = 1;
    ctx->accepted = n->accepted;

    ngx_http_auth_radius_main_conf_t* conf = ngx_http_get_module_loc_conf( r, ngx_http_auth_radius_module );
    ngx_str_t args;
    ngx_str_t key;
    key.data = ctx->digest;
    key.len = sizeof( ctx->digest );
    args.len = sizeof( "o=set&v=X&k=" ) - 1 + key.len; // TODO
    args.data = ngx_palloc( r->pool, args.len );
    u_char* e = ngx_snprintf( args.data, args.len, "o=set&v=%d&k=%V", n->accepted, &key );
    args.len = e - args.data;
    int rc = ngx_http_auth_radius_init_subrequest( r, &conf->radius_cache, &args, ngx_http_auth_radius_subrequest_mcset_done );
    if ( rc != NGX_OK )
        abort(); // TODO
    ngx_post_event( r->connection->write, &ngx_posted_events );

    release_req_queue_node( n );

}
static ngx_int_t
ngx_live_relay_static_relay(ngx_rtmp_session_t *s,
        ngx_live_relay_static_relay_t *r)
{
    ngx_rtmp_session_t                 *rs;
    ngx_live_relay_ctx_t               *ctx, *pctx;
    ngx_live_relay_app_conf_t          *lracf;
    ngx_live_relay_static_main_conf_t  *rsmcf;
    ngx_live_relay_static_ctx_t        *sctx;
    ngx_live_relay_t                   *relay;
    ngx_rtmp_addr_conf_t               *addr_conf;

    relay = r->relay;
    rsmcf = ngx_rtmp_cycle_get_module_main_conf(ngx_cycle,
                                                ngx_live_relay_static_module);
    addr_conf = ngx_rtmp_find_related_addr_conf((ngx_cycle_t *) ngx_cycle,
                                                &rsmcf->pull_port);
    if (addr_conf == NULL) {
        ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
                "relay static, find related add_conf for %V failed",
                &rsmcf->pull_port);
        return NGX_DECLINED;
    }

    rs = ngx_rtmp_create_static_session(relay, addr_conf,
                                        &ngx_live_relay_static_module);
    if (rs == NULL) {
        ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
                "relay static, create relay session %V failed", &relay->stream);
        return NGX_DECLINED;
    }
    r->session = rs;

    rs->publishing = 1;
    rs->live_stream = ngx_live_create_stream(&rs->domain, &rs->stream);
    ngx_live_create_ctx(rs, 1);

    sctx = ngx_pcalloc(rs->pool, sizeof(ngx_live_relay_static_ctx_t));
    if (sctx == NULL) {
        ngx_log_error(NGX_LOG_ERR, rs->log, 0,
                "relay static, create static relay ctx failed");
        ngx_rtmp_finalize_session(rs);

        return NGX_OK;
    }
    ngx_rtmp_set_ctx(rs, sctx, ngx_live_relay_static_module);
    sctx->relay = r;

    ctx = ngx_rtmp_get_module_ctx(rs, ngx_live_relay_module);
    ctx->reconnect.log = rs->log;
    ctx->reconnect.data = rs;
    ctx->reconnect.handler = ngx_live_relay_static_handler;

    if (s == NULL) {
        ngx_post_event(&ctx->reconnect, &ngx_posted_events);
        return NGX_OK;
    }

    // reconnect
    pctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module);
    if (pctx->successd) { // prev relay successd
        ngx_post_event(&ctx->reconnect, &ngx_posted_events);
        return NGX_OK;
    }

    ctx->idx = pctx->idx;
    ctx->failed_reconnect = pctx->failed_reconnect;

    if (ctx->idx < relay->urls.nelts) { // retry backup url immediately
        ngx_post_event(&ctx->reconnect, &ngx_posted_events);
        return NGX_OK;
    }

    lracf = ngx_rtmp_get_module_app_conf(rs, ngx_live_relay_module);

    if (!pctx->reconnect.timer_set) { // prev relay timeout
        ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2,
                lracf->relay_reconnect);
        ngx_post_event(&ctx->reconnect, &ngx_posted_events);
        return NGX_OK;
    }

    if (pctx->failed_reconnect) {
        ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2,
                lracf->relay_reconnect);
    } else {
        ctx->failed_reconnect = lracf->failed_reconnect;
    }

    ctx->failed_delay = 1;
    ngx_add_timer(&ctx->reconnect, ctx->failed_reconnect);

    return NGX_OK;
}
Ejemplo n.º 21
0
static void
ngx_epoll_eventfd_handler(ngx_event_t *ev)
{
    int               n, events;
    long              i;
    uint64_t          ready;
    ngx_err_t         err;
    ngx_event_t      *e;
    ngx_event_aio_t  *aio;
    struct io_event   event[64];
    struct timespec   ts;

    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd handler");

    n = read(ngx_eventfd, &ready, 8);

    err = ngx_errno;

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd: %d", n);

    if (n != 8) {
        if (n == -1) {
            if (err == NGX_EAGAIN) {
                return;
            }

            ngx_log_error(NGX_LOG_ALERT, ev->log, err, "read(eventfd) failed");
            return;
        }

        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
                      "read(eventfd) returned only %d bytes", n);
        return;
    }

    ts.tv_sec = 0;
    ts.tv_nsec = 0;

    while (ready) {

        events = io_getevents(ngx_aio_ctx, 1, 64, event, &ts);

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                       "io_getevents: %l", events);

        if (events > 0) {
            ready -= events;

            for (i = 0; i < events; i++) {

                ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                               "io_event: %uXL %uXL %L %L",
                                event[i].data, event[i].obj,
                                event[i].res, event[i].res2);

                e = (ngx_event_t *) (uintptr_t) event[i].data;

                e->complete = 1;
                e->active = 0;
                e->ready = 1;

                aio = e->data;
                aio->res = event[i].res;

                ngx_post_event(e, &ngx_posted_events);
            }

            continue;
        }

        if (events == 0) {
            return;
        }

        /* events == -1 */
        ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
                      "io_getevents() failed");
        return;
    }
}
static ngx_int_t
ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
                          ngx_uint_t flags)
{
    int                ready, nready;
    ngx_err_t          err;
    ngx_uint_t         i, found;
    ngx_event_t       *ev;
    ngx_queue_t       *queue;
    struct timeval     tv, *tp;
    ngx_connection_t  *c;

    if (max_fd == -1) {
        for (i = 0; i < nevents; i++) {
            c = event_index[i]->data;
            if (max_fd < c->fd) {
                max_fd = c->fd;
            }
        }

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "change max_fd: %i", max_fd);
    }

#if (NGX_DEBUG)
    if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
        for (i = 0; i < nevents; i++) {
            ev = event_index[i];
            c = ev->data;
            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "select event: fd:%d wr:%d", c->fd, ev->write);
        }

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "max_fd: %i", max_fd);
    }
#endif

    if (timer == NGX_TIMER_INFINITE) {
        tp = NULL;

    } else {
        tv.tv_sec = (long) (timer / 1000);
        tv.tv_usec = (long) ((timer % 1000) * 1000);
        tp = &tv;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "select timer: %M", timer);

    work_read_fd_set = master_read_fd_set;
    work_write_fd_set = master_write_fd_set;

    ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp);

    err = (ready == -1) ? ngx_errno : 0;

    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
        ngx_time_update();
    }

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "select ready %d", ready);

    if (err) {
        ngx_uint_t  level;

        if (err == NGX_EINTR) {

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

            level = NGX_LOG_INFO;

        } else {
            level = NGX_LOG_ALERT;
        }

        ngx_log_error(level, cycle->log, err, "select() failed");

        if (err == NGX_EBADF) {
            ngx_select_repair_fd_sets(cycle);
        }

        return NGX_ERROR;
    }

    if (ready == 0) {
        if (timer != NGX_TIMER_INFINITE) {
            return NGX_OK;
        }

        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                      "select() returned no events without timeout");
        return NGX_ERROR;
    }

    nready = 0;

    for (i = 0; i < nevents; i++) {
        ev = event_index[i];
        c = ev->data;
        found = 0;

        if (ev->write) {
            if (FD_ISSET(c->fd, &work_write_fd_set)) {
                found = 1;
                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                               "select write %d", c->fd);
            }

        } else {
            if (FD_ISSET(c->fd, &work_read_fd_set)) {
                found = 1;
                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                               "select read %d", c->fd);
            }
        }

        if (found) {
            ev->ready = 1;

            queue = ev->accept ? &ngx_posted_accept_events
                    : &ngx_posted_events;

            ngx_post_event(ev, queue);

            nready++;
        }
    }

    if (ready != nready) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                      "select ready != events: %d:%d", ready, nready);

        ngx_select_repair_fd_sets(cycle);
    }

    return NGX_OK;
}
Ejemplo n.º 23
0
static void sigev_notify(union ofp_sigval sv)
{
    struct ofp_sock_sigval *ss = sv.sival_ptr;
    if (!ss)
       return ;
    int s = ss->sockfd;
    int event = ss->event;
    odp_packet_t pkt = ss->pkt;
    ngx_uint_t         i = 0;
    ngx_queue_t       *queue = NULL;
    ngx_event_t       *ev;
    ngx_connection_t  *c;

    if (event == OFP_EVENT_ACCEPT)  {
        for (i = 0; i < nevents; i++) {
            ev = event_index[i];
            c  = ev->data;

            if (ev->accept) {
                ev->ready = 1;
                ev->handler(ev);
                OFP_DBG("%s: posted on ACCEPT EVENT", __func__);
                break;
            }
        }
	return;
    }

    if (event == OFP_EVENT_SEND)  {
	    for (i = 0; i < nevents; i++) {
		    ev = event_index[i];
		    c = ev->data;
		    if (ev->write && CLR_FD_BIT(c->fd)==s) {
			    OFP_DBG("%s: posted SEND event on fd=%d", __func__, s);
			    ev->ready = 1;
			    ngx_post_event(ev, &ngx_posted_events);
		    }
	    }
	    return;
    }

    int r = odp_packet_len(pkt);

    if (r > 0) {
        for (i = 0; i < nevents; i++) {
            ev = event_index[i];
            c  = ev->data;
            if (s == CLR_FD_BIT(c->fd))  {
                queue = &ngx_posted_events;
                ngx_post_event(ev, queue);
                OFP_DBG("%s: posted on RECV EVENT", __func__);
                ev->ready = 1;
                break;
            }
        }
    } else if (r == 0) {
        odp_packet_free(pkt);
        ss->pkt = ODP_PACKET_INVALID;
    }

    return;
}
Ejemplo n.º 24
0
static ngx_int_t
ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
    int                events;
    uint32_t           revents;
    ngx_int_t          instance, i;
    ngx_uint_t         level;
    ngx_err_t          err;
    ngx_event_t       *rev, *wev;
    ngx_queue_t       *queue;
    ngx_connection_t  *c;

    /* NGX_TIMER_INFINITE == INFTIM */

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "epoll timer: %M", timer);

    events = epoll_wait(ep, event_list, (int) nevents, timer);

    err = (events == -1) ? ngx_errno : 0;

    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
        ngx_time_update();
    }

    if (err) {
        if (err == NGX_EINTR) {

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

            level = NGX_LOG_INFO;

        } else {
            level = NGX_LOG_ALERT;
        }

        ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
        return NGX_ERROR;
    }

    if (events == 0) {
        if (timer != NGX_TIMER_INFINITE) {
            return NGX_OK;
        }

        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                      "epoll_wait() returned no events without timeout");
        return NGX_ERROR;
    }

    for (i = 0; i < events; i++) {
        c = event_list[i].data.ptr;

        instance = (uintptr_t) c & 1;
        c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);

        rev = c->read;

        if (c->fd == -1 || rev->instance != instance) {

            /*
             * the stale event from a file descriptor
             * that was just closed in this iteration
             */

            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "epoll: stale event %p", c);
            continue;
        }

        revents = event_list[i].events;

        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "epoll: fd:%d ev:%04XD d:%p",
                       c->fd, revents, event_list[i].data.ptr);

        if (revents & (EPOLLERR|EPOLLHUP)) {
            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "epoll_wait() error on fd:%d ev:%04XD",
                           c->fd, revents);
        }

#if 0
        if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "strange epoll_wait() events fd:%d ev:%04XD",
                          c->fd, revents);
        }
#endif

        if ((revents & (EPOLLERR|EPOLLHUP))
             && (revents & (EPOLLIN|EPOLLOUT)) == 0)
        {
            /*
             * if the error events were returned without EPOLLIN or EPOLLOUT,
             * then add these flags to handle the events at least in one
             * active handler
             */

            revents |= EPOLLIN|EPOLLOUT;
        }

        if ((revents & EPOLLIN) && rev->active) {

#if (NGX_HAVE_EPOLLRDHUP)
            if (revents & EPOLLRDHUP) {
                rev->pending_eof = 1;
            }
#endif

            rev->ready = 1;

            if (flags & NGX_POST_EVENTS) {
                queue = rev->accept ? &ngx_posted_accept_events
                                    : &ngx_posted_events;

                ngx_post_event(rev, queue);

            } else {
                rev->handler(rev);
            }
        }

        wev = c->write;

        if ((revents & EPOLLOUT) && wev->active) {

            if (c->fd == -1 || wev->instance != instance) {

                /*
                 * the stale event from a file descriptor
                 * that was just closed in this iteration
                 */

                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                               "epoll: stale event %p", c);
                continue;
            }

            wev->ready = 1;
#if (NGX_THREADS)
            wev->complete = 1;
#endif

            if (flags & NGX_POST_EVENTS) {
                ngx_post_event(wev, &ngx_posted_events);

            } else {
                wev->handler(wev);
            }
        }
    }

    return NGX_OK;
}
static void
ngx_rtmp_play_send(ngx_event_t *e)
{
    ngx_rtmp_session_t             *s;
    ngx_rtmp_play_ctx_t            *ctx;
    uint32_t                        last_timestamp;
    ngx_rtmp_header_t               h, lh;
    ngx_rtmp_core_srv_conf_t       *cscf;
    ngx_chain_t                    *out, in;
    ngx_buf_t                       in_buf;
    ssize_t                         n;
    uint32_t                        buflen, end_timestamp, size;

    s = e->data;

    cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
    if (ctx == NULL) {
        return;
    }

    if (ctx->offset == -1) {
        ctx->offset = ngx_rtmp_play_timestamp_to_offset(s,
                                                        ctx->start_timestamp);
        ctx->start_timestamp = -1; /* set later from actual timestamp */
    }

    ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                  "play: read tag at offset=%i", ctx->offset);

    /* read tag header */
    n = ngx_read_file(&ctx->file, ngx_rtmp_play_header, 
                      sizeof(ngx_rtmp_play_header), ctx->offset);
    if (n != sizeof(ngx_rtmp_play_header)) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                     "play: could not read flv tag header");
        ngx_rtmp_send_user_stream_eof(s, 1);
        return;
    }

    /* parse header fields */
    ngx_memzero(&h, sizeof(h));
    h.msid = NGX_RTMP_LIVE_MSID;
    h.type = ngx_rtmp_play_header[0];
    size = 0;
    ngx_rtmp_rmemcpy(&size, ngx_rtmp_play_header + 1, 3);
    ngx_rtmp_rmemcpy(&h.timestamp, ngx_rtmp_play_header + 4, 3);
    ((u_char *) &h.timestamp)[3] = ngx_rtmp_play_header[7];

    ctx->offset += (sizeof(ngx_rtmp_play_header) + size + 4);

    last_timestamp = 0;

    switch (h.type) {
        case NGX_RTMP_MSG_AUDIO:
            h.csid = NGX_RTMP_LIVE_CSID_AUDIO;
            last_timestamp = ctx->last_audio;
            ctx->last_audio = h.timestamp;
            break;

        case NGX_RTMP_MSG_VIDEO:
            h.csid = NGX_RTMP_LIVE_CSID_VIDEO;
            last_timestamp = ctx->last_video;
            ctx->last_video = h.timestamp;
            break;

        default:
            goto skip;
    }

    ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                  "play: read tag type=%i size=%uD timestamp=%uD "
                  "last_timestamp=%uD", 
                  (ngx_int_t) h.type,size, h.timestamp, last_timestamp);

    lh = h;
    lh.timestamp = last_timestamp;

    if (size > sizeof(ngx_rtmp_play_buffer)) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                     "play: too big message: %D>%uz", size, 
                      sizeof(ngx_rtmp_play_buffer));
        goto next;
    }

    /* read tag body */
    n = ngx_read_file(&ctx->file, ngx_rtmp_play_buffer, size, 
                      ctx->offset - size - 4);
    if (n != (ssize_t) size) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                     "play: could not read flv tag");
        return;
    }

    /* prepare input chain */
    ngx_memzero(&in, sizeof(in));
    ngx_memzero(&in_buf, sizeof(in_buf));
    in.buf = &in_buf;
    in_buf.pos = ngx_rtmp_play_buffer;
    in_buf.last = ngx_rtmp_play_buffer + size;

    /* output chain */
    out = ngx_rtmp_append_shared_bufs(cscf, NULL, &in);
    ngx_rtmp_prepare_message(s, &h, ctx->msg_mask & (1 << h.type) ? 
                             &lh : NULL, out);
    ngx_rtmp_send_message(s, out, 0); /* TODO: priority */
    ngx_rtmp_free_shared_chain(cscf, out);

    ctx->msg_mask |= (1 << h.type);

next:
    if (ctx->start_timestamp == -1) {
        ctx->start_timestamp = h.timestamp;
        ctx->epoch = ngx_current_msec;
        ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                      "play: start_timestamp=%i", ctx->start_timestamp);
        goto skip;
    }

    buflen = (s->buflen ? s->buflen : NGX_RTMP_PLAY_DEFAULT_BUFLEN);
    end_timestamp = (ngx_current_msec - ctx->epoch) +
                     ctx->start_timestamp + buflen;

    ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
           "play: %s wait=%D timestamp=%D end_timestamp=%D bufen=%i",
            h.timestamp > end_timestamp ? "schedule" : "advance",
            h.timestamp > end_timestamp ? h.timestamp - end_timestamp : 0,
            h.timestamp, end_timestamp, (ngx_int_t) buflen);

    /* too much data sent; schedule timeout */
    if (h.timestamp > end_timestamp) {
        ngx_add_timer(e, h.timestamp - end_timestamp);
        return;
    }

skip:
    ngx_post_event(e, &ngx_posted_events);
}
Ejemplo n.º 26
0
int ngx_epoll_process_events(ngx_cycle_t *cycle)
{
    int                events;
    size_t             n;
    ngx_int_t          instance, i;
    ngx_uint_t         lock, accept_lock, expire;
    ngx_err_t          err;
    ngx_log_t         *log;
    ngx_msec_t         timer;
    ngx_event_t       *rev, *wev;
    struct timeval     tv;
    ngx_connection_t  *c;
    ngx_epoch_msec_t   delta;

    for ( ;; ) { 
        timer = ngx_event_find_timer();

#if (NGX_THREADS)

        if (timer == NGX_TIMER_ERROR) {
            return NGX_ERROR;
        }

        if (timer == NGX_TIMER_INFINITE || timer > 500) {
            timer = 500;
            break;
        }

#endif

        if (timer != 0) {
            break;
        }

        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "epoll expired timer");

        ngx_event_expire_timers((ngx_msec_t)
                                    (ngx_elapsed_msec - ngx_old_elapsed_msec));

        if (ngx_posted_events && ngx_threaded) {
            ngx_wakeup_worker_thread(cycle);
        }
    }

    /* NGX_TIMER_INFINITE == INFTIM */

    if (timer == NGX_TIMER_INFINITE) {
        expire = 0;

    } else {
        expire = 1;
    }

    ngx_old_elapsed_msec = ngx_elapsed_msec;
    accept_lock = 0;

    if (ngx_accept_mutex) {
        if (ngx_accept_disabled > 0) {
            ngx_accept_disabled--;

        } else {
            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
                return NGX_ERROR;
            }

            if (ngx_accept_mutex_held) {
                accept_lock = 1;

            } else if (timer == NGX_TIMER_INFINITE
                       || timer > ngx_accept_mutex_delay)
            {
                timer = ngx_accept_mutex_delay;
                expire = 0;
            }
        }
    }

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "epoll timer: %d", timer);

    events = epoll_wait(ep, event_list, nevents, timer);

    if (events == -1) {
        err = ngx_errno;
    } else {
        err = 0;
    }

    ngx_gettimeofday(&tv);
    ngx_time_update(tv.tv_sec);

    delta = ngx_elapsed_msec;
    ngx_elapsed_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000
                                          + tv.tv_usec / 1000 - ngx_start_msec;

    if (timer != NGX_TIMER_INFINITE) {
        delta = ngx_elapsed_msec - delta;

        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "epoll timer: %d, delta: %d", timer, (int) delta);
    } else {
        if (events == 0) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "epoll_wait() returned no events without timeout");
            ngx_accept_mutex_unlock();
            return NGX_ERROR;
        }
    }

    if (err) {
        ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
                      cycle->log, err, "epoll_wait() failed");
        ngx_accept_mutex_unlock();
        return NGX_ERROR;
    }

    if (events > 0) {
        if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
            ngx_accept_mutex_unlock();
            return NGX_ERROR;
        } 

        lock = 1;

    } else {
        lock =0;
    }

    log = cycle->log;

    for (i = 0; i < events; i++) {
        c = event_list[i].data.ptr;

        instance = (uintptr_t) c & 1;
        c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);

        rev = c->read;

        if (c->fd == -1 || rev->instance != instance) {

            /*
             * the stale event from a file descriptor
             * that was just closed in this iteration
             */

            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "epoll: stale event " PTR_FMT, c);
            continue;
        }

#if (NGX_DEBUG0)
        log = c->log ? c->log : cycle->log;
#endif

        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
                       "epoll: fd:%d ev:%04X d:" PTR_FMT,
                       c->fd, event_list[i].events, event_list[i].data);

        if (event_list[i].events & (EPOLLERR|EPOLLHUP)) {
            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
                           "epoll_wait() error on fd:%d ev:%04X",
                           c->fd, event_list[i].events);
        }

        if (event_list[i].events & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
            ngx_log_error(NGX_LOG_ALERT, log, 0,
                          "strange epoll_wait() events fd:%d ev:%04X",
                          c->fd, event_list[i].events);
        }

        wev = c->write;

        if ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP))
            && wev->active)
        {
            if (ngx_threaded) {
                wev->posted_ready = 1;
                ngx_post_event(wev);

            } else {
                wev->ready = 1;

                if (!ngx_accept_mutex_held) {
                    wev->event_handler(wev);

                } else {
                    ngx_post_event(wev);
                }
            }
        }

        /*
         * EPOLLIN must be handled after EPOLLOUT because we use
         * the optimization to avoid the unnecessary mutex locking/unlocking
         * if the accept event is the last one.
         */

        if ((event_list[i].events & (EPOLLIN|EPOLLERR|EPOLLHUP))
            && rev->active)
        {
            if (ngx_threaded && !rev->accept) {
                rev->posted_ready = 1;

                ngx_post_event(rev);

                continue;
            }

            rev->ready = 1;

            if (!ngx_threaded && !ngx_accept_mutex_held) {
                rev->event_handler(rev);

            } else if (!rev->accept) {
                ngx_post_event(rev);

            } else if (ngx_accept_disabled <= 0) {

                ngx_mutex_unlock(ngx_posted_events_mutex);

                rev->event_handler(rev);

                if (ngx_accept_disabled > 0) {
                    ngx_accept_mutex_unlock();
                    accept_lock = 0;
                }

                if (i + 1 == events) {
                    lock = 0;
                    break;
                }

                if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
                    if (accept_lock) {
                        ngx_accept_mutex_unlock();
                    }
                    return NGX_ERROR;
                }
            }
        }
    }

    if (accept_lock) {
        ngx_accept_mutex_unlock();
    }

    if (lock) {
        ngx_mutex_unlock(ngx_posted_events_mutex);
    }

    if (expire && delta) {
        ngx_event_expire_timers((ngx_msec_t) delta);
    }

    if (ngx_posted_events) {
        if (ngx_threaded) {
            ngx_wakeup_worker_thread(cycle);

        } else {
            ngx_event_process_posted(cycle);
        }
    }

    return NGX_OK;
}
// if stream's need to continue pull or push chain, otherwise return NGX_OK
static ngx_int_t
ngx_live_relay_inner_relay(ngx_rtmp_session_t *s, unsigned publishing)
{
    ngx_rtmp_session_t                 *rs;
    ngx_live_relay_ctx_t               *ctx, *pctx;
    ngx_live_relay_app_conf_t          *lracf;
    ngx_int_t                           pslot;

    pslot = ngx_stream_zone_insert_stream(&s->stream);
    if (pslot == NGX_ERROR) { // stream zone not configured or configured error
        ngx_log_error(NGX_LOG_ERR, s->log, 0,
                "inner relay, insert stream %V failed", &s->stream);
        return NGX_DECLINED;
    }

    ngx_log_error(NGX_LOG_INFO, s->log, 0,
            "inner relay, stream %V not in current process, "
            "pslot:%i ngx_process_slot:%i",
            &s->stream, pslot, ngx_process_slot);

    s->live_stream->pslot = pslot;
    if (pslot == ngx_process_slot) { // current process become stream owner
        return NGX_DECLINED;
    }

    rs = ngx_rtmp_create_relay_session(s, &ngx_live_relay_inner_module);
    if (rs == NULL) {
        ngx_log_error(NGX_LOG_ERR, s->log, 0,
                "inner relay, create relay session failed");
        return NGX_DECLINED;
    }
    rs->publishing = publishing;
    rs->live_stream = s->live_stream;
    ngx_live_create_ctx(rs, publishing);

    ctx = ngx_rtmp_get_module_ctx(rs, ngx_live_relay_module);
    ctx->reconnect.log = rs->log;
    ctx->reconnect.data = rs;
    ctx->reconnect.handler = ngx_live_relay_inner_handler;

    lracf = ngx_rtmp_get_module_app_conf(rs, ngx_live_relay_module);

    // play trigger pull or publish trigger push
    if (s->publishing != rs->publishing) {
        ngx_post_event(&ctx->reconnect, &ngx_posted_events);
        return NGX_OK;
    }

    // normal publisher close, need to trigger pull
    if (s->publishing && !s->relay) {
        ngx_post_event(&ctx->reconnect, &ngx_posted_events);
        return NGX_OK;
    }

    // reconnect
    pctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module);
    if (pctx->successd) { // prev relay susccessd
        ngx_post_event(&ctx->reconnect, &ngx_posted_events);
        return NGX_OK;
    }

    if (!pctx->reconnect.timer_set) { // prev relay timeout
        ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2,
                lracf->relay_reconnect);
        ngx_post_event(&ctx->reconnect, &ngx_posted_events);
        return NGX_OK;
    }

    if (pctx->failed_reconnect) {
        ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2,
                lracf->relay_reconnect);
    } else {
        ctx->failed_reconnect = lracf->failed_reconnect;
    }

    ctx->failed_delay = 1;
    ngx_add_timer(&ctx->reconnect, ctx->failed_reconnect);

    return NGX_OK;
}
Ejemplo n.º 28
0
/**
 *  @param [in] cycle cycle对象
 *  @param [in] timer 阻塞时间
 *  @param [in] flags 是否更新时间片(0/NGX_UPDATE_TIME),是否后置处理NGX_POST_EVENTS
 *  @return NGX_OK|NGX_ERROR
 *  收集、分发事件。事件触发时,只有一个worker进入
 */
static ngx_int_t
ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
    int                events;
    uint32_t           revents;
    ngx_int_t          instance, i;
    ngx_uint_t         level;
    ngx_err_t          err;
    ngx_event_t       *rev, *wev;
    ngx_queue_t       *queue;
    ngx_connection_t  *c;

    /* NGX_TIMER_INFINITE == INFTIM */

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "epoll timer: %M", timer);

    //等待事件,最长等待时间为timer
    events = epoll_wait(ep, event_list, (int) nevents, timer);

    err = (events == -1) ? ngx_errno : 0;

    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
        ngx_time_update();  //更新时间
    }

    if (err) {
        if (err == NGX_EINTR) {

            if (ngx_event_timer_alarm) {	//epoll失败是由定时器打断
                ngx_event_timer_alarm = 0;
                return NGX_OK;
            }

            level = NGX_LOG_INFO;

        } else {
            level = NGX_LOG_ALERT;
        }

        ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
        return NGX_ERROR;
    }

    if (events == 0) {
        if (timer != NGX_TIMER_INFINITE) {	//非阻塞
            return NGX_OK;
        }
		
		//若epoll非阻塞方式,但却失败了,记录并返回错误
        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                      "epoll_wait() returned no events without timeout");
        return NGX_ERROR;
    }

    for (i = 0; i < events; i++) {
        c = event_list[i].data.ptr;

        //提取出instance标志
        instance = (uintptr_t) c & 1;
        //屏蔽最后一位计算出真正的连接对象的地址
        c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);

        //取出读事件
        rev = c->read;

        //推断这个读事件是否过期
        if (c->fd == -1 || rev->instance != instance) {

            /*
             * the stale event from a file descriptor
             * that was just closed in this iteration
             */

            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "epoll: stale event %p", c);
            continue;
        }

        //获得事件类型
        revents = event_list[i].events;

        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "epoll: fd:%d ev:%04XD d:%p",
                       c->fd, revents, event_list[i].data.ptr);

        if (revents & (EPOLLERR|EPOLLHUP)) {
            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "epoll_wait() error on fd:%d ev:%04XD",
                           c->fd, revents);
        }

#if 0
        if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "strange epoll_wait() events fd:%d ev:%04XD",
                          c->fd, revents);
        }
#endif

        if ((revents & (EPOLLERR|EPOLLHUP))
             && (revents & (EPOLLIN|EPOLLOUT)) == 0)
        {
            /*
             * if the error events were returned without EPOLLIN or EPOLLOUT,
             * then add these flags to handle the events at least in one
             * active handler
             */

            revents |= EPOLLIN|EPOLLOUT;
        }

        //读事件触发且该事件是活跃的
        if ((revents & EPOLLIN) && rev->active) {

#if (NGX_HAVE_EPOLLRDHUP)
            if (revents & EPOLLRDHUP) {
                rev->pending_eof = 1;
            }
#endif

            rev->ready = 1;

            //事件需要延后处理
            if (flags & NGX_POST_EVENTS) {
                /**
                 * 如果要在post队列中延后处理该事件,首先要判断它是新连接事件还是普通事件
                 * 以确定是把它加入到ngx_posted_accept_events队列或者ngx_posted_events队列中
                 */
                queue = rev->accept ? &ngx_posted_accept_events
                                    : &ngx_posted_events;
                
                //将该事件添加到相应的延后队列中。@ngx_locked_post_event(rev, queue);
                ngx_post_event(rev, queue);

            } else {
                /**
                 * \file ngx_epoll_module.c
				 * 立即调用事件回调方法来处理这个事件
                 * Listen Socket连接为ngx_event_accept,ngx_event_process_init被赋值
                 */
                rev->handler(rev);
            }
        }

        //取出写事件
        wev = c->write;

        //写事件触发且该事件是活跃的
        if ((revents & EPOLLOUT) && wev->active) {

            if (c->fd == -1 || wev->instance != instance) {

                /*
                 * the stale event from a file descriptor
                 * that was just closed in this iteration
                 */

                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                               "epoll: stale event %p", c);
                continue;
            }

            wev->ready = 1;

            //事件需要延后处理
            if (flags & NGX_POST_EVENTS) {
                //将该事件添加到相应的延后队列中,普通队列。@ngx_locked_post_event(rev, queue);
                ngx_post_event(wev, &ngx_posted_events);

            } else {
                //立即调用事件回调方法来处理这个事件
                wev->handler(wev);
            }
        }
    }

    return NGX_OK;
}
Ejemplo n.º 29
0
static ngx_int_t
ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
                          ngx_uint_t flags)
{
    int               events, n;
    ngx_int_t         i, instance;
    ngx_uint_t        level;
    ngx_err_t         err;
    ngx_event_t      *ev;
    ngx_queue_t      *queue;
    struct timespec   ts, *tp;
    n = (int) nchanges;
    nchanges = 0;
    if (timer == NGX_TIMER_INFINITE)
    {
        tp = NULL;
    }
    else
    {
        ts.tv_sec = timer / 1000;
        ts.tv_nsec = (timer % 1000) * 1000000;
        /*
         * 64-bit Darwin kernel has the bug: kernel level ts.tv_nsec is
         * the int32_t while user level ts.tv_nsec is the long (64-bit),
         * so on the big endian PowerPC all nanoseconds are lost.
         */
#if (NGX_DARWIN_KEVENT_BUG)
        ts.tv_nsec <<= 32;
#endif
        tp = &ts;
    }
    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "kevent timer: %M, changes: %d", timer, n);
    events = kevent(ngx_kqueue, change_list, n, event_list, (int) nevents, tp);
    err = (events == -1) ? ngx_errno : 0;
    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm)
    {
        ngx_time_update();
    }
    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "kevent events: %d", events);
    if (err)
    {
        if (err == NGX_EINTR)
        {
            if (ngx_event_timer_alarm)
            {
                ngx_event_timer_alarm = 0;
                return NGX_OK;
            }
            level = NGX_LOG_INFO;
        }
        else
        {
            level = NGX_LOG_ALERT;
        }
        ngx_log_error(level, cycle->log, err, "kevent() failed");
        return NGX_ERROR;
    }
    if (events == 0)
    {
        if (timer != NGX_TIMER_INFINITE)
        {
            return NGX_OK;
        }
        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                      "kevent() returned no events without timeout");
        return NGX_ERROR;
    }
    for (i = 0; i < events; i++)
    {
        ngx_kqueue_dump_event(cycle->log, &event_list[i]);
        if (event_list[i].flags & EV_ERROR)
        {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, event_list[i].data,
                          "kevent() error on %d filter:%d flags:%04Xd",
                          event_list[i].ident, event_list[i].filter,
                          event_list[i].flags);
            continue;
        }
#if (NGX_HAVE_TIMER_EVENT)
        if (event_list[i].filter == EVFILT_TIMER)
        {
            ngx_time_update();
            continue;
        }
#endif
        ev = (ngx_event_t *) event_list[i].udata;
        switch (event_list[i].filter)
        {
        case EVFILT_READ:
        case EVFILT_WRITE:
            instance = (uintptr_t) ev & 1;
            ev = (ngx_event_t *)((uintptr_t) ev & (uintptr_t) ~1);
            if (ev->closed || ev->instance != instance)
            {
                /*
                 * the stale event from a file descriptor
                 * that was just closed in this iteration
                 */
                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                               "kevent: stale event %p", ev);
                continue;
            }
            if (ev->log && (ev->log->log_level & NGX_LOG_DEBUG_CONNECTION))
            {
                ngx_kqueue_dump_event(ev->log, &event_list[i]);
            }
            if (ev->oneshot)
            {
                ev->active = 0;
            }
            ev->available = event_list[i].data;
            if (event_list[i].flags & EV_EOF)
            {
                ev->pending_eof = 1;
                ev->kq_errno = event_list[i].fflags;
            }
            ev->ready = 1;
            break;
        case EVFILT_VNODE:
            ev->kq_vnode = 1;
            break;
        case EVFILT_AIO:
            ev->complete = 1;
            ev->ready = 1;
            break;
#ifdef EVFILT_USER
        case EVFILT_USER:
            break;
#endif
        default:
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "unexpected kevent() filter %d",
                          event_list[i].filter);
            continue;
        }
        if (flags & NGX_POST_EVENTS)
        {
            queue = ev->accept ? &ngx_posted_accept_events
                    : &ngx_posted_events;
            ngx_post_event(ev, queue);
            continue;
        }
        ev->handler(ev);
    }
    return NGX_OK;
}
Ejemplo n.º 30
0
void
ngx_tcp2http_init_connection(ngx_connection_t *c)
{
    ngx_uint_t              i;
    ngx_event_t            *rev;
    struct sockaddr_in     *sin;
    ngx_http_port_t        *port;
    ngx_http_in_addr_t     *addr;
    ngx_http_log_ctx_t     *ctx;
    ngx_http_connection_t  *hc;
#if (NGX_HAVE_INET6)
    struct sockaddr_in6    *sin6;
    ngx_http_in6_addr_t    *addr6;
#endif

    hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
    if (hc == NULL) {
        ngx_http_close_connection(c);
        return;
    }

    c->data = hc;

    /* find the server configuration for the address:port */

    port = c->listening->servers;

    if (port->naddrs > 1) {

        /*
         * there are several addresses on this port and one of them
         * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
         * is required to determine a server address
         */

        if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
            ngx_http_close_connection(c);
            return;
        }

        switch (c->local_sockaddr->sa_family) {

#if (NGX_HAVE_INET6)
        case AF_INET6:
            sin6 = (struct sockaddr_in6 *) c->local_sockaddr;

            addr6 = port->addrs;

            /* the last address is "*" */

            for (i = 0; i < port->naddrs - 1; i++) {
                if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
                    break;
                }
            }

            hc->addr_conf = &addr6[i].conf;

            break;
#endif

        default: /* AF_INET */
            sin = (struct sockaddr_in *) c->local_sockaddr;

            addr = port->addrs;

            /* the last address is "*" */

            for (i = 0; i < port->naddrs - 1; i++) {
                if (addr[i].addr == sin->sin_addr.s_addr) {
                    break;
                }
            }

            hc->addr_conf = &addr[i].conf;

            break;
        }

    } else {

        switch (c->local_sockaddr->sa_family) {

#if (NGX_HAVE_INET6)
        case AF_INET6:
            addr6 = port->addrs;
            hc->addr_conf = &addr6[0].conf;
            break;
#endif

        default: /* AF_INET */
            addr = port->addrs;
            hc->addr_conf = &addr[0].conf;
            break;
        }
    }

    /* the default server configuration for the address:port */
    hc->conf_ctx = hc->addr_conf->default_server->ctx;

    ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
    if (ctx == NULL) {
        ngx_http_close_connection(c);
        return;
    }

    ctx->connection = c;
    ctx->request = NULL;
    ctx->current_request = NULL;

    c->log->connection = c->number;
    c->log->handler = ngx_tcp2http_log_error;
    c->log->data = ctx;
    c->log->action = "waiting for request";

    c->log_error = NGX_ERROR_INFO;

    rev = c->read;
    rev->handler = ngx_tcp2http_init_session;
	rev->data=c;
    c->write->handler = ngx_tcp2http_empty_handler;

/*
#if (NGX_STAT_STUB)
    (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
#endif
*/
    if (rev->ready) {
        /* the deferred accept(), rtsig, aio, iocp */

        if (ngx_use_accept_mutex) {
            ngx_post_event(rev, &ngx_posted_events);
            return;
        }

        rev->handler(rev);
        return;
    }

    ngx_add_timer(rev, c->listening->post_accept_timeout);

    if (ngx_handle_read_event(rev, 0) != NGX_OK) {
/*
#if (NGX_STAT_STUB)
        (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
#endif
*/
        ngx_http_close_connection(c);
        return;
    }

}