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; }
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); }
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"); }
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; } }
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; }
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); }
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; }
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; }
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; }
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); }
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; }
/** * @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; }
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; }
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; } }