ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) { ssize_t n, written; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "write: %d, %p, %uz, %O", file->fd, buf, size, offset); written = 0; #if (NGX_HAVE_PWRITE) for ( ;; ) { n = pwrite(file->fd, buf + written, size, offset); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() \"%s\" failed", file->name.data); return NGX_ERROR; } file->offset += n; written += n; if ((size_t) n == size) { return written; } offset += n; size -= n; } #else if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() \"%s\" failed", file->name.data); return NGX_ERROR; } file->sys_offset = offset; } for ( ;; ) { n = write(file->fd, buf + written, size); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() \"%s\" failed", file->name.data); return NGX_ERROR; } file->offset += n; written += n; if ((size_t) n == size) { return written; } size -= n; } #endif }
ngx_chain_t * ngx_rtmp_create_play_status(ngx_rtmp_session_t *s, char *code, char* level, ngx_uint_t duration, ngx_uint_t bytes) { ngx_rtmp_header_t h; static double dduration; static double dbytes; static ngx_rtmp_amf_elt_t out_inf[] = { { NGX_RTMP_AMF_STRING, ngx_string("code"), NULL, 0 }, { NGX_RTMP_AMF_STRING, ngx_string("level"), NULL, 0 }, { NGX_RTMP_AMF_NUMBER, ngx_string("duration"), &dduration, 0 }, { NGX_RTMP_AMF_NUMBER, ngx_string("bytes"), &dbytes, 0 }, }; static ngx_rtmp_amf_elt_t out_elts[] = { { NGX_RTMP_AMF_STRING, ngx_null_string, "onPlayStatus", 0 }, { NGX_RTMP_AMF_OBJECT, ngx_null_string, out_inf, sizeof(out_inf) }, }; ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "create: play_status code='%s' level='%s' " "duration=%ui bytes=%ui", code, level, duration, bytes); out_inf[0].data = code; out_inf[1].data = level; dduration = duration; dbytes = bytes; memset(&h, 0, sizeof(h)); h.type = NGX_RTMP_MSG_AMF_META; h.csid = NGX_RTMP_CSID_AMF; h.msid = NGX_RTMP_MSID; h.timestamp = duration; return ngx_rtmp_create_amf(s, &h, out_elts, sizeof(out_elts) / sizeof(out_elts[0])); }
//在ngx_thread_read把该handler添加到线程池中 static void //ngx_thread_read->ngx_thread_read_handler ngx_thread_read_handler(void *data, ngx_log_t *log) {//该函数执行后,会通过ngx_notify执行event.handler = ngx_http_cache_thread_event_handler; ngx_thread_read_ctx_t *ctx = data; ssize_t n; ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "thread read handler"); //缓存文件数据会拷贝到dst中,也就是ngx_output_chain_ctx_t->buf,然后在ngx_output_chain_copy_buf函数外层会重新把ctx->buf赋值给新的chain,然后write出去 n = pread(ctx->fd, ctx->buf, ctx->size, ctx->offset); if (n == -1) { ctx->err = ngx_errno; } else { ctx->read = n; ctx->err = 0; } #if 0 ngx_time_update(); #endif ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0, "pread read return read size: %z (err: %i) of buf-size%uz offset@%O", n, ctx->err, ctx->size, ctx->offset); }
static void * ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size) { ngx_http_gzip_ctx_t *ctx = opaque; void *p; ngx_uint_t alloc; alloc = items * size; if (alloc % 512 != 0 && alloc < 8192) { /* * The zlib deflate_state allocation, it takes about 6K, * we allocate 8K. Other allocations are divisible by 512. */ alloc = 8192; } if (alloc <= ctx->allocated) { p = ctx->free_mem; ctx->free_mem += alloc; ctx->allocated -= alloc; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0, "gzip alloc: n:%ud s:%ud a:%ud p:%p", items, size, alloc, p); return p; } ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0, "gzip filter failed to use preallocated memory: %ud of %ud", items * size, ctx->allocated); p = ngx_palloc(ctx->request->pool, items * size); return p; }
static void ngx_thread_read_handler(void *data, ngx_log_t *log) { ngx_thread_read_ctx_t *ctx = data; ssize_t n; ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "thread read handler"); n = pread(ctx->fd, ctx->buf, ctx->size, ctx->offset); if (n == -1) { ctx->err = ngx_errno; } else { ctx->read = n; ctx->err = 0; } #if 0 ngx_time_update(); #endif ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0, "pread: %z (err: %i) of %uz @%O", n, ctx->err, ctx->size, ctx->offset); }
ssize_t ngx_udp_wsarecv(ngx_connection_t *c, u_char *buf, size_t size) { int rc; u_long bytes, flags; WSABUF wsabuf[1]; ngx_err_t err; ngx_event_t *rev; wsabuf[0].buf = (char *) buf; wsabuf[0].len = size; flags = 0; bytes = 0; rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, NULL, NULL); ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSARecv: fd:%d rc:%d %ul of %z", c->fd, rc, bytes, size); rev = c->read; if (rc == -1) { rev->ready = 0; err = ngx_socket_errno; if (err == WSAEWOULDBLOCK) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "WSARecv() not ready"); return NGX_AGAIN; } rev->error = 1; ngx_connection_error(c, err, "WSARecv() failed"); return NGX_ERROR; } return bytes; }
static ngx_int_t ngx_http_session_store_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_session_store_loc_conf_t *sslcf; sslcf = ngx_http_get_module_loc_conf(r, ngx_http_session_store_module); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session handler: store_shm_zone=%p, store_index=%d, get_shm_zone=%p, get_index=%d", sslcf->store_shm_zone, sslcf->store_index[0], sslcf->get_shm_zone, sslcf->get_index[0]); if (sslcf->store_shm_zone != NULL && sslcf->store_index[0] != NGX_CONF_UNSET_UINT) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session store"); rc = ngx_http_session_store_by_key(r); if (rc == NGX_ERROR) { return NGX_ERROR; } } if (sslcf->get_shm_zone != NULL && sslcf->get_index[0] != NGX_CONF_UNSET_UINT) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session get"); rc = ngx_http_session_get_by_key(r); if (rc == NGX_ERROR) { return NGX_ERROR; } } return NGX_DECLINED; }
ngx_int_t ngx_open_pipes(ngx_cycle_t *cycle) { ngx_int_t stat; ngx_uint_t i; ngx_core_conf_t *ccf; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); for (i = 0; i < ngx_last_pipe; i++) { if (!ngx_pipes[i].configured) { continue; } if (ngx_pipes[i].generation != ngx_pipe_generation) { continue; } ngx_pipes[i].backup = ngx_pipes[i].open_fd->name; ngx_pipes[i].user = ccf->user; stat = ngx_open_pipe(cycle, &ngx_pipes[i]); ngx_log_debug4(NGX_LOG_DEBUG_CORE, cycle->log, 0, "pipe: %ui(%d, %d) \"%s\"", i, ngx_pipes[i].pfd[0], ngx_pipes[i].pfd[1], ngx_pipes[i].cmd); if (stat == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "open pipe \"%s\" failed", ngx_pipes[i].cmd); return NGX_ERROR; } if (fcntl(ngx_pipes[i].open_fd->fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", ngx_pipes[i].cmd); return NGX_ERROR; } if (ngx_nonblocking(ngx_pipes[i].open_fd->fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "nonblock \"%s\" failed", ngx_pipes[i].cmd); return NGX_ERROR; } ngx_pipes[i].open_fd->name.len = 0; ngx_pipes[i].open_fd->name.data = NULL; } return NGX_OK; }
ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) { ssize_t n; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "write: %d, %p, %uz, %O", file->fd, buf, size, offset); #if (NGX_HAVE_PWRITE) n = pwrite(file->fd, buf, size, offset); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed"); return NGX_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "pwrite() has written only %z of %uz", n, size); return NGX_ERROR; } #else if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); return NGX_ERROR; } file->sys_offset = offset; } n = write(file->fd, buf, size); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() failed"); return NGX_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "write() has written only %z of %uz", n, size); return NGX_ERROR; } file->sys_offset += n; #endif file->offset += n; return n; }
ssize_t ngx_udp_wsasend(ngx_connection_t *c, u_char *buf, size_t size) { int n; u_long sent; ngx_err_t err; ngx_event_t *wev; WSABUF wsabuf; wev = c->write; if (!wev->ready) { return NGX_AGAIN; } /* * WSABUF must be 4-byte aligned otherwise * WSASend() will return undocumented WSAEINVAL error. */ wsabuf.buf = (char *) buf; wsabuf.len = size; sent = 0; n = WSASendTo(c->fd,&wsabuf,1,&sent,0,c->sockaddr, c->socklen,NULL,NULL); ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSASend: fd:%d, %d, %ul of %uz", c->fd, n, sent, size); if (n == 0) { if (sent < size) { wev->ready = 0; } c->sent += sent; return sent; } err = ngx_socket_errno; if (err == WSAEWOULDBLOCK) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "WSASend() not ready"); wev->ready = 0; return NGX_AGAIN; } wev->error = 1; ngx_connection_error(c, err, "WSASend() failed"); return NGX_ERROR; }
ngx_int_t ngx_rtmp_relay_push(ngx_rtmp_session_t *s, ngx_str_t *name, ngx_rtmp_relay_target_t *target) { ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "relay: create push name='%V' app='%V' playpath='%V' url='%V'", name, &target->app, &target->play_path, &target->url.url); return ngx_rtmp_relay_create(s, name, target, ngx_rtmp_relay_create_local_ctx, ngx_rtmp_relay_create_remote_ctx); }
ssize_t ngx_thread_read(ngx_thread_task_t **taskp, ngx_file_t *file, u_char *buf, size_t size, off_t offset, ngx_pool_t *pool) { ngx_thread_task_t *task; ngx_thread_read_ctx_t *ctx; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "thread read: %d, %p, %uz, %O", file->fd, buf, size, offset); task = *taskp; if (task == NULL) { task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_read_ctx_t)); if (task == NULL) { return NGX_ERROR; } task->handler = ngx_thread_read_handler; *taskp = task; } ctx = task->ctx; if (task->event.complete) { task->event.complete = 0; if (ctx->err) { ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err, "pread() \"%s\" failed", file->name.data); return NGX_ERROR; } return ctx->read; } ctx->fd = file->fd; ctx->buf = buf; ctx->size = size; ctx->offset = offset; if (file->thread_handler(task, file) != NGX_OK) { return NGX_ERROR; } return NGX_AGAIN; }
static ngx_int_t ngx_http_subs_output(ngx_http_request_t *r, ngx_http_subs_ctx_t *ctx, ngx_chain_t *in) { ngx_int_t rc; #if SUBS_DEBUG ngx_buf_t *b; ngx_chain_t *cl; for (cl = ctx->out; cl; cl = cl->next) { b = cl->buf; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "subs out buffer:%p, size:%uz, t:%d, l:%d", b, ngx_buf_size(b), b->temporary, b->last_buf); } #endif /* ctx->out may not output all the data */ rc = ngx_http_next_body_filter(r, ctx->out); if (rc == NGX_ERROR) { return NGX_ERROR; } #if SUBS_DEBUG for (cl = ctx->out; cl; cl = cl->next) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "subs out end: %p %uz", cl->buf, ngx_buf_size(cl->buf)); } #endif #if defined(nginx_version) && (nginx_version >= 1001004) ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out, (ngx_buf_tag_t) &ngx_http_subs_filter_module); #else ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out, (ngx_buf_tag_t) &ngx_http_subs_filter_module); #endif if (ctx->last) { r->connection->buffered &= ~NGX_HTTP_SUB_BUFFERED; } return rc; }
ssize_t ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) { ssize_t n; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "read: %d, %p, %uz, %O", file->fd, buf, size, offset); #if (NGX_HAVE_PREAD) n = pread(file->fd, buf, size, offset); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pread() \"%s\" failed", file->name.data); return NGX_ERROR; } #else if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() \"%s\" failed", file->name.data); return NGX_ERROR; } file->sys_offset = offset; } n = read(file->fd, buf, size); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "read() \"%s\" failed", file->name.data); return NGX_ERROR; } file->sys_offset += n; #endif file->offset += n; return n; }
void ngx_http_tfs_dump_rc_info(ngx_http_tfs_rcs_info_t *rc_info, ngx_log_t *log) { uint32_t i, j, k; ngx_http_tfs_group_info_t *group_info; ngx_http_tfs_logical_cluster_t *logical_clusters; ngx_http_tfs_physical_cluster_t *physical_clusters; ngx_http_tfs_cluster_group_info_t *unlink_cluster_groups; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "=========dump rc info for appkey: %V =========", &rc_info->appkey); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, "appid: %uL, logical_cluster_count: %uD", rc_info->app_id, rc_info->logical_cluster_count); logical_clusters = rc_info->logical_clusters; for (i = 0; i < rc_info->logical_cluster_count; i++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "need_duplicate: %ud", logical_clusters[i].need_duplicate); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "rw_cluster_count: %uD", logical_clusters[i].rw_cluster_count); physical_clusters = logical_clusters[i].rw_clusters; for (j = 0; j < logical_clusters[i].rw_cluster_count; j++) { ngx_log_debug4(NGX_LOG_DEBUG_HTTP, log, 0, "cluster_stat: %uD, access_type: %uD, cluster_id: %V, ns_vip: %V", physical_clusters[j].cluster_stat, physical_clusters[j].access_type, &physical_clusters[j].cluster_id_text, &physical_clusters[j].ns_vip_text); } } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "unlink_cluster_group_count: %ud", rc_info->unlink_cluster_group_count); unlink_cluster_groups = rc_info->unlink_cluster_groups; for (j = 0; j < rc_info->unlink_cluster_group_count; j++) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, log, 0, "cluster_id: %ud, info_count: %uD, group_count: %D", unlink_cluster_groups[j].cluster_id, unlink_cluster_groups[j].info_count, unlink_cluster_groups[j].group_count); group_info = unlink_cluster_groups[j].group_info; for (k = 0; k < unlink_cluster_groups[j].info_count; k++) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, "group_seq: %D, ns_vip: %V", group_info[k].group_seq, &group_info[k].ns_vip_text); } } }
static ngx_int_t ngx_http_subs_body_filter_init_context(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_subs_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_subs_filter_module); r->connection->buffered |= NGX_HTTP_SUB_BUFFERED; ctx->in = NULL; if (in) { if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) { return NGX_ERROR; } } #if SUBS_DEBUG if (ngx_buf_size(ctx->line_in) > 0) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "subs line in buffer: %p, size:%uz", ctx->line_in, ngx_buf_size(ctx->line_in)); } #endif #if SUBS_DEBUG ngx_chain_t *cl; for (cl = ctx->in; cl; cl = cl->next) { if (cl->buf) { ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "subs in buffer:%p, size:%uz, " "flush:%d, last_buf:%d", cl->buf, ngx_buf_size(cl->buf), cl->buf->flush, cl->buf->last_buf); } } #endif ctx->last_out = &ctx->out; ctx->out_buf = NULL; return NGX_OK; }
static void ngx_tcp_check_begin_handler(ngx_event_t *event) { ngx_tcp_check_peer_conf_t *peer_conf; ngx_tcp_upstream_srv_conf_t *uscf; if (ngx_tcp_check_need_exit()) { return; } peer_conf = event->data; uscf = peer_conf->conf; ngx_add_timer(event, uscf->check_interval/2); /* This process are processing the event now. */ if (peer_conf->shm->owner == ngx_pid) { return; } ngx_log_debug4(NGX_LOG_DEBUG_TCP, event->log, 0, "tcp check begin handler index:%ud, owner: %d, " "ngx_pid: %ud, time:%d", peer_conf->index, peer_conf->shm->owner, ngx_pid, (ngx_current_msec - peer_conf->shm->access_time)); ngx_spinlock(&peer_conf->shm->lock, ngx_pid, 1024); if (((ngx_current_msec - peer_conf->shm->access_time) >= uscf->check_interval) && peer_conf->shm->owner == NGX_INVALID_PID) { peer_conf->shm->owner = ngx_pid; } ngx_spinlock_unlock(&peer_conf->shm->lock); if (peer_conf->shm->owner == ngx_pid) { ngx_tcp_check_connect_handler(event); } }
static ngx_int_t ngx_rtmp_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) { ngx_rtmp_live_app_conf_t *lacf; lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); if (lacf == NULL || !lacf->live) { goto next; } ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "live: play: name='%s' start=%uD duration=%uD reset=%d", v->name, (uint32_t)v->start, (uint32_t)v->duration, (uint32_t)v->reset); /* join stream as player */ ngx_rtmp_live_join(s, v->name, 0); next: return next_play(s, v); }
static ngx_int_t ngx_rtmp_gop_cache_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) { ngx_rtmp_gop_cache_app_conf_t *gacf; #ifdef NGX_DEBUG ngx_msec_t start, end; #endif gacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_gop_cache_module); if (gacf == NULL || !gacf->gop_cache) { goto next; } ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "gop cache play: name='%s' start='%i' duration='%i' reset='%d'", v->name, (ngx_int_t) v->start, (ngx_int_t) v->duration, (ngx_uint_t) v->reset); #ifdef NGX_DEBUG start = ngx_current_msec; ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "gop cache send: start_time='%uD'", start); #endif ngx_rtmp_gop_cache_send(s); #ifdef NGX_DEBUG end = ngx_current_msec; ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "gop cache send: end_time='%uD'", end); ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "gop cache send: delta_time='%uD'", end - start); #endif next: return next_play(s, v); }
static void ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log) { ngx_linux_sendfile_ctx_t *ctx = data; off_t offset; ssize_t n; ngx_buf_t *file; ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "linux sendfile thread handler"); file = ctx->file; offset = file->file_pos; again: n = sendfile(ctx->socket, file->file->fd, &offset, ctx->size); if (n == -1) { ctx->err = ngx_errno; } else { ctx->sent = n; ctx->err = 0; } #if 0 ngx_time_update(); #endif ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, "sendfile: %z (err: %i) of %uz @%O", n, ctx->err, ctx->size, file->file_pos); if (ctx->err == NGX_EINTR) { goto again; } }
static ngx_int_t ngx_rtmp_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) { ngx_rtmp_live_app_conf_t *lacf; ngx_rtmp_live_ctx_t *ctx; lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); if (lacf == NULL || !lacf->live) { goto next; } ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "live: play: name='%s' start=%uD duration=%uD reset=%d", v->name, (uint32_t) v->start, (uint32_t) v->duration, (uint32_t) v->reset); /* join stream as subscriber */ ngx_rtmp_live_join(s, v->name, 0); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); if (ctx == NULL) { goto next; } ctx->silent = v->silent; if (!ctx->silent && !lacf->play_restart) { ngx_rtmp_send_status(s, "NetStream.Play.Start", "status", "Start live"); ngx_rtmp_send_sample_access(s); } next: return next_play(s, v); }
ngx_chain_t * ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { int rc; off_t send, prev_send, sent; off_t file_size; ssize_t n; ngx_uint_t eintr; ngx_err_t err; ngx_buf_t *file; ngx_event_t *wev; ngx_chain_t *cl; ngx_iovec_t header, trailer; struct sf_hdtr hdtr; struct iovec headers[NGX_IOVS_PREALLOCATE]; struct iovec trailers[NGX_IOVS_PREALLOCATE]; wev = c->write; if (!wev->ready) { return in; } #if (NGX_HAVE_KQUEUE) if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { (void) ngx_connection_error(c, wev->kq_errno, "kevent() reported about an closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } #endif /* the maximum limit size is the maximum size_t value - the page size */ if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; } send = 0; header.iovs = headers; header.nalloc = NGX_IOVS_PREALLOCATE; trailer.iovs = trailers; trailer.nalloc = NGX_IOVS_PREALLOCATE; for ( ;; ) { eintr = 0; prev_send = send; /* create the header iovec and coalesce the neighbouring bufs */ cl = ngx_output_chain_to_iovec(&header, in, limit - send, c->log); if (cl == NGX_CHAIN_ERROR) { return NGX_CHAIN_ERROR; } send += header.size; if (cl && cl->buf->in_file && send < limit) { file = cl->buf; /* coalesce the neighbouring file bufs */ file_size = ngx_chain_coalesce_file(&cl, limit - send); send += file_size; if (header.count == 0) { /* * create the trailer iovec and coalesce the neighbouring bufs */ cl = ngx_output_chain_to_iovec(&trailer, cl, limit - send, c->log); if (cl == NGX_CHAIN_ERROR) { return NGX_CHAIN_ERROR; } send += trailer.size; } else { trailer.count = 0; } /* * sendfile() returns EINVAL if sf_hdtr's count is 0, * but corresponding pointer is not NULL */ hdtr.headers = header.count ? header.iovs : NULL; hdtr.hdr_cnt = header.count; hdtr.trailers = trailer.count ? trailer.iovs : NULL; hdtr.trl_cnt = trailer.count; sent = header.size + file_size; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: @%O %O h:%uz", file->file_pos, sent, header.size); /* 这里开始真正的发送文件, * 当输入localhost的时候默认的是index.html * 那么此时这里的file->file->name就是xxxx/html/index.html , * 发送过去之后,客户端页面就可以正常显示了。 */ rc = sendfile(file->file->fd, c->fd, file->file_pos, &sent, &hdtr, 0); if (rc == -1) { err = ngx_errno; switch (err) { case NGX_EAGAIN: break; case NGX_EINTR: eintr = 1; break; default: wev->error = 1; (void) ngx_connection_error(c, err, "sendfile() failed"); return NGX_CHAIN_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, "sendfile() sent only %O bytes", sent); } if (rc == 0 && sent == 0) { /* * if rc and sent equal to zero, then someone * has truncated the file, so the offset became beyond * the end of the file */ ngx_log_error(NGX_LOG_ALERT, c->log, 0, "sendfile() reported that \"%s\" was truncated", file->file->name.data); return NGX_CHAIN_ERROR; } ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %d, @%O %O:%O", rc, file->file_pos, sent, file_size + header.size); } else { n = ngx_writev(c, &header); if (n == NGX_ERROR) { return NGX_CHAIN_ERROR; } sent = (n == NGX_AGAIN) ? 0 : n; } c->sent += sent; in = ngx_chain_update_sent(in, sent); if (eintr) { send = prev_send + sent; continue; } if (send - prev_send != sent) { wev->ready = 0; return in; } if (send >= limit || in == NULL) { return in; } } }
static ngx_int_t ngx_rtmp_cmd_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) { ngx_rtmp_header_t h; static double trans; static ngx_rtmp_amf_elt_t out_inf[] = { { NGX_RTMP_AMF_STRING, ngx_string("code"), "NetStream.Publish.Start", 0 }, { NGX_RTMP_AMF_STRING, ngx_string("level"), "status", 0 }, { NGX_RTMP_AMF_STRING, ngx_string("description"), "Publish succeeded.", 0 }, }; static ngx_rtmp_amf_elt_t out_elts[] = { { NGX_RTMP_AMF_STRING, ngx_null_string, "onStatus", 0 }, { NGX_RTMP_AMF_NUMBER, ngx_null_string, &trans, 0 }, { NGX_RTMP_AMF_NULL, ngx_null_string, NULL, 0 }, { NGX_RTMP_AMF_OBJECT, ngx_null_string, out_inf, sizeof(out_inf) }, }; ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "publish: name='%s' args='%s' type=%s silent=%d", v->name, v->args, v->type, v->silent); if (v->silent) { return NGX_OK; } /* send onStatus reply */ memset(&h, 0, sizeof(h)); h.type = NGX_RTMP_MSG_AMF_CMD; h.csid = NGX_RTMP_CMD_CSID_AMF; h.msid = NGX_RTMP_CMD_MSID; if (ngx_rtmp_send_amf(s, &h, out_elts, sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK) { return NGX_ERROR; } return NGX_OK; }
ngx_int_t ngx_zeromq_connect(ngx_peer_connection_t *pc) { ngx_connection_t *c; ngx_event_t *rev, *wev; void *zmq; int fd, zero; size_t fdsize; zmq = zmq_socket(zmq_context, ZMQ_REQ); if (zmq == NULL) { ngx_zeromq_log_error(pc->log, "zmq_socket(ZMQ_REQ)"); return NGX_ERROR; } fdsize = sizeof(int); if (zmq_getsockopt(zmq, ZMQ_FD, &fd, &fdsize) == -1) { ngx_zeromq_log_error(pc->log, "zmq_getsockopt(ZMQ_FD)"); goto failed_zmq; } zero = 0; if (zmq_setsockopt(zmq, ZMQ_LINGER, &zero, sizeof(int)) == -1) { ngx_zeromq_log_error(pc->log, "zmq_setsockopt(ZMQ_LINGER)"); goto failed_zmq; } c = ngx_get_connection(fd, pc->log); if (c == NULL) { goto failed_zmq; } c->data = zmq; c->recv = ngx_zeromq_recv; c->send = ngx_zeromq_send; c->recv_chain = ngx_zeromq_recv_chain; c->send_chain = ngx_zeromq_send_chain; /* This won't fly with ZeroMQ */ c->sendfile = 0; c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED; c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED; c->log_error = pc->log_error; rev = c->read; wev = c->write; rev->log = pc->log; wev->log = pc->log; pc->connection = c; c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); if (pc->local) { ngx_log_error(NGX_LOG_WARN, pc->log, 0, "zmq_connect: binding to local address is not supported"); } if (zmq_connect(zmq, (const char *) pc->data) == -1) { ngx_zeromq_log_error(pc->log, "zmq_connect()"); goto failed; } ngx_log_debug4(NGX_LOG_DEBUG_EVENT, pc->log, 0, "zmq_connect: lazily connected to tcp://%V," " zmq:%p fd:%d #%d", pc->name, zmq, fd, c->number); if (ngx_add_conn) { /* rtsig */ if (ngx_add_conn(c) == NGX_ERROR) { goto failed; } } else { if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { /* kqueue, epoll */ if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { goto failed; } } else { /* select, poll, /dev/poll */ if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) != NGX_OK) { goto failed; } } } /* * ZeroMQ assumes that new socket is read-ready (but it really isn't) * and it won't notify us about any new events if we don't fail to read * from it first. Sigh. */ rev->ready = 1; wev->ready = 1; return NGX_OK; failed: ngx_free_connection(c); c->fd = (ngx_socket_t) -1; failed_zmq: if (zmq_close(zmq) == -1) { ngx_zeromq_log_error(pc->log, "zmq_close()"); } return NGX_ERROR; }
ngx_int_t ngx_lcb_process(ngx_http_request_t *r) { lcb_error_t err = LCB_NOT_SUPPORTED; ngx_http_variable_value_t *vv; ngx_str_t key, val; enum ngx_lcb_cmd opcode; ngx_http_core_loc_conf_t *clcf; ngx_lcb_connection_t *conn; lcb_cas_t cas = 0; lcb_uint32_t flags = 0, exptime = 0; ngx_int_t need_free_value = 0; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); conn = ngx_http_get_couchbase_connection(clcf->name); if (conn == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couchbase: connection not found: \"%V\"", &clcf->name); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* setup command: use variable or fallback to HTTP method */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_cmd_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (vv->not_found || vv->len == 0) { if (r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)) { opcode = ngx_lcb_cmd_get; } else if (r->method == NGX_HTTP_POST) { opcode = ngx_lcb_cmd_add; } else if (r->method == NGX_HTTP_PUT) { opcode = ngx_lcb_cmd_set; } else if (r->method == NGX_HTTP_DELETE) { opcode = ngx_lcb_cmd_delete; } else { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "ngx_memc: $memc_cmd variable requires explicit " "assignment for HTTP request method %V", &r->method_name); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_HTTP_BAD_REQUEST; } } else { if (ngx_strncmp(vv->data, "get", 3) == 0) { opcode = ngx_lcb_cmd_get; } else if (ngx_strncmp(vv->data, "add", 3) == 0) { opcode = ngx_lcb_cmd_add; } else if (ngx_strncmp(vv->data, "replace", 7) == 0) { opcode = ngx_lcb_cmd_replace; } else if (ngx_strncmp(vv->data, "set", 3) == 0) { opcode = ngx_lcb_cmd_set; } else if (ngx_strncmp(vv->data, "append", 6) == 0) { opcode = ngx_lcb_cmd_append; } else if (ngx_strncmp(vv->data, "prepend", 7) == 0) { opcode = ngx_lcb_cmd_prepend; } else if (ngx_strncmp(vv->data, "delete", 6) == 0) { opcode = ngx_lcb_cmd_delete; } else { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "ngx_memc: unknown $couchbase_cmd \"%v\"", vv); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_HTTP_BAD_REQUEST; } } /* setup key: use variable or fallback to URI */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_key_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (vv->not_found || vv->len == 0) { size_t loc_len; loc_len = r->valid_location ? clcf->name.len : 0; key.data = r->uri.data + loc_len; key.len = r->uri.len - loc_len; } else { u_char *dst, *src; key.data = ngx_palloc(r->pool, vv->len); if (key.data == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } dst = key.data; src = vv->data; ngx_unescape_uri(&dst, &src, vv->len, 0); *dst = 0; key.len = dst - key.data; } /* setup value: use variable or fallback to HTTP body */ ngx_str_null(&val); if (opcode >= ngx_lcb_cmd_add && opcode <= ngx_lcb_cmd_prepend) { vv = ngx_http_get_indexed_variable(r, ngx_lcb_val_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (vv->not_found || vv->len == 0) { if (r->request_body == NULL || r->request_body->bufs == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "neither the \"$couchbase_value\" variable " "nor the request body is available"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_HTTP_BAD_REQUEST; } else { /* copy body to the buffer */ ngx_chain_t *cl; u_char *p; val.len = 0; for (cl = r->request_body->bufs; cl; cl = cl->next) { val.len += ngx_buf_size(cl->buf); } p = val.data = ngx_palloc(r->pool, val.len); if (p == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } for (cl = r->request_body->bufs; cl; cl = cl->next) { p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos); } vv = NULL; } } else { u_char *dst, *src; val.data = ngx_palloc(r->pool, vv->len); if (val.data == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } need_free_value = 1; dst = val.data; src = vv->data; ngx_unescape_uri(&dst, &src, vv->len, 0); *dst = 0; val.len = dst - val.data; } } /* setup CAS value */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_cas_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (!vv->not_found && vv->len > 0) { if (ngx_lcb_atocas(vv->data, vv->len, &cas) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_HTTP_BAD_REQUEST; } } /* setup flags value */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_flags_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (!vv->not_found && vv->len > 0) { flags = ngx_atoi(vv->data, vv->len); } /* setup expiration value */ vv = ngx_http_get_indexed_variable(r, ngx_lcb_exptime_idx); if (vv == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (!vv->not_found && vv->len > 0) { exptime = ngx_atoi(vv->data, vv->len); } switch (opcode) { case ngx_lcb_cmd_get: { lcb_get_cmd_t cmd; const lcb_get_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = key.data; cmd.v.v0.nkey = key.len; cmd.v.v0.exptime = exptime; err = lcb_get(conn->lcb, r, 1, commands); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "couchbase(%p): get request \"%*s\"", (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key); } break; case ngx_lcb_cmd_add: case ngx_lcb_cmd_replace: case ngx_lcb_cmd_set: case ngx_lcb_cmd_append: case ngx_lcb_cmd_prepend: { lcb_store_cmd_t cmd; const lcb_store_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.operation = opcode; cmd.v.v0.key = key.data; cmd.v.v0.nkey = key.len; cmd.v.v0.bytes = val.data; cmd.v.v0.nbytes = val.len; cmd.v.v0.cas = cas; cmd.v.v0.flags = flags; cmd.v.v0.exptime = exptime; err = lcb_store(conn->lcb, r, 1, commands); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "couchbase(%p): store request \"%*s\", operation: 0x%02xd", (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key, cmd.v.v0.operation); } break; case ngx_lcb_cmd_delete: { lcb_remove_cmd_t cmd; const lcb_remove_cmd_t *commands[1]; commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = key.data; cmd.v.v0.nkey = key.len; err = lcb_remove(conn->lcb, r, 1, commands); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "couchbase(%p): remove request \"%*s\"", (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key); } break; } if (need_free_value) { ngx_pfree(r->pool, val.data); } if (err != LCB_SUCCESS) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couchbase: failed to schedule couchbase request: %s", lcb_strerror(conn->lcb, err)); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } return NGX_OK; }
ngx_chain_t * ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { int rc, tcp_nodelay; off_t size, send, prev_send, aligned, sent, fprev; u_char *prev; size_t file_size; ngx_err_t err; ngx_buf_t *file; ngx_uint_t eintr, complete; ngx_array_t header; ngx_event_t *wev; ngx_chain_t *cl; struct iovec *iov, headers[NGX_HEADERS]; #if (NGX_HAVE_SENDFILE64) off_t offset; #else int32_t offset; #endif wev = c->write; if (!wev->ready) { return in; } /* the maximum limit size is 2G-1 - the page size */ if (limit == 0 || limit > (off_t) (NGX_SENDFILE_LIMIT - ngx_pagesize)) { limit = NGX_SENDFILE_LIMIT - ngx_pagesize; } send = 0; header.elts = headers; header.size = sizeof(struct iovec); header.nalloc = NGX_HEADERS; header.pool = c->pool; for ( ;; ) { file = NULL; file_size = 0; eintr = 0; complete = 0; prev_send = send; header.nelts = 0; prev = NULL; iov = NULL; /* create the iovec and coalesce the neighbouring bufs */ for (cl = in; cl && header.nelts < IOV_MAX && send < limit; cl = cl->next) { if (ngx_buf_special(cl->buf)) { continue; } #if 1 if (!ngx_buf_in_memory(cl->buf) && !cl->buf->in_file) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in sendfile " "t:%d r:%d f:%d %p %p-%p %p %O-%O", cl->buf->temporary, cl->buf->recycled, cl->buf->in_file, cl->buf->start, cl->buf->pos, cl->buf->last, cl->buf->file, cl->buf->file_pos, cl->buf->file_last); ngx_debug_point(); return NGX_CHAIN_ERROR; } #endif if (!ngx_buf_in_memory_only(cl->buf)) { break; } size = cl->buf->last - cl->buf->pos; if (send + size > limit) { size = limit - send; } if (prev == cl->buf->pos) { iov->iov_len += (size_t) size; } else { iov = ngx_array_push(&header); if (iov == NULL) { return NGX_CHAIN_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = (size_t) size; } prev = cl->buf->pos + (size_t) size; send += size; } /* set TCP_CORK if there is a header before a file */ if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET && header.nelts != 0 && cl && cl->buf->in_file) { /* the TCP_CORK and TCP_NODELAY are mutually exclusive */ if (c->tcp_nodelay == NGX_TCP_NODELAY_SET) { tcp_nodelay = 0; if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, (const void *) &tcp_nodelay, sizeof(int)) == -1) { err = ngx_errno; /* * there is a tiny chance to be interrupted, however, * we continue a processing with the TCP_NODELAY * and without the TCP_CORK */ if (err != NGX_EINTR) { wev->error = 1; ngx_connection_error(c, err, "setsockopt(TCP_NODELAY) failed"); return NGX_CHAIN_ERROR; } } else { c->tcp_nodelay = NGX_TCP_NODELAY_UNSET; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "no tcp_nodelay"); } } if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { err = ngx_errno; /* * there is a tiny chance to be interrupted, however, * we continue a processing without the TCP_CORK */ if (err != NGX_EINTR) { wev->error = 1; ngx_connection_error(c, err, ngx_tcp_nopush_n " failed"); return NGX_CHAIN_ERROR; } } else { c->tcp_nopush = NGX_TCP_NOPUSH_SET; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "tcp_nopush"); } } } /* get the file buf */ if (header.nelts == 0 && cl && cl->buf->in_file && send < limit) { file = cl->buf; /* coalesce the neighbouring file bufs */ do { size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) & ~((off_t) ngx_pagesize - 1); if (aligned <= cl->buf->file_last) { size = aligned - cl->buf->file_pos; } } file_size += (size_t) size; send += size; fprev = cl->buf->file_pos + size; cl = cl->next; } while (cl && cl->buf->in_file && send < limit && file->file->fd == cl->buf->file->fd && fprev == cl->buf->file_pos); } if (file) { #if 1 if (file_size == 0) { ngx_debug_point(); return NGX_CHAIN_ERROR; } #endif #if (NGX_HAVE_SENDFILE64) offset = file->file_pos; #else offset = (int32_t) file->file_pos; #endif ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: @%O %uz", file->file_pos, file_size); rc = sendfile(c->fd, file->file->fd, &offset, file_size); if (rc == -1) { err = ngx_errno; switch (err) { case NGX_EAGAIN: break; case NGX_EINTR: eintr = 1; break; default: wev->error = 1; ngx_connection_error(c, err, "sendfile() failed"); return NGX_CHAIN_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "sendfile() is not ready"); } sent = rc > 0 ? rc : 0; ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %d, @%O %O:%uz", rc, file->file_pos, sent, file_size); } else { rc = writev(c->fd, header.elts, header.nelts); if (rc == -1) { err = ngx_errno; switch (err) { case NGX_EAGAIN: break; case NGX_EINTR: eintr = 1; break; default: wev->error = 1; ngx_connection_error(c, err, "writev() failed"); return NGX_CHAIN_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "writev() not ready"); } sent = rc > 0 ? rc : 0; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent); } if (send - prev_send == sent) { complete = 1; } c->sent += sent; for (cl = in; cl; cl = cl->next) { if (ngx_buf_special(cl->buf)) { continue; } if (sent == 0) { break; } size = ngx_buf_size(cl->buf); if (sent >= size) { sent -= size; if (ngx_buf_in_memory(cl->buf)) { cl->buf->pos = cl->buf->last; } if (cl->buf->in_file) { cl->buf->file_pos = cl->buf->file_last; } continue; } if (ngx_buf_in_memory(cl->buf)) { cl->buf->pos += (size_t) sent; } if (cl->buf->in_file) { cl->buf->file_pos += sent; } break; } if (eintr) { continue; } if (!complete) { wev->ready = 0; return cl; } if (send >= limit || cl == NULL) { return cl; } in = cl; } }
static ngx_int_t ngx_http_subs_body_filter_process_buffer(ngx_http_request_t *r, ngx_buf_t *b) { u_char *p, *last, *linefeed; ngx_int_t len, rc; ngx_http_subs_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_subs_filter_module); if (b == NULL) { return NGX_DECLINED; } p = b->pos; last = b->last; b->pos = b->last; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "subs process in buffer: %p %uz, line_in buffer: %p %uz", b, last - p, ctx->line_in, ngx_buf_size(ctx->line_in)); if ((last - p) == 0 && ngx_buf_size(ctx->line_in) == 0){ return NGX_OK; } if ((last - p) == 0 && ngx_buf_size(ctx->line_in) && ctx->last) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "the last zero buffer, try to do substitution"); rc = ngx_http_subs_match(r, ctx); if (rc < 0) { return NGX_ERROR; } return NGX_OK; } while (p < last) { linefeed = memchr(p, LF, last - p); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "find linefeed: %p", linefeed); if (linefeed == NULL) { if (ctx->last) { linefeed = last - 1; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "the last buffer, not find linefeed"); } } if (linefeed) { len = linefeed - p + 1; if (buffer_append_string(ctx->line_in, p, len, r->pool) == NULL) { return NGX_ERROR; } p += len; rc = ngx_http_subs_match(r, ctx); if (rc < 0) { return NGX_ERROR; } } else { /* Not find linefeed in this chain, save the left data to line_in */ if (buffer_append_string(ctx->line_in, p, last - p, r->pool) == NULL) { return NGX_ERROR; } break; } } return NGX_OK; }
static ngx_int_t ngx_lua_http_btt_parse_args(ngx_http_request_t *r, ngx_btt_ctx_t *ctx) { size_t nlen, vlen; u_char *p, *last, *name, *val, *dst, *src; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua http btt parse args"); if (r->args.len == 0) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "invalid uri \"%V\"", &r->args); return NGX_ERROR; } p = r->args.data; last = p + r->args.len; for ( /* void */ ; p < last; p++) { name = p; p = ngx_strlchr(p, last, '&'); if (p == NULL) { p = last; } val = ngx_strlchr(name, p, '='); if (val == NULL) { val = p; } nlen = val - name; vlen = (++val < p) ? p - val : 0; dst = ngx_pnalloc(r->pool, vlen); if (dst == NULL) { return NGX_ERROR; } src = val; val = dst; ngx_unescape_uri(&dst, &src, vlen, 0); vlen = dst - val; ngx_log_debug4(NGX_LOG_ALERT, r->connection->log, 0, "%*s=%*s", nlen, name, vlen, val); /* * BT Client: * * BitComet: localip, natmapped, port_type * NetTransport: supportcrypto * uTorrent: corrupt * XunLei: ip */ switch (nlen) { case 2: if (ngx_strncmp(name, "ip", nlen) == 0) { ctx->internal_ip = ngx_inet_addr(val, vlen); if (ctx->internal_ip == INADDR_NONE) { goto invalid; } break; } break; case 3: if (ngx_strncmp(name, "key", nlen) == 0) { ngx_memcpy(ctx->key, val, vlen); break; } break; case 4: if (ngx_strncmp(name, "port", nlen) == 0) { ctx->internal_port = (in_port_t) ngx_atoi(val, vlen); if (ctx->internal_port == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "left", nlen) == 0) { ctx->left = ngx_atoof(val, vlen); if (ctx->left == NGX_ERROR) { goto invalid; } break; } break; case 5: if (ngx_strncmp(name, "event", nlen) == 0) { if (ngx_strncmp(val, "none", sizeof("none") - 1) == 0) { ctx->event = NGX_BTT_EVENT_NONE; } else if (ngx_strncmp(val, "completed", sizeof("completed") - 1) == 0) { ctx->event = NGX_BTT_EVENT_COMPLETED; } else if (ngx_strncmp(val, "started", sizeof("started") - 1) == 0) { ctx->event = NGX_BTT_EVENT_STARTED; } else if (ngx_strncmp(val, "stopped", sizeof("stopped") - 1) == 0) { ctx->event = NGX_BTT_EVENT_STOPPED; } else { goto invalid; } break; } break; case 7: if (ngx_strncmp(name, "peer_id", nlen) == 0) { ngx_memcpy(ctx->peer_id, val, vlen); break; } if (ngx_strncmp(name, "localip", nlen) == 0) { ctx->internal_ip = ngx_inet_addr(val, vlen); if (ctx->internal_ip == INADDR_NONE) { goto invalid; } break; } if (ngx_strncmp(name, "numwant", nlen) == 0) { ctx->numwant = ngx_atoi(val, vlen); if (ctx->numwant == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "compact", nlen) == 0) { ctx->compact = ngx_atoi(val, vlen); if (ctx->compact == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "corrupt", nlen) == 0) { ctx->corrupt = ngx_atoi(val, vlen); if (ctx->corrupt == NGX_ERROR) { goto invalid; } break; } break; case 8: if (ngx_strncmp(name, "uploaded", nlen) == 0) { ctx->uploaded = ngx_atoof(val, vlen); if (ctx->uploaded == NGX_ERROR) { goto invalid; } break; } break; case 9: if (ngx_strncmp(name, "info_hash ", nlen) == 0) { ngx_memcpy(ctx->info_hash, val, vlen); break; } if (ngx_strncmp(name, "natmapped ", nlen) == 0) { ctx->natmapped = ngx_atoi(val, vlen); if (ctx->natmapped == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "port_type", nlen) == 0) { ngx_memcpy(ctx->port_type, val, vlen); break; } break; case 10: if (ngx_strncmp(name, "downloaded", nlen) == 0) { ctx->downloaded = ngx_atoof(val, vlen); if (ctx->downloaded == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "no_peer_id ", nlen) == 0) { ctx->no_peer_id = ngx_atoi(val, vlen); if (ctx->no_peer_id == NGX_ERROR) { goto invalid; } break; } break; case 13: if (ngx_strncmp(name, "supportcrypto", nlen) == 0) { ctx->supportcrypto = ngx_atoi(val, vlen); if (ctx->supportcrypto == NGX_ERROR) { goto invalid; } break; } break; default: break; } } return NGX_OK; invalid: ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "invalid value \"%*s\" of the key \"%*s\"", nlen, name, vlen, val); return NGX_ERROR; }
ngx_chain_t * ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { int rc, flags; u_char *prev; off_t size, send, prev_send, aligned, sent, fprev; size_t header_size, file_size; ngx_uint_t eintr, eagain, complete; ngx_err_t err; ngx_buf_t *file; ngx_array_t header, trailer; ngx_event_t *wev; ngx_chain_t *cl; struct sf_hdtr hdtr; struct iovec *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS]; wev = c->write; if (!wev->ready) { return in; } #if (NGX_HAVE_KQUEUE) if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { (void) ngx_connection_error(c, wev->kq_errno, "kevent() reported about an closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } #endif /* the maximum limit size is the maximum size_t value - the page size */ if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; } send = 0; eagain = 0; flags = 0; header.elts = headers; header.size = sizeof(struct iovec); header.nalloc = NGX_HEADERS; header.pool = c->pool; trailer.elts = trailers; trailer.size = sizeof(struct iovec); trailer.nalloc = NGX_TRAILERS; trailer.pool = c->pool; for ( ;; ) { file = NULL; file_size = 0; header_size = 0; eintr = 0; complete = 0; prev_send = send; header.nelts = 0; trailer.nelts = 0; /* create the header iovec and coalesce the neighbouring bufs */ prev = NULL; iov = NULL; for (cl = in; cl && send < limit; cl = cl->next) { if (ngx_buf_special(cl->buf)) { continue; } if (!ngx_buf_in_memory_only(cl->buf)) { break; } size = cl->buf->last - cl->buf->pos; if (send + size > limit) { size = limit - send; } if (prev == cl->buf->pos) { iov->iov_len += (size_t) size; } else { if (header.nelts >= IOV_MAX){ break; } iov = ngx_array_push(&header); if (iov == NULL) { return NGX_CHAIN_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = (size_t) size; } prev = cl->buf->pos + (size_t) size; header_size += (size_t) size; send += size; } if (cl && cl->buf->in_file && send < limit) { file = cl->buf; /* coalesce the neighbouring file bufs */ do { size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) & ~((off_t) ngx_pagesize - 1); if (aligned <= cl->buf->file_last) { size = aligned - cl->buf->file_pos; } } file_size += (size_t) size; send += size; fprev = cl->buf->file_pos + size; cl = cl->next; } while (cl && cl->buf->in_file && send < limit && file->file->fd == cl->buf->file->fd && fprev == cl->buf->file_pos); } if (file) { /* create the trailer iovec and coalesce the neighbouring bufs */ prev = NULL; iov = NULL; while (cl && send < limit) { if (ngx_buf_special(cl->buf)) { cl = cl->next; continue; } if (!ngx_buf_in_memory_only(cl->buf)) { break; } size = cl->buf->last - cl->buf->pos; if (send + size > limit) { size = limit - send; } if (prev == cl->buf->pos) { iov->iov_len += (size_t) size; } else { if (trailer.nelts >= IOV_MAX){ break; } iov = ngx_array_push(&trailer); if (iov == NULL) { return NGX_CHAIN_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = (size_t) size; } prev = cl->buf->pos + (size_t) size; send += size; cl = cl->next; } } if (file) { if (ngx_freebsd_use_tcp_nopush && c->tcp_nopush == NGX_TCP_NOPUSH_UNSET) { if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { err = ngx_socket_errno; /* * there is a tiny chance to be interrupted, however, * we continue a processing without the TCP_NOPUSH */ if (err != NGX_EINTR) { wev->error = 1; (void) ngx_connection_error(c, err, ngx_tcp_nopush_n " failed"); return NGX_CHAIN_ERROR; } } else { c->tcp_nopush = NGX_TCP_NOPUSH_SET; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "tcp_nopush"); } } /* * sendfile() does unneeded work if sf_hdtr's count is 0, * but corresponding pointer is not NULL */ hdtr.headers = header.nelts ? (struct iovec *) header.elts: NULL; hdtr.hdr_cnt = header.nelts; hdtr.trailers = trailer.nelts ? (struct iovec *) trailer.elts: NULL; hdtr.trl_cnt = trailer.nelts; /* * the "nbytes bug" of the old sendfile() syscall: * http://bugs.freebsd.org/33771 */ if (!ngx_freebsd_sendfile_nbytes_bug) { header_size = 0; } sent = 0; #if (NGX_HAVE_AIO_SENDFILE) flags = c->aio_sendfile ? SF_NODISKIO : 0; #endif rc = sendfile(file->file->fd, c->fd, file->file_pos, file_size + header_size, &hdtr, &sent, flags); if (rc == -1) { err = ngx_errno; switch (err) { case NGX_EAGAIN: eagain = 1; break; case NGX_EINTR: eintr = 1; break; #if (NGX_HAVE_AIO_SENDFILE) case NGX_EBUSY: c->busy_sendfile = file; break; #endif default: wev->error = 1; (void) ngx_connection_error(c, err, "sendfile() failed"); return NGX_CHAIN_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, "sendfile() sent only %O bytes", sent); /* * sendfile() in FreeBSD 3.x-4.x may return value >= 0 * on success, although only 0 is documented */ } else if (rc >= 0 && sent == 0) { /* * if rc is OK and sent equal to zero, then someone * has truncated the file, so the offset became beyond * the end of the file */ ngx_log_error(NGX_LOG_ALERT, c->log, 0, "sendfile() reported that \"%s\" was truncated at %O", file->file->name.data, file->file_pos); return NGX_CHAIN_ERROR; } ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %d, @%O %O:%uz", rc, file->file_pos, sent, file_size + header_size); } else { rc = writev(c->fd, header.elts, header.nelts); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d of %uz", rc, header_size); if (rc == -1) { err = ngx_errno; switch (err) { case NGX_EAGAIN: break; case NGX_EINTR: eintr = 1; break; default: wev->error = 1; ngx_connection_error(c, err, "writev() failed"); return NGX_CHAIN_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "writev() not ready"); } sent = rc > 0 ? rc : 0; } if (send - prev_send == sent) { complete = 1; } c->sent += sent; for ( /* void */ ; in; in = in->next) { if (ngx_buf_special(in->buf)) { continue; } if (sent == 0) { break; } size = ngx_buf_size(in->buf); if (sent >= size) { sent -= size; if (ngx_buf_in_memory(in->buf)) { in->buf->pos = in->buf->last; } if (in->buf->in_file) { in->buf->file_pos = in->buf->file_last; } continue; } if (ngx_buf_in_memory(in->buf)) { in->buf->pos += (size_t) sent; } if (in->buf->in_file) { in->buf->file_pos += sent; } break; } #if (NGX_HAVE_AIO_SENDFILE) if (c->busy_sendfile) { return in; } #endif if (eagain) { /* * sendfile() may return EAGAIN, even if it has sent a whole file * part, it indicates that the successive sendfile() call would * return EAGAIN right away and would not send anything. * We use it as a hint. */ wev->ready = 0; return in; } if (eintr) { continue; } if (!complete) { wev->ready = 0; return in; } if (send >= limit || in == NULL) { return in; } } }
static ngx_int_t ngx_http_redis_filter(void *data, ssize_t bytes) { ngx_http_redis_ctx_t *ctx = data; u_char *last; ngx_buf_t *b; ngx_chain_t *cl, **ll; ngx_http_upstream_t *u; u = ctx->request->upstream; b = &u->buffer; if (u->length == ctx->rest) { if (ngx_strncmp(b->last, ngx_http_redis_end + NGX_HTTP_REDIS_END - ctx->rest, ctx->rest) != 0) { ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, "redis sent invalid trailer"); } u->length = 0; ctx->rest = 0; return NGX_OK; } for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) { ll = &cl->next; } cl = ngx_chain_get_free_buf(ctx->request->pool, &u->free_bufs); if (cl == NULL) { return NGX_ERROR; } cl->buf->flush = 1; cl->buf->memory = 1; *ll = cl; last = b->last; cl->buf->pos = last; b->last += bytes; cl->buf->last = b->last; cl->buf->tag = u->output.tag; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0, "redis filter bytes:%z size:%z length:%z rest:%z", bytes, b->last - b->pos, u->length, ctx->rest); if (bytes <= (ssize_t) (u->length - NGX_HTTP_REDIS_END)) { u->length -= bytes; return NGX_OK; } last += u->length - NGX_HTTP_REDIS_END; if (ngx_strncmp(last, ngx_http_redis_end, b->last - last) != 0) { ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, "redis sent invalid trailer"); } ctx->rest -= b->last - last; b->last = last; cl->buf->last = last; u->length = ctx->rest; return NGX_OK; }