static apr_status_t nginx_bucket_read(apr_bucket *b, const char **str,
                                      apr_size_t *len, apr_read_type_e block)
{
    apr_bucket_nginx *n = b->data;
    ngx_buf_t        *buf = n->buf;
    u_char           *data;
    ssize_t           size;

    if (buf->pos == NULL && ngx_buf_size(buf) != 0) {
        data = apr_bucket_alloc(ngx_buf_size(buf), b->list);
        if (data == NULL) {
            return APR_EGENERAL;
        }

        size = ngx_read_file(buf->file, data, ngx_buf_size(buf),
                buf->file_pos);

        if (size != ngx_buf_size(buf)) {
            apr_bucket_free(data);
            return APR_EGENERAL;
        }
        buf->pos = data;
    }

    *str = (char *)buf->pos + b->start;
    *len = b->length;

    return APR_SUCCESS;
}
Beispiel #2
0
/*信号处理函数,向进程发送信号*/
ngx_int_t
ngx_signal_process(ngx_cycle_t *cycle, char *sig)
{
    ssize_t           n;
    ngx_pid_t         pid;
    ngx_file_t        file;
    ngx_core_conf_t  *ccf;
    u_char            buf[NGX_INT64_LEN + 2];

    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started");

    /*获取核心模块存储配置项结构体指针*/
    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    ngx_memzero(&file, sizeof(ngx_file_t));

    file.name = ccf->pid;  //ccf->pid为nginx.pid文件
    file.log = cycle->log;

    /*以可读方式打开nginx.pid文件*/
    file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
                            NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS);

    if (file.fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
                      ngx_open_file_n " \"%s\" failed", file.name.data);
        return 1;
    }

    /*读文件*/
    n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0);

    if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", file.name.data);
    }

    if (n == NGX_ERROR) {
        return 1;
    }

    /*去掉结尾的控制字符*/
    while (n-- && (buf[n] == CR || buf[n] == LF)) { /* void */ }

    /*将字符串转换为数字,获取master进程pid*/
    pid = ngx_atoi(buf, ++n);

    if (pid == (ngx_pid_t) NGX_ERROR) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
                      "invalid PID number \"%*s\" in \"%s\"",
                      n, buf, file.name.data);
        return 1;
    }

    /*封装kill系统调用的信号发送函数*/
    return ngx_os_signal_process(cycle, sig, pid);

}
Beispiel #3
0
ngx_int_t
ngx_signal_process(ngx_cycle_t *cycle, char *sig)
{
    ssize_t           n;
    ngx_pid_t         pid;
    ngx_file_t        file;
    ngx_core_conf_t  *ccf;
    u_char            buf[NGX_INT64_LEN + 2];

    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started");

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    ngx_memzero(&file, sizeof(ngx_file_t));

    file.name = ccf->pid;
    file.log = cycle->log;

    file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
                            NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS);

    if (file.fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
                      ngx_open_file_n " \"%s\" failed", file.name.data);
        return 1;
    }

    n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0);

    if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", file.name.data);
    }

    if (n == NGX_ERROR) {
        return 1;
    }

    while (n-- && (buf[n] == CR || buf[n] == LF)) {
        /* void */
    }

    pid = ngx_atoi(buf, ++n);

    if (pid == (ngx_pid_t) NGX_ERROR) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
                      "invalid PID number \"%*s\" in \"%s\"",
                      n, buf, file.name.data);
        return 1;
    }

    return ngx_os_signal_process(cycle, sig, pid);

}
static ngx_int_t
ngx_http_groonga_join_request_body_chain(ngx_http_request_t *r,
                                         ngx_chain_t *chain,
                                         u_char **out_start,
                                         u_char **out_end)
{
  ngx_int_t rc;

  ngx_log_t *log = r->connection->log;

  ngx_chain_t *current;
  u_char *out;
  size_t out_size;

  u_char *out_cursor;
  ngx_buf_t *buffer;
  size_t buffer_size;

  out_size = 0;
  for (current = chain; current; current = current->next) {
    out_size += ngx_buf_size(current->buf);
  }
  out = ngx_palloc(r->pool, out_size);
  if (!out) {
    ngx_log_error(NGX_LOG_ERR, log, 0,
                  "http_groonga: failed to allocate memory for request body");
    return NGX_ERROR;
  }

  out_cursor = out;
  for (current = chain; current; current = current->next) {
    buffer = current->buf;
    buffer_size = ngx_buf_size(current->buf);

    if (buffer->file) {
      rc = ngx_read_file(buffer->file, out_cursor, buffer_size, 0);
      if (rc < 0) {
        ngx_log_error(NGX_LOG_ERR, log, 0,
                      "http_groonga: failed to read a request body stored in a file");
        return rc;
      }
    } else {
      ngx_memcpy(out_cursor, buffer->pos, buffer_size);
    }
    out_cursor += buffer_size;
  }

  *out_start = out;
  *out_end = out + out_size;

  return NGX_OK;
}
static ssize_t
ngx_http_vhost_traffic_status_dump_header_read(ngx_file_t *file,
    ngx_http_vhost_traffic_status_dump_header_t *file_header)
{
    ssize_t  n;

    ngx_memzero(file_header, sizeof(ngx_http_vhost_traffic_status_dump_header_t));

    n = ngx_read_file(file, (u_char *) file_header,
                      sizeof(ngx_http_vhost_traffic_status_dump_header_t), 0);

    return n;
}
Beispiel #6
0
// this function adapted from push stream module. thanks Wandenberg Peixoto <*****@*****.**> and Rogério Carvalho Schneider <*****@*****.**>
static ngx_buf_t * nchan_request_body_to_single_buffer(ngx_http_request_t *r) {
  ngx_buf_t *buf = NULL;
  ngx_chain_t *chain;
  ssize_t n;
  off_t len;

  chain = r->request_body->bufs;
  if (chain->next == NULL) {
    return chain->buf;
  }
  //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "nchan: multiple buffers in request, need memcpy :(");
  if (chain->buf->in_file) {
    if (ngx_buf_in_memory(chain->buf)) {
      ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "nchan: can't handle a buffer in a temp file and in memory ");
    }
    if (chain->next != NULL) {
      ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "nchan: error reading request body with multiple ");
    }
    return chain->buf;
  }
  buf = ngx_create_temp_buf(r->pool, r->headers_in.content_length_n + 1);
  if (buf != NULL) {
    ngx_memset(buf->start, '\0', r->headers_in.content_length_n + 1);
    while ((chain != NULL) && (chain->buf != NULL)) {
      len = ngx_buf_size(chain->buf);
      // if buffer is equal to content length all the content is in this buffer
      if (len >= r->headers_in.content_length_n) {
        buf->start = buf->pos;
        buf->last = buf->pos;
        len = r->headers_in.content_length_n;
      }
      if (chain->buf->in_file) {
        n = ngx_read_file(chain->buf->file, buf->start, len, 0);
        if (n == NGX_FILE_ERROR) {
          ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "nchan: cannot read file with request body");
          return NULL;
        }
        buf->last = buf->last + len;
        ngx_delete_file(chain->buf->file->name.data);
        chain->buf->file->fd = NGX_INVALID_FILE;
      } else {
        buf->last = ngx_copy(buf->start, chain->buf->pos, len);
      }

      chain = chain->next;
      buf->start = buf->last;
    }
    buf->last_buf = 1;
  }
  return buf;
}
ngx_int_t 
ngx_async_file_read(ngx_file_reader_state_t* state, ngx_buf_t *buf, size_t size, off_t offset)
{
	ssize_t rc;

	ngx_log_debug2(NGX_LOG_DEBUG_HTTP, state->log, 0, "ngx_async_file_read: reading offset %O size %uz", offset, size);

	rc = ngx_read_file(&state->file, buf->last, size, offset);
	if (rc < 0)
	{
		ngx_log_error(NGX_LOG_ERR, state->log, 0, "ngx_async_file_read: ngx_read_file failed rc=%z", rc);
		return rc;
	}

	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, state->log, 0, "ngx_async_file_read: ngx_read_file returned %z", rc);
	buf->last += rc;

	return NGX_OK;
}
static ngx_buf_t *
ngx_http_push_stream_read_request_body_to_buffer(ngx_http_request_t *r)
{
    ngx_buf_t                              *buf = NULL;
    ngx_chain_t                            *chain;
    ssize_t                                 n;
    off_t                                   len;

    buf = ngx_create_temp_buf(r->pool, r->headers_in.content_length_n + 1);
    if (buf != NULL) {
        buf->memory = 1;
        buf->temporary = 0;
        ngx_memset(buf->start, '\0', r->headers_in.content_length_n + 1);

        chain = r->request_body->bufs;
        while ((chain != NULL) && (chain->buf != NULL)) {
            len = ngx_buf_size(chain->buf);
            // if buffer is equal to content length all the content is in this buffer
            if (len >= r->headers_in.content_length_n) {
                buf->start = buf->pos;
                buf->last = buf->pos;
                len = r->headers_in.content_length_n;
            }

            if (chain->buf->in_file) {
                n = ngx_read_file(chain->buf->file, buf->start, len, 0);
                if (n == NGX_FILE_ERROR) {
                    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: cannot read file with request body");
                    return NULL;
                }
                buf->last = buf->last + len;
                ngx_delete_file(chain->buf->file->name.data);
                chain->buf->file->fd = NGX_INVALID_FILE;
            } else {
                buf->last = ngx_copy(buf->start, chain->buf->pos, len);
            }

            chain = chain->next;
            buf->start = buf->last;
        }
    }
    return buf;
}
static ngx_int_t
ngx_squ_file_aio_read(ngx_squ_thread_t *thr, ngx_lua_file_ctx_t *ctx)
{
    ssize_t      n;
    ngx_buf_t   *b;
    ngx_file_t  *file;

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, thr->log, 0, "squ file aio read");

    file = &ctx->file;
    b = ctx->in;

#if (NGX_HAVE_FILE_AIO)
    n = ngx_file_aio_read(file, b->start, ctx->size, ctx->offset, ctx->pool);
#else
    n = ngx_read_file(file, b->start, ctx->size, ctx->offset);
#endif

    if (n == NGX_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, thr->log, ngx_errno,
                      "ngx_file_aio_read() \"%V\" failed", &file->name);
        squ_pushboolean(thr->l, 0);
        squ_pushstring(thr->l, "ngx_file_aio_read() failed");
        return 2;
    }

#if (NGX_HAVE_FILE_AIO)
    if (n == NGX_AGAIN) {
        ctx->file.aio->data = ctx;
        ctx->file.aio->handler = ngx_squ_file_aio_read_handler;
        return NGX_AGAIN;
    }
#endif

    ctx->offset += n;

    squ_pushlstring(thr->l, (char *) b->start, n);

    return 1;
}
ngx_int_t 
ngx_async_file_read(ngx_file_reader_state_t* state, ngx_buf_t *buf, size_t size, off_t offset)
{
	ssize_t rc;

	ngx_log_debug2(NGX_LOG_DEBUG_HTTP, state->log, 0, "ngx_async_file_read: reading offset %O size %uz", offset, size);

	if (state->use_aio)
	{
		rc = ngx_file_aio_read(&state->file, buf->last, size, offset, state->r->pool);
		if (rc == NGX_AGAIN)
		{
			// wait for completion
			state->file.aio->data = state;
			state->file.aio->handler = ngx_async_read_completed_callback;

			state->r->main->blocked++;
			state->r->aio = 1;

			state->buf = buf;
			return rc;
		}
	}
	else
	{
		rc = ngx_read_file(&state->file, buf->last, size, offset);
	}

	if (rc < 0)
	{
		ngx_log_error(NGX_LOG_ERR, state->log, 0, "ngx_async_file_read: ngx_file_aio_read failed rc=%z", rc);
		return rc;
	}

	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, state->log, 0, "ngx_async_file_read: ngx_file_aio_read returned %z", rc);
	buf->last += rc;
	
	return NGX_OK;
}
Beispiel #11
0
static ssize_t
ngx_http_file_cache_aio_read(ngx_http_request_t *r, ngx_http_cache_t *c)
{
#if (NGX_HAVE_FILE_AIO)
    ssize_t                    n;
    ngx_http_core_loc_conf_t  *clcf;

    if (!ngx_file_aio) {
        goto noaio;
    }

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (!clcf->aio) {
        goto noaio;
    }

    n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool);

    if (n != NGX_AGAIN) {
        return n;
    }

    c->file.aio->data = r;
    c->file.aio->handler = ngx_http_cache_aio_event_handler;

    r->main->blocked++;
    r->aio = 1;

    return NGX_AGAIN;

noaio:

#endif

    return ngx_read_file(&c->file, c->buf->pos, c->body_start, 0);
}
Beispiel #12
0
/*
 * 读取配置文件的token信息
 */
static ngx_int_t
ngx_conf_read_token(ngx_conf_t *cf)
{
    u_char      *start, ch, *src, *dst;
    off_t        file_size;
    size_t       len;
    ssize_t      n, size;
    ngx_uint_t   found, need_space, last_space, sharp_comment, variable;
    ngx_uint_t   quoted, s_quoted, d_quoted, start_line;
    ngx_str_t   *word;
    ngx_buf_t   *b;

    found = 0;
    need_space = 0;
    last_space = 1;
    sharp_comment = 0;
    variable = 0;
    quoted = 0;
    s_quoted = 0;
    d_quoted = 0;

    cf->args->nelts = 0;                                                        //此处相当于将配置项缓冲区给清空了
    b = cf->conf_file->buffer;
    start = b->pos;
    start_line = cf->conf_file->line;

    file_size = ngx_file_size(&cf->conf_file->file.info);                       //文件大小

    for ( ;; ) {

        if (b->pos >= b->last) {                                                //缓冲区中是否还有数据                                       

            if (cf->conf_file->file.offset >= file_size) {

                if (cf->args->nelts > 0 || !last_space) {

                    if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
                        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                           "unexpected end of parameter, "
                                           "expecting \";\"");
                        return NGX_ERROR;
                    }

                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                  "unexpected end of file, "
                                  "expecting \";\" or \"}\"");
                    return NGX_ERROR;
                }

                return NGX_CONF_FILE_DONE;
            }

            len = b->pos - start;                                           //已读取的大小

            if (len == NGX_CONF_BUFFER) {                                   //缓冲区已满
                cf->conf_file->line = start_line;

                if (d_quoted) {
                    ch = '"';

                } else if (s_quoted) {
                    ch = '\'';

                } else {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "too long parameter \"%*s...\" started",
                                       10, start);
                    return NGX_ERROR;
                }

                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "too long parameter, probably "
                                   "missing terminating \"%c\" character", ch);
                return NGX_ERROR;
            }

            if (len) {
                ngx_memmove(b->start, start, len);
            }

            size = (ssize_t) (file_size - cf->conf_file->file.offset);      //配置文件剩余未读取数据大小

            if (size > b->end - (b->start + len)) {                         //确定缓冲区剩余空间大小
                size = b->end - (b->start + len);
            }

            /*读取配置内容*/
            n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
                              cf->conf_file->file.offset);

            if (n == NGX_ERROR) {
                return NGX_ERROR;
            }

            if (n != size) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   ngx_read_file_n " returned "
                                   "only %z bytes instead of %z",
                                   n, size);
                return NGX_ERROR;
            }

            b->pos = b->start + len;
            b->last = b->pos + n;
            start = b->start;
        }

        ch = *b->pos++;

        if (ch == LF) {                         //换行
            cf->conf_file->line++;

            if (sharp_comment) {
                sharp_comment = 0;
            }
        }

        if (sharp_comment) {                    //注释
            continue;
        }

        if (quoted) {                           //引号
            quoted = 0;
            continue;
        }

        if (need_space) {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
                last_space = 1;
                need_space = 0;
                continue;
            }

            if (ch == ';') {
                return NGX_OK;
            }

            if (ch == '{') {
                return NGX_CONF_BLOCK_START;
            }

            if (ch == ')') {
                last_space = 1;
                need_space = 0;

            } else {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                    "unexpected \"%c\"", ch);
                 return NGX_ERROR;
            }
        }

        if (last_space) {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
                continue;
            }

            start = b->pos - 1;
            start_line = cf->conf_file->line;

            switch (ch) {

            case ';':
            case '{':
                if (cf->args->nelts == 0) {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "unexpected \"%c\"", ch);
                    return NGX_ERROR;
                }

                if (ch == '{') {                                    //块开始
                    return NGX_CONF_BLOCK_START;
                }

                return NGX_OK;

            case '}':                                               //块结束
                if (cf->args->nelts != 0) {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "unexpected \"}\"");
                    return NGX_ERROR;
                }

                return NGX_CONF_BLOCK_DONE;

            case '#':                                               //注释
                sharp_comment = 1;
                continue;

            case '\\':
                quoted = 1;
                last_space = 0;
                continue;

            case '"':
                start++;
                d_quoted = 1;
                last_space = 0;
                continue;

            case '\'':
                start++;
                s_quoted = 1;
                last_space = 0;
                continue;

            default:
                last_space = 0;
            }

        } else {
            if (ch == '{' && variable) {
                continue;
            }

            variable = 0;

            if (ch == '\\') {
                quoted = 1;
                continue;
            }

            if (ch == '$') {
                variable = 1;
                continue;
            }

            if (d_quoted) {
                if (ch == '"') {
                    d_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            } else if (s_quoted) {
                if (ch == '\'') {
                    s_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
                       || ch == ';' || ch == '{')       //找到一个配置项
            {
                last_space = 1;
                found = 1;                              //找到了哇
            }

            if (found) {
                word = ngx_array_push(cf->args);        //配置项槽
                if (word == NULL) {
                    return NGX_ERROR;
                }

                word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);         //配置项名字
                if (word->data == NULL) {
                    return NGX_ERROR;
                }

                for (dst = word->data, src = start, len = 0;
                     src < b->pos - 1;
                     len++)
                {
                    if (*src == '\\') {
                        switch (src[1]) {
                        case '"':
                        case '\'':
                        case '\\':
                            src++;
                            break;

                        case 't':
                            *dst++ = '\t';
                            src += 2;
                            continue;

                        case 'r':
                            *dst++ = '\r';
                            src += 2;
                            continue;

                        case 'n':
                            *dst++ = '\n';
                            src += 2;
                            continue;
                        }

                    }
                    *dst++ = *src++;
                }
                *dst = '\0';
                word->len = len;

                if (ch == ';') {
                    return NGX_OK;
                }

                if (ch == '{') {
                    return NGX_CONF_BLOCK_START;
                }

                found = 0;
            }
        }
    }
}
Beispiel #13
0
ngx_int_t
ngx_getmeminfo(ngx_meminfo_t *meminfo, ngx_log_t *log)
{
    u_char              buf[2048];
    u_char             *p, *start, *last;
    size_t             *sz = NULL;
    ssize_t             n, len;
    ngx_fd_t            fd;
    enum {
        sw_name = 0,
        sw_value_start,
        sw_value,
        sw_skipline,
        sw_newline,
    } state;

    ngx_memzero(meminfo, sizeof(ngx_meminfo_t));

    if (ngx_meminfo_file.fd == 0) {

        fd = ngx_open_file(NGX_MEMINFO_FILE, NGX_FILE_RDONLY,
                           NGX_FILE_OPEN,
                           NGX_FILE_DEFAULT_ACCESS);

        if (fd == NGX_INVALID_FILE) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                          ngx_open_file_n " \"%s\" failed",
                          NGX_MEMINFO_FILE);

            return NGX_ERROR;
        }

        ngx_meminfo_file.name.data = (u_char *) NGX_MEMINFO_FILE;
        ngx_meminfo_file.name.len = ngx_strlen(NGX_MEMINFO_FILE);

        ngx_meminfo_file.fd = fd;
    }

    ngx_meminfo_file.log = log;
    n = ngx_read_file(&ngx_meminfo_file, buf, sizeof(buf) - 1, 0);
    if (n == NGX_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                      ngx_read_file_n " \"%s\" failed",
                      NGX_MEMINFO_FILE);

        return NGX_ERROR;
    }

    p = buf;
    start = buf;
    last = buf + n;
    state = sw_name;

    for (; p < last; p++) {

        if (*p == '\n') {
            state = sw_newline;
        }

        switch (state) {

        case sw_name:
            if (*p != ':') {
                continue;
            }

            len = p - start;
            sz = NULL;

            switch (len) {
            case 6:
                /* Cached */
                if (meminfo->cachedram == 0 &&
                    ngx_strncmp(start, "Cached", len) == 0)
                {
                    sz = &meminfo->cachedram;
                }
                break;
            case 7:
                /* Buffers MemFree */
                if (meminfo->bufferram == 0 &&
                    ngx_strncmp(start, "Buffers", len) == 0)
                {
                    sz = &meminfo->bufferram;
                } else if (meminfo->freeram == 0 &&
                           ngx_strncmp(start, "MemFree", len) == 0)
                {
                    sz = &meminfo->freeram;
                }
                break;
            case 8:
                /* MemTotal SwapFree */
                if (meminfo->totalram == 0 &&
                    ngx_strncmp(start, "MemTotal", len) == 0)
                {
                    sz = &meminfo->totalram;
                } else if (meminfo->freeswap == 0 &&
                           ngx_strncmp(start, "SwapFree", len) == 0)
                {
                    sz = &meminfo->freeswap;
                }
                break;
            case 9:
                /* SwapTotal */
                if (meminfo->totalswap == 0 &&
                    ngx_strncmp(start, "SwapTotal", len) == 0)
                {
                    sz = &meminfo->totalswap;
                }
                break;
            }

            if (sz == NULL) {
                state = sw_skipline;
                continue;
            }

            state = sw_value_start;

            continue;

        case sw_value_start:

            if (*p == ' ') {
                continue;
            }

            start = p;
            state = sw_value;

            continue;

        case sw_value:

            if (*p >= '0' && *p <= '9') {
                continue;
            }

            *(sz) =  ngx_atosz(start, p - start) * 1024;

            state = sw_skipline;

            continue;

        case sw_skipline:

            continue;

        case sw_newline:

            state = sw_name;
            start = p + 1;

            continue;
        }
    }

    return NGX_OK;
}
static ngx_int_t
ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf,
    ngx_http_lua_block_parser_ctx_t *ctx)
{
    enum {
        OVEC_SIZE = 2
    };
    int          i, rc;
    int          ovec[OVEC_SIZE];
    u_char      *start, *p, *q, ch;
    off_t        file_size;
    size_t       len, buf_size;
    ssize_t      n, size;
    ngx_uint_t   start_line;
    ngx_str_t   *word;
    ngx_buf_t   *b;
#if nginx_version >= 1009002
    ngx_buf_t   *dump;
#endif

    b = cf->conf_file->buffer;
#if nginx_version >= 1009002
    dump = cf->conf_file->dump;
#endif
    start = b->pos;
    start_line = cf->conf_file->line;
    buf_size = b->end - b->start;

    dd("lexer start line: %d", (int) start_line);

    file_size = ngx_file_size(&cf->conf_file->file.info);

    for ( ;; ) {

        if (b->pos >= b->last) {

            if (cf->conf_file->file.offset >= file_size) {

                cf->conf_file->line = ctx->start_line;

                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "unexpected end of file, expecting "
                                   "terminating characters for lua code "
                                   "block");
                return NGX_ERROR;
            }

            len = b->pos - start;

            if (len == buf_size) {

                cf->conf_file->line = start_line;

                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "too long lua code block, probably "
                                   "missing terminating characters");

                return NGX_ERROR;
            }

            if (len) {
                ngx_memmove(b->start, start, len);
            }

            size = (ssize_t) (file_size - cf->conf_file->file.offset);

            if (size > b->end - (b->start + len)) {
                size = b->end - (b->start + len);
            }

            n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
                              cf->conf_file->file.offset);

            if (n == NGX_ERROR) {
                return NGX_ERROR;
            }

            if (n != size) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   ngx_read_file_n " returned "
                                   "only %z bytes instead of %z",
                                   n, size);
                return NGX_ERROR;
            }

            b->pos = b->start + len;
            b->last = b->pos + n;
            start = b->start;

#if nginx_version >= 1009002
            if (dump) {
                dump->last = ngx_cpymem(dump->last, b->pos, size);
            }
#endif
        }

        rc = ngx_http_lua_lex(b->pos, b->last - b->pos, ovec);

        if (rc < 0) {  /* no match */
            /* alas. the lexer does not yet support streaming processing. need
             * more work below */

            if (cf->conf_file->file.offset >= file_size) {

                cf->conf_file->line = ctx->start_line;

                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "unexpected end of file, expecting "
                                   "terminating characters for lua code "
                                   "block");
                return NGX_ERROR;
            }

            len = b->last - b->pos;

            if (len == buf_size) {

                cf->conf_file->line = start_line;

                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "too long lua code block, probably "
                                   "missing terminating characters");

                return NGX_ERROR;
            }

            if (len) {
                ngx_memcpy(b->start, b->pos, len);
            }

            size = (ssize_t) (file_size - cf->conf_file->file.offset);

            if (size > b->end - (b->start + len)) {
                size = b->end - (b->start + len);
            }

            n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
                              cf->conf_file->file.offset);

            if (n == NGX_ERROR) {
                return NGX_ERROR;
            }

            if (n != size) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   ngx_read_file_n " returned "
                                   "only %z bytes instead of %z",
                                   n, size);
                return NGX_ERROR;
            }

            b->pos = b->start + len;
            b->last = b->pos + n;
            start = b->start;

            continue;
        }

        if (rc == FOUND_LEFT_LBRACKET_STR || rc == FOUND_LEFT_LBRACKET_CMT) {

            /* we update the line numbers for best error messages when the
             * closing long bracket is missing */

            for (i = 0; i < ovec[0]; i++) {
                ch = b->pos[i];
                if (ch == LF) {
                    cf->conf_file->line++;
                }
            }

            b->pos += ovec[0];
            ovec[1] -= ovec[0];
            ovec[0] = 0;

            if (rc == FOUND_LEFT_LBRACKET_CMT) {
                p = &b->pos[2];     /* we skip the leading "--" prefix */
                rc = FOUND_LBRACKET_CMT;

            } else {
                p = b->pos;
                rc = FOUND_LBRACKET_STR;
            }

            /* we temporarily rewrite [=*[ in the input buffer to ]=*] to
             * construct the pattern for the corresponding closing long
             * bracket without additional buffers. */

            ngx_http_lua_assert(p[0] == '[');
            p[0] = ']';

            ngx_http_lua_assert(b->pos[ovec[1] - 1] == '[');
            b->pos[ovec[1] - 1] = ']';

            /* search for the corresponding closing bracket */

            dd("search pattern for the closing long bracket: \"%.*s\" (len=%d)",
               (int) (b->pos + ovec[1] - p), p, (int) (b->pos + ovec[1] - p));

            q = ngx_http_lua_strlstrn(b->pos + ovec[1], b->last, p,
                                      b->pos + ovec[1] - p - 1);

            if (q == NULL) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "Lua code block missing the closing "
                                   "long bracket \"%*s\"",
                                   b->pos + ovec[1] - p, p);
                return NGX_ERROR;
            }

            /* restore the original opening long bracket */

            p[0] = '[';
            b->pos[ovec[1] - 1] = '[';

            ovec[1] = q - b->pos + b->pos + ovec[1] - p;

            dd("found long bracket token: \"%.*s\"",
               (int) (ovec[1] - ovec[0]), b->pos + ovec[0]);
        }

        for (i = 0; i < ovec[1]; i++) {
            ch = b->pos[i];
            if (ch == LF) {
                cf->conf_file->line++;
            }
        }

        b->pos += ovec[1];
        ctx->token_len = ovec[1] - ovec[0];

        break;
    }

    word = ngx_array_push(cf->args);
    if (word == NULL) {
        return NGX_ERROR;
    }

    word->data = ngx_pnalloc(cf->temp_pool, b->pos - start);
    if (word->data == NULL) {
        return NGX_ERROR;
    }

    len = b->pos - start;
    ngx_memcpy(word->data, start, len);
    word->len = len;

    return rc;
}
static ngx_int_t
ngx_output_chain_copy_buf(ngx_output_chain_ctx_t *ctx)
{
    off_t        size;
    ssize_t      n;
    ngx_buf_t   *src, *dst;
    ngx_uint_t   sendfile;

    src = ctx->in->buf;
    dst = ctx->buf;

    size = ngx_buf_size(src);
    size = ngx_min(size, dst->end - dst->pos);

    sendfile = ctx->sendfile & !ctx->directio;

#if (NGX_SENDFILE_LIMIT)

    if (src->in_file && src->file_pos >= NGX_SENDFILE_LIMIT) {
        sendfile = 0;
    }

#endif

    if (ngx_buf_in_memory(src)) {
        ngx_memcpy(dst->pos, src->pos, (size_t) size);
        src->pos += (size_t) size;
        dst->last += (size_t) size;

        if (src->in_file) {

            if (sendfile) {
                dst->in_file = 1;
                dst->file = src->file;
                dst->file_pos = src->file_pos;
                dst->file_last = src->file_pos + size;

            } else {
                dst->in_file = 0;
            }

            src->file_pos += size;

        } else {
            dst->in_file = 0;
        }

        if (src->pos == src->last) {
            dst->flush = src->flush;
            dst->last_buf = src->last_buf;
            dst->last_in_chain = src->last_in_chain;
        }

    } else {

#if (NGX_HAVE_ALIGNED_DIRECTIO)

        if (ctx->unaligned) {
            if (ngx_directio_off(src->file->fd) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
                              ngx_directio_off_n " \"%s\" failed",
                              src->file->name.data);
            }
        }

#endif

#if (NGX_HAVE_FILE_AIO)
        if (ctx->aio_handler) {
            n = ngx_file_aio_read(src->file, dst->pos, (size_t) size,
                                  src->file_pos, ctx->pool);
            if (n == NGX_AGAIN) {
                ctx->aio_handler(ctx, src->file);
                return NGX_AGAIN;
            }

        } else
#endif
#if (NGX_THREADS)
        if (src->file->thread_handler) {
            n = ngx_thread_read(&ctx->thread_task, src->file, dst->pos,
                                (size_t) size, src->file_pos, ctx->pool);
            if (n == NGX_AGAIN) {
                ctx->aio = 1;
                return NGX_AGAIN;
            }

        } else
#endif
        {
            n = ngx_read_file(src->file, dst->pos, (size_t) size,
                              src->file_pos);
        }

#if (NGX_HAVE_ALIGNED_DIRECTIO)

        if (ctx->unaligned) {
            ngx_err_t  err;

            err = ngx_errno;

            if (ngx_directio_on(src->file->fd) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
                              ngx_directio_on_n " \"%s\" failed",
                              src->file->name.data);
            }

            ngx_set_errno(err);

            ctx->unaligned = 0;
        }

#endif

        if (n == NGX_ERROR) {
            return (ngx_int_t) n;
        }

        if (n != size) {
            ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
                          ngx_read_file_n " read only %z of %O from \"%s\"",
                          n, size, src->file->name.data);
            return NGX_ERROR;
        }

        dst->last += n;

        if (sendfile) {
            dst->in_file = 1;
            dst->file = src->file;
            dst->file_pos = src->file_pos;
            dst->file_last = src->file_pos + n;

        } else {
            dst->in_file = 0;
        }

        src->file_pos += n;

        if (src->file_pos == src->file_last) {
            dst->flush = src->flush;
            dst->last_buf = src->last_buf;
            dst->last_in_chain = src->last_in_chain;
        }
    }

    return NGX_OK;
}
Beispiel #16
0
/**
 * nginx handler to feed request body (if any) to IronBee
 *
 * @param[in] r   the nginx request object
 * @return    NGX_DECLINED for normal operation
 * @return    NGX_DONE if body is not yet available (processing will resume
 *            on new data)
 * @return    Error status if set by IronBee on sight of request data.
 */
ngx_int_t ngxib_handler(ngx_http_request_t *r)
{
    ngx_chain_t *link;
    ngxib_req_ctx *ctx;
    ngx_int_t rv = NGX_DECLINED;
    ngx_http_request_body_t *rb;
    /* Don't process internal requests */
    if (r->internal)
        return rv;

    ctx = ngx_http_get_module_ctx(r, ngx_ironbee_module);
    if (ctx->body_done)
        return rv;

    /* We already completed handling of no-body requests
     * when we looked at headers
     */
    if (!ngxib_has_request_body(r, ctx))
        return rv;

    ngx_regex_malloc_init(r->pool);

    /* We can now read the body.
     * This may come asynchronously in many chunks, so we need
     * to check for AGAIN and return DONE if waiting.
     * We pass it a handler to go round again while waiting.
     *
     * TODO: figure out how to pass data to ironbee asynchronously
     */
    rv = ngx_http_read_client_request_body(r, ngxib_post_handler);
    if (rv == NGX_AGAIN) {
        ctx->body_wait = 1;
        cleanup_return NGX_DONE;
    }

    /* We now have the request body.  Feed it to ironbee */
    rb = r->request_body;
    if (!rb) {
        ib_log_error_tx(ctx->tx, "Failed to read request body.");
        cleanup_return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    if (!rb->bufs) {
        /* I think this shouldn't happen */
        /* But rethink if this turns up in logs when all is fine */
        ib_log_error_tx(ctx->tx, "Probable error reading request body.");
    }

    if (rb->temp_file && (rb->temp_file->file.fd != NGX_INVALID_FILE)) {
        /* Reader has put request body in temp file */
        off_t count = 0;
        u_char buf[BUFSIZE];
        size_t buf_len;
        ib_log_debug_tx(ctx->tx, "Reading request body in temp file.");
        while (buf_len = ngx_read_file(&rb->temp_file->file,
                         buf, BUFSIZE, count),
               buf_len > 0) {
            ib_log_debug_tx(ctx->tx, "Feeding %zd bytes request data to ironbee.",
                            buf_len);
            ib_state_notify_request_body_data(ctx->tx->ib, ctx->tx,
                                              (const char*)buf, buf_len);
            count += buf_len;
        }
        if ((int)buf_len == NGX_ERROR) {
            ib_log_error_tx(ctx->tx, "Failed to read request body in temp file.");
        }
    }

    for (link = rb->bufs; link != NULL; link = link->next) {
        size_t len = (link->buf->last - link->buf->pos);
        ib_log_debug_tx(ctx->tx, "Feeding %zd bytes request data to ironbee.",
                        len);
        if (len > 0) {
            ib_state_notify_request_body_data(ctx->tx->ib, ctx->tx,
                                              (const char*)link->buf->pos, len);
        }
    }
    ctx->body_done = 1;
    ib_state_notify_request_finished(ctx->tx->ib, ctx->tx);

    /* If IronBee signaled an error, we can return it */
    if (STATUS_IS_ERROR(ctx->status)) {
        rv = ctx->status;
        ctx->internal_errordoc = 1;
        ib_log_error_tx(ctx->tx, "IronBee set %d reading request body.", (int)rv);
    }

    cleanup_return rv;
}
static ngx_buf_t *
ngx_http_dyups_read_body_from_file(ngx_http_request_t *r)
{
    size_t        len;
    ssize_t       size;
    ngx_buf_t    *buf, *body;
    ngx_chain_t  *cl;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "interface read post body from file");

    len = 0;
    cl = r->request_body->bufs;

    while (cl) {

        buf = cl->buf;

        if (buf->in_file) {
            len += buf->file_last - buf->file_pos;

        } else {
            len += buf->last - buf->pos;
        }

        cl = cl->next;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "interface read post body file size %ui", len);

    body = ngx_create_temp_buf(r->pool, len);
    if (body == NULL) {
        return NULL;
    }

    cl = r->request_body->bufs;

    while (cl) {

        buf = cl->buf;

        if (buf->in_file) {

            size = ngx_read_file(buf->file, body->last,
                                 buf->file_last - buf->file_pos, buf->file_pos);

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

            body->last += size;

        } else {

            body->last = ngx_cpymem(body->last, buf->pos, buf->last - buf->pos);
        }

        cl = cl->next;
    }

    return body;
}
static ngx_int_t
ngx_http_auth_basic_handler(ngx_http_request_t *r)
{
    off_t                            offset;
    ssize_t                          n;
    ngx_fd_t                         fd;
    ngx_int_t                        rc;
    ngx_err_t                        err;
    ngx_str_t                        pwd, realm, user_file;
    ngx_uint_t                       i, level, login, left, passwd;
    ngx_file_t                       file;
    ngx_http_auth_basic_ctx_t       *ctx;
    ngx_http_auth_basic_loc_conf_t  *alcf;
    u_char                           buf[NGX_HTTP_AUTH_BUF_SIZE];
    enum {
        sw_login,
        sw_passwd,
        sw_skip
    } state;

    alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module);

    if (alcf->realm == NULL || alcf->user_file.value.data == NULL) {
        return NGX_DECLINED;
    }

    if (ngx_http_complex_value(r, alcf->realm, &realm) != NGX_OK) {
        return NGX_ERROR;
    }

    if (realm.len == 3 && ngx_strncmp(realm.data, "off", 3) == 0) {
        return NGX_DECLINED;
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_auth_basic_module);

    if (ctx) {
        return ngx_http_auth_basic_crypt_handler(r, ctx, &ctx->passwd,
                                                 &realm);
    }

    rc = ngx_http_auth_basic_user(r);

    if (rc == NGX_DECLINED) {

        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                      "no user/password was provided for basic authentication");

        return ngx_http_auth_basic_set_realm(r, &realm);
    }

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

    if (ngx_http_complex_value(r, &alcf->user_file, &user_file) != NGX_OK) {
        return NGX_ERROR;
    }

    fd = ngx_open_file(user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);

    if (fd == NGX_INVALID_FILE) {
        err = ngx_errno;

        if (err == NGX_ENOENT) {
            level = NGX_LOG_ERR;
            rc = NGX_HTTP_FORBIDDEN;

        } else {
            level = NGX_LOG_CRIT;
            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        ngx_log_error(level, r->connection->log, err,
                      ngx_open_file_n " \"%s\" failed", user_file.data);

        return rc;
    }

    ngx_memzero(&file, sizeof(ngx_file_t));

    file.fd = fd;
    file.name = user_file;
    file.log = r->connection->log;

    state = sw_login;
    passwd = 0;
    login = 0;
    left = 0;
    offset = 0;

    for ( ;; ) {
        i = left;

        n = ngx_read_file(&file, buf + left, NGX_HTTP_AUTH_BUF_SIZE - left,
                          offset);

        if (n == NGX_ERROR) {
            ngx_http_auth_basic_close(&file);
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        if (n == 0) {
            break;
        }

        for (i = left; i < left + n; i++) {
            switch (state) {

            case sw_login:
                if (login == 0) {

                    if (buf[i] == '#' || buf[i] == CR) {
                        state = sw_skip;
                        break;
                    }

                    if (buf[i] == LF) {
                        break;
                    }
                }

                if (buf[i] != r->headers_in.user.data[login]) {
                    state = sw_skip;
                    break;
                }

                if (login == r->headers_in.user.len) {
                    state = sw_passwd;
                    passwd = i + 1;
                }

                login++;

                break;

            case sw_passwd:
                if (buf[i] == LF || buf[i] == CR || buf[i] == ':') {
                    buf[i] = '\0';

                    ngx_http_auth_basic_close(&file);

                    pwd.len = i - passwd;
                    pwd.data = &buf[passwd];

                    return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd,
                                                             &realm);
                }

                break;

            case sw_skip:
                if (buf[i] == LF) {
                    state = sw_login;
                    login = 0;
                }

                break;
            }
        }

        if (state == sw_passwd) {
            left = left + n - passwd;
            ngx_memmove(buf, &buf[passwd], left);
            passwd = 0;

        } else {
            left = 0;
        }

        offset += n;
    }

    ngx_http_auth_basic_close(&file);

    if (state == sw_passwd) {
        pwd.len = i - passwd;
        pwd.data = ngx_pnalloc(r->pool, pwd.len + 1);
        if (pwd.data == NULL) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);

        return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &realm);
    }

    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                  "user \"%V\" was not found in \"%V\"",
                  &r->headers_in.user, &user_file);

    return ngx_http_auth_basic_set_realm(r, &realm);
}
Beispiel #19
0
static ngx_int_t
ngx_http_file_cache_add_file(ngx_tree_ctx_t *ctx, ngx_str_t *name)
{
    u_char                        *p;
    ngx_fd_t                       fd;
    ngx_int_t                      n;
    ngx_uint_t                     i;
    ngx_file_info_t                fi;
    ngx_http_cache_t               c;
    ngx_http_file_cache_t         *cache;
    ngx_http_file_cache_header_t   h;

    if (name->len < 2 * NGX_HTTP_CACHE_KEY_LEN) {
        return NGX_ERROR;
    }

    ngx_memzero(&c, sizeof(ngx_http_cache_t));

    fd = ngx_open_file(name->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);

    if (fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
                      ngx_open_file_n " \"%s\" failed", name->data);
        return NGX_ERROR;
    }

    c.file.fd = fd;
    c.file.name = *name;
    c.file.log = ctx->log;

    n = ngx_read_file(&c.file, (u_char *) &h,
                      sizeof(ngx_http_file_cache_header_t), 0);
    if (n == NGX_ERROR) {
        return NGX_ERROR;
    }

    if ((size_t) n < sizeof(ngx_http_file_cache_header_t)) {
        ngx_log_error(NGX_LOG_CRIT, ctx->log, 0,
                      "cache file \"%s\" is too small", name->data);
        return NGX_ERROR;
    }

    if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
                      ngx_fd_info_n " \"%s\" failed", name->data);

    } else {
        c.uniq = ngx_file_uniq(&fi);
        c.valid_sec = h.valid_sec;
        c.valid_msec = h.valid_msec;
        c.body_start = h.body_start;
        c.length = ngx_file_size(&fi);
    }

    if (ngx_close_file(fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", name->data);
    }

    if (c.body_start == 0) {
        return NGX_ERROR;
    }

    p = &name->data[name->len - 2 * NGX_HTTP_CACHE_KEY_LEN];

    for (i = 0; i < NGX_HTTP_CACHE_KEY_LEN; i++) {
        n = ngx_hextoi(p, 2);

        if (n == NGX_ERROR) {
            return NGX_ERROR;
        }

        p += 2;

        c.key[i] = (u_char) n;
    }

    cache = ctx->data;

    return ngx_http_file_cache_add(cache, &c);
}
ssize_t
ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
    ngx_pool_t *pool)
{
    int               n;
    ngx_event_t      *ev;
    ngx_event_aio_t  *aio;

    if (!ngx_file_aio) {
        return ngx_read_file(file, buf, size, offset);
    }

    aio = file->aio;

    if (aio == NULL) {
        aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t));
        if (aio == NULL) {
            return NGX_ERROR;
        }

        aio->file = file;
        aio->fd = file->fd;
        aio->event.data = aio;
        aio->event.ready = 1;
        aio->event.log = file->log;
#if (NGX_HAVE_AIO_SENDFILE)
        aio->last_offset = -1;
#endif
        file->aio = aio;
    }

    ev = &aio->event;

    if (!ev->ready) {
        ngx_log_error(NGX_LOG_ALERT, file->log, 0,
                      "second aio post for \"%V\"", &file->name);
        return NGX_AGAIN;
    }

    ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
                   "aio complete:%d @%O:%z %V",
                   ev->complete, offset, size, &file->name);

    if (ev->complete) {
        ev->complete = 0;
        ngx_set_errno(aio->err);

        if (aio->err == 0) {
            return aio->nbytes;
        }

        ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
                      "aio read \"%s\" failed", file->name.data);

        return NGX_ERROR;
    }

    ngx_memzero(&aio->aiocb, sizeof(struct aiocb));

    aio->aiocb.aio_fildes = file->fd;
    aio->aiocb.aio_offset = offset;
    aio->aiocb.aio_buf = buf;
    aio->aiocb.aio_nbytes = size;
#if (NGX_HAVE_KQUEUE)
    aio->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue;
    aio->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
    aio->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev;
#endif
    ev->handler = ngx_file_aio_event_handler;

    n = aio_read(&aio->aiocb);

    if (n == -1) {
        n = ngx_errno;

        if (n == NGX_EAGAIN) {
            return ngx_read_file(file, buf, size, offset);
        }

        ngx_log_error(NGX_LOG_CRIT, file->log, n,
                      "aio_read(\"%V\") failed", &file->name);

        if (n == NGX_ENOSYS) {
            ngx_file_aio = 0;
            return ngx_read_file(file, buf, size, offset);
        }

        return NGX_ERROR;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0,
                   "aio_read: fd:%d %d", file->fd, n);

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

    return ngx_file_aio_result(aio->file, aio, ev);
}
//从配置文件中读取数据到cf->conf_file->buffer中,并解析
static ngx_int_t
ngx_conf_read_token(ngx_conf_t *cf)
{
    u_char      *start, ch, *src, *dst;
    off_t        file_size;
    size_t       len;
    ssize_t      n, size;
    ngx_uint_t   found, need_space, last_space, sharp_comment, variable;
    ngx_uint_t   quoted, s_quoted, d_quoted, start_line;
    ngx_str_t   *word;
    ngx_buf_t   *b;

    found = 0;
    need_space = 0;
    last_space = 1;
    sharp_comment = 0;
    variable = 0;
    quoted = 0;
    s_quoted = 0;
    d_quoted = 0;

    cf->args->nelts = 0;
    b = cf->conf_file->buffer;
    start = b->pos;
    start_line = cf->conf_file->line;

    file_size = ngx_file_size(&cf->conf_file->file.info);

    for ( ;; ) {

        if (b->pos >= b->last) { //如果已经解析完了读取到的数据

            if (cf->conf_file->file.offset >= file_size) {//配置文件已经读完

                if (cf->args->nelts > 0) {//没有碰到配置块的结束,文件已经读完则出错

                    if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
                        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                           "unexpected end of parameter, "
                                           "expecting \";\"");
                        return NGX_ERROR;
                    }

                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                  "unexpected end of file, "
                                  "expecting \";\" or \"}\"");
                    return NGX_ERROR;
                }

                return NGX_CONF_FILE_DONE; //否则我们返回DONE
            }

            len = b->pos - start;	//len字节数据已经解析完了

            if (len == NGX_CONF_BUFFER) { //如果缓冲区满了
                cf->conf_file->line = start_line;

                if (d_quoted) {
                    ch = '"';

                } else if (s_quoted) {
                    ch = '\'';

                } else {//当前参数的解析还没有结束则出错
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "too long parameter \"%*s...\" started",
                                       10, start);
                    return NGX_ERROR;
                }

                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "too long parameter, probably "
                                   "missing terminating \"%c\" character", ch); //可能是引号不匹配
                return NGX_ERROR;
            }

            if (len) {//len字节数据已经解析完成了,我们不再需要保存这些数据,将他们覆盖,以读取更多的数据 
                ngx_memmove(b->start, start, len);
            }

			//文件还有size大小未读取
            size = (ssize_t) (file_size - cf->conf_file->file.offset);

            if (size > b->end - (b->start + len)) { //如果缓冲区读不完整个文件
                size = b->end - (b->start + len);  //则只读取缓冲区大小
            }

			//读取文件(如果缓冲区足够大,则我们一次性读取整个文件到缓冲区中,否则我们只读取一部分)
            n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
                              cf->conf_file->file.offset);

            if (n == NGX_ERROR) {
                return NGX_ERROR;
            }

            if (n != size) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   ngx_read_file_n " returned "
                                   "only %z bytes instead of %z",
                                   n, size);
                return NGX_ERROR;
            }

            b->pos = b->start + len;//b->pos指向我们将要解析的数据开始位置
            b->last = b->pos + n;	//b->last现在指向数据的结束位置
            start = b->start;
        } //end if b->pos >= b->last


		//以下开始解析缓冲区中读取到的数据
        ch = *b->pos++;

        if (ch == LF) {//碰到换行符,则line++
            cf->conf_file->line++;

            if (sharp_comment) {
                sharp_comment = 0;
            }
        }

        if (sharp_comment) {
            continue;
        }

        if (quoted) {
            quoted = 0;
            continue;
        }

        if (need_space) {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
                last_space = 1;
                need_space = 0;
                continue;
            }

            if (ch == ';') {
                return NGX_OK;
            }

            if (ch == '{') {
                return NGX_CONF_BLOCK_START;
            }

            if (ch == ')') {
                last_space = 1;
                need_space = 0;

            } else {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                    "unexpected \"%c\"", ch);
                 return NGX_ERROR;
            }
        }

        if (last_space) {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
                continue;
            }

            start = b->pos - 1;
            start_line = cf->conf_file->line;

            switch (ch) {

            case ';':
            case '{':
                if (cf->args->nelts == 0) {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "unexpected \"%c\"", ch);
                    return NGX_ERROR;
                }

                if (ch == '{') {
                    return NGX_CONF_BLOCK_START;
                }

                return NGX_OK;

            case '}':
                if (cf->args->nelts != 0) {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "unexpected \"}\"");
                    return NGX_ERROR;
                }

                return NGX_CONF_BLOCK_DONE;

            case '#':
                sharp_comment = 1;
                continue;

            case '\\':
                quoted = 1;
                last_space = 0;
                continue;

            case '"':
                start++;
                d_quoted = 1;
                last_space = 0;
                continue;

            case '\'':
                start++;
                s_quoted = 1;
                last_space = 0;
                continue;

            default:
                last_space = 0;
            }

        } else {
            if (ch == '{' && variable) {
                continue;
            }

            variable = 0;

            if (ch == '\\') {
                quoted = 1;
                continue;
            }

            if (ch == '$') {
                variable = 1;
                continue;
            }

            if (d_quoted) {
                if (ch == '"') {
                    d_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            } else if (s_quoted) {
                if (ch == '\'') {
                    s_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
                       || ch == ';' || ch == '{')
            {
                last_space = 1;
                found = 1;
            }

			//如果发现一条配置项,则我们将其放置到cf->args数组中
            if (found) {
                word = ngx_array_push(cf->args);
                if (word == NULL) {
                    return NGX_ERROR;
                }

                word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
                if (word->data == NULL) {
                    return NGX_ERROR;
                }

                for (dst = word->data, src = start, len = 0;
                     src < b->pos - 1;
                     len++)
                {
                    if (*src == '\\') {
                        switch (src[1]) {
                        case '"':
                        case '\'':
                        case '\\':
                            src++;
                            break;

                        case 't':
                            *dst++ = '\t';
                            src += 2;
                            continue;

                        case 'r':
                            *dst++ = '\r';
                            src += 2;
                            continue;

                        case 'n':
                            *dst++ = '\n';
                            src += 2;
                            continue;
                        }

                    }
                    *dst++ = *src++;
                }
                *dst = '\0';
                word->len = len;

                if (ch == ';') {
                    return NGX_OK;
                }

                if (ch == '{') {
                    return NGX_CONF_BLOCK_START;
                }

                found = 0;
            }
        }
    }
}
static void
ngx_rtmp_play_read_meta(ngx_rtmp_session_t *s)
{
    ngx_rtmp_play_ctx_t            *ctx;
    ssize_t                         n;
    ngx_rtmp_header_t               h;
    ngx_chain_t                    *out, in;
    ngx_buf_t                       in_buf;
    ngx_rtmp_core_srv_conf_t       *cscf;
    uint32_t                        size;

    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;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                  "play: read meta");
    
    /* read tag header */
    n = ngx_read_file(&ctx->file, ngx_rtmp_play_header, 
                      sizeof(ngx_rtmp_play_header), NGX_RTMP_PLAY_DATA_OFFSET);
    if (n != sizeof(ngx_rtmp_play_header)) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                     "play: could not read metadata tag header");
        return;
    }

    if (ngx_rtmp_play_header[0] != NGX_RTMP_MSG_AMF_META) {
        ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                      "play: first tag is not metadata, giving up");
        return;
    }

    ngx_memzero(&h, sizeof(h));
    h.type = NGX_RTMP_MSG_AMF_META;
    h.msid = NGX_RTMP_LIVE_MSID;
    h.csid = NGX_RTMP_LIVE_CSID_META;
    size = 0;
    ngx_rtmp_rmemcpy(&size, ngx_rtmp_play_header + 1, 3);

    ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                  "play: metadata size=%D", size);

    if (size > sizeof(ngx_rtmp_play_buffer)) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                     "play: too big metadata");
        return;
    }

    /* read metadata */
    n = ngx_read_file(&ctx->file, ngx_rtmp_play_buffer, 
                      size, sizeof(ngx_rtmp_play_header) + 
                      NGX_RTMP_PLAY_DATA_OFFSET);
    if (n != (ssize_t) size) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                      "play: could not read metadata");
        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;

    ngx_rtmp_play_init_index(s, &in);

    /* output chain */
    out = ngx_rtmp_append_shared_bufs(cscf, NULL, &in);
    ngx_rtmp_prepare_message(s, &h, NULL, out);
    ngx_rtmp_send_message(s, out, 0);
    ngx_rtmp_free_shared_chain(cscf, out);
}
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);
}
Beispiel #24
0
static ngx_int_t
ngx_conf_read_token(ngx_conf_t *cf)
{
    u_char      *start, ch, *src, *dst;
    int          len;
    int          found, need_space, last_space, sharp_comment, variable;
    int          quoted, s_quoted, d_quoted;
    ssize_t      n;
    ngx_str_t   *word;
    ngx_buf_t   *b;

    found = 0;
    need_space = 0;
    last_space = 1;
    sharp_comment = 0;
    variable = 0;
    quoted = s_quoted = d_quoted = 0;

    cf->args->nelts = 0;
    b = cf->conf_file->buffer;
    start = b->pos;

    for ( ;; ) {

        if (b->pos >= b->last) {
            if (cf->conf_file->file.offset
                                 >= ngx_file_size(&cf->conf_file->file.info))
            {
                if (cf->args->nelts > 0) {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                  "unexpected end of file, "
                                  "expecting \";\" or \"}\"");
                    return NGX_ERROR;
                }

                return NGX_CONF_FILE_DONE;
            }

            if (b->pos - start) {
                ngx_memcpy(b->start, start, b->pos - start);
            }

            n = ngx_read_file(&cf->conf_file->file,
                              b->start + (b->pos - start),
                              b->end - (b->start + (b->pos - start)),
                              cf->conf_file->file.offset);

            if (n == NGX_ERROR) {
                return NGX_ERROR;
            }

            b->pos = b->start + (b->pos - start);
            start = b->start;
            b->last = b->pos + n;
        }

        ch = *b->pos++;

        if (ch == LF) {
            cf->conf_file->line++;

            if (sharp_comment) {
                sharp_comment = 0;
            }
        }

        if (sharp_comment) {
            continue;
        }

        if (quoted) {
            quoted = 0;
            continue;
        }

        if (need_space) {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
                last_space = 1;
                need_space = 0;
                continue;
            }

            if (ch == ';') {
                return NGX_OK;
            }

            if (ch == '{') {
                return NGX_CONF_BLOCK_START;
            }

            if (ch == ')') {
                last_space = 1;
                need_space = 0;

            } else {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                    "unexpected \"%c\"", ch);
                 return NGX_ERROR;
            }
        }

        if (last_space) {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
                continue;
            }

            start = b->pos - 1;

            switch (ch) {

            case ';':
            case '{':
                if (cf->args->nelts == 0) {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "unexpected \"%c\"", ch);
                    return NGX_ERROR;
                }

                if (ch == '{') {
                    return NGX_CONF_BLOCK_START;
                }

                return NGX_OK;

            case '}':
                if (cf->args->nelts != 0) {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "unexpected \"}\"");
                    return NGX_ERROR;
                }

                return NGX_CONF_BLOCK_DONE;

            case '#':
                sharp_comment = 1;
                continue;

            case '\\':
                quoted = 1;
                last_space = 0;
                continue;

            case '"':
                start++;
                d_quoted = 1;
                last_space = 0;
                continue;

            case '\'':
                start++;
                s_quoted = 1;
                last_space = 0;
                continue;

            default:
                last_space = 0;
            }

        } else {
            if (ch == '{' && variable) {
                continue;
            }

            variable = 0;

            if (ch == '\\') {
                quoted = 1;
                continue;
            }

            if (ch == '$') {
                variable = 1;
                continue;
            }

            if (d_quoted) {
                if (ch == '"') {
                    d_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            } else if (s_quoted) {
                if (ch == '\'') {
                    s_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
                       || ch == ';' || ch == '{') {
                last_space = 1;
                found = 1;
            }

            if (found) {
                word = ngx_array_push(cf->args);
                if (word == NULL) {
                    return NGX_ERROR;
                }

                word->data = ngx_palloc(cf->pool, b->pos - start + 1);
                if (word->data == NULL) {
                    return NGX_ERROR;
                }

                for (dst = word->data, src = start, len = 0;
                     src < b->pos - 1;
                     len++)
                {
                    if (*src == '\\') {
                        switch (src[1]) {
                        case '"':
                        case '\'':
                        case '\\':
                            src++;
                            break;

                        case 't':
                            *dst++ = '\t';
                            src += 2;
                            continue;

                        case 'r':
                            *dst++ = '\r';
                            src += 2;
                            continue;

                        case 'n':
                            *dst++ = '\n';
                            src += 2;
                            continue;
                        }

                    }
                    *dst++ = *src++;
                }
                *dst = '\0';
                word->len = len;

                if (ch == ';') {
                    return NGX_OK;
                }

                if (ch == '{') {
                    return NGX_CONF_BLOCK_START;
                }

                found = 0;
            }
        }
    }
}
Beispiel #25
0
static int ngx_conf_read_token(ngx_conf_t *cf)
{
    u_char      *start, ch, *src, *dst;
    int          len;
    int          found, need_space, last_space, sharp_comment;
    int          quoted, s_quoted, d_quoted;
    ssize_t      n;
    ngx_str_t   *word;
    ngx_buf_t   *b;

    found = 0;
    need_space = 0;
    last_space = 1;
    sharp_comment = 0;
    quoted = s_quoted = d_quoted = 0;

    cf->args->nelts = 0;
    b = cf->conf_file->buffer;
    start = b->pos;

#if 0
    ngx_log_debug(cf->log, "TOKEN START");
#endif

    for ( ;; )
    {

        if (b->pos >= b->last)
        {
            if (cf->conf_file->file.offset
                    >= ngx_file_size(&cf->conf_file->file.info))
            {
                return NGX_CONF_FILE_DONE;
            }

            if (b->pos - start)
            {
                ngx_memcpy(b->start, start, b->pos - start);
            }

            n = ngx_read_file(&cf->conf_file->file,
                              b->start + (b->pos - start),
                              b->end - (b->start + (b->pos - start)),
                              cf->conf_file->file.offset);

            if (n == NGX_ERROR)
            {
                return NGX_ERROR;
            }

            b->pos = b->start + (b->pos - start);
            start = b->start;
            b->last = b->pos + n;
        }

        ch = *b->pos++;

#if 0
        ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _
                      last_space _ need_space _
                      quoted _ s_quoted _ d_quoted _ ch);
#endif

        if (ch == LF)
        {
            cf->conf_file->line++;

            if (sharp_comment)
            {
                sharp_comment = 0;
            }
        }

        if (sharp_comment)
        {
            continue;
        }

        if (quoted)
        {
            quoted = 0;
            continue;
        }

        if (need_space)
        {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF)
            {
                last_space = 1;
                need_space = 0;
                continue;
            }

            if (ch == ';' || ch == '{')
            {
                return NGX_OK;
            }

            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                          "unexpected '%c' in %s:%d",
                          ch, cf->conf_file->file.name.data,
                          cf->conf_file->line);

            return NGX_ERROR;
        }

        if (last_space)
        {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF)
            {
                continue;
            }

            start = b->pos - 1;

            switch (ch)
            {

            case ';':
            case '{':
                if (cf->args->nelts == 0)
                {
                    ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                                  "unexpected '%c' in %s:%d",
                                  ch, cf->conf_file->file.name.data,
                                  cf->conf_file->line);
                    return NGX_ERROR;
                }

                return NGX_OK;

            case '}':
                if (cf->args->nelts > 0)
                {
                    ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                                  "unexpected '}' in %s:%d",
                                  cf->conf_file->file.name.data,
                                  cf->conf_file->line);
                    return NGX_ERROR;
                }

                return NGX_CONF_BLOCK_DONE;

            case '#':
                sharp_comment = 1;
                continue;

            case '\\':
                quoted = 1;
                last_space = 0;
                continue;

            case '"':
                start++;
                d_quoted = 1;
                last_space = 0;
                continue;

            case '\'':
                start++;
                s_quoted = 1;
                last_space = 0;
                continue;

            default:
                last_space = 0;
            }

        }
        else
        {
            if (ch == '\\')
            {
                quoted = 1;
                continue;
            }

            if (d_quoted)
            {
                if (ch == '"')
                {
                    d_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            }
            else if (s_quoted)
            {
                if (ch == '\'')
                {
                    s_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            }
            else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
                     || ch == ';' || ch == '{')
            {
                last_space = 1;
                found = 1;
            }

            if (found)
            {
                if (!(word = ngx_push_array(cf->args)))
                {
                    return NGX_ERROR;
                }

                if (!(word->data = ngx_palloc(cf->pool, b->pos - start + 1)))
                {
                    return NGX_ERROR;
                }

                for (dst = word->data, src = start, len = 0;
                        src < b->pos - 1;
                        len++)
                {
                    if (*src == '\\')
                    {
                        switch (src[1])
                        {
                        case '"':
                        case '\'':
                        case '\\':
                            src++;
                            break;

                        case 't':
                            *dst++ = '\t';
                            src += 2;
                            continue;

                        case 'r':
                            *dst++ = '\r';
                            src += 2;
                            continue;

                        case 'n':
                            *dst++ = '\n';
                            src += 2;
                            continue;
                        }

                    }
                    *dst++ = *src++;
                }
                *dst = '\0';
                word->len = len;

#if 0
                ngx_log_debug(cf->log, "FOUND %d:'%s'" _ word->len _ word->data);
#endif

                if (ch == ';' || ch == '{')
                {
                    return NGX_OK;
                }

                found = 0;
            }
        }
    }
}
static ngx_int_t
ngx_rtmp_play_timestamp_to_offset(ngx_rtmp_session_t *s, ngx_int_t timestamp)
{
    ngx_rtmp_play_ctx_t            *ctx;
    ssize_t                         n, size;
    ngx_uint_t                      offset, index, ret, nelts;
    double                          v;

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
    if (ctx == NULL) {
        goto rewind;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                  "play: lookup index start timestamp=%i", 
                   timestamp);

    if (ctx->meta_read == 0) {
        ngx_rtmp_play_read_meta(s);
        ctx->meta_read = 1;
    }

    if (timestamp <= 0 || ctx->filepositions.nelts == 0
                       || ctx->times.nelts == 0) 
    {
        goto rewind;
    }

    /* read index table from file given offset */
    offset = NGX_RTMP_PLAY_DATA_OFFSET + NGX_RTMP_PLAY_TAG_HEADER
             + ctx->times.offset;

    /* index should fit in the buffer */
    nelts = ngx_min(ctx->times.nelts, sizeof(ngx_rtmp_play_buffer) / 9);
    size = nelts * 9;
    n = ngx_read_file(&ctx->file, ngx_rtmp_play_buffer, size, offset);
    if (n != size) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                     "play: could not read times index");
        goto rewind;
    }

    /*TODO: implement binary search */
    ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                  "play: lookup times nelts=%ui", nelts);

    for (index = 0; index < nelts - 1; ++index) {
        v = ngx_rtmp_play_index_value(ngx_rtmp_play_buffer 
                                      + index * 9 + 1) * 1000;

        ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                      "play: lookup times index=%ui value=%ui", 
                      index, (ngx_uint_t) v);

        if (timestamp < v) {
            break;
        }
    }

    if (index >= ctx->filepositions.nelts) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                     "play: index out of bounds: %ui>=%ui", 
                     index, ctx->filepositions.nelts);
        goto rewind;
    }

    /* take value from filepositions */
    offset = NGX_RTMP_PLAY_DATA_OFFSET + NGX_RTMP_PLAY_TAG_HEADER
           + ctx->filepositions.offset + index * 9;
    n = ngx_read_file(&ctx->file, ngx_rtmp_play_buffer, 8, offset + 1);
    if (n != 8) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                     "play: could not read filepositions index");
        goto rewind;
    }
    ret = ngx_rtmp_play_index_value(ngx_rtmp_play_buffer);

    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                  "play: lookup index timestamp=%i offset=%ui", 
                   timestamp, ret);

    return ret;

rewind:
    ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                  "play: lookup index timestamp=%i offset=begin", 
                   timestamp);
    
    return NGX_RTMP_PLAY_DATA_OFFSET;
}
static ngx_int_t
ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
                          ngx_rtmp_record_rec_ctx_t *rctx)
{
    ngx_rtmp_record_app_conf_t *rracf;
    ngx_rtmp_core_srv_conf_t   *cscf;
    ngx_err_t                   err;
    ngx_str_t                   path;
    ngx_int_t                   mode, create_mode;
    u_char                      buf[8], *p;
    off_t                       file_size;
    uint32_t                    tag_size, mlen, timestamp;

    rracf = rctx->conf;
    tag_size = 0;

    if (rctx->file.fd != NGX_INVALID_FILE) {
        return NGX_AGAIN;
    }

    cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);

    ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "record: %V opening", &rracf->id);

    ngx_memzero(rctx, sizeof(*rctx));
    rctx->conf = rracf;
    rctx->last = *ngx_cached_time;
    rctx->timestamp = ngx_cached_time->sec;

    ngx_rtmp_record_make_path(s, rctx, &path);

    mode = rracf->append ? NGX_FILE_RDWR : NGX_FILE_WRONLY;
    create_mode = rracf->append ? NGX_FILE_CREATE_OR_OPEN : NGX_FILE_TRUNCATE;

    ngx_memzero(&rctx->file, sizeof(rctx->file));
    rctx->file.offset = 0;
    rctx->file.log = s->connection->log;
    rctx->file.fd = ngx_open_file(path.data, mode, create_mode,
                                  cscf->file_access);
    ngx_str_set(&rctx->file.name, "recorded");

    if (rctx->file.fd == NGX_INVALID_FILE) {
        err = ngx_errno;

        if (err != NGX_ENOENT) {
            ngx_log_error(NGX_LOG_CRIT, s->connection->log, err,
                          "record: %V failed to open file '%V'",
                          &rracf->id, &path);
        }

        ngx_rtmp_record_notify_error(s, rctx);

        return NGX_OK;
    }

#if !(NGX_WIN32)
    if (rracf->lock_file) {
        err = ngx_lock_fd(rctx->file.fd);
        if (err) {
            ngx_log_error(NGX_LOG_CRIT, s->connection->log, err,
                          "record: %V lock failed", &rracf->id);
        }
    }
#endif

    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "record: %V opened '%V'", &rracf->id, &path);

    if (rracf->notify) {
        ngx_rtmp_send_status(s, "NetStream.Record.Start", "status",
                             rracf->id.data ? (char *) rracf->id.data : "");
    }

    if (rracf->append) {

        file_size = 0;
        timestamp = 0;

#if (NGX_WIN32)
        {
            LONG  lo, hi;

            lo = 0;
            hi = 0;
            lo = SetFilePointer(rctx->file.fd, lo, &hi, FILE_END);
            file_size = (lo == INVALID_SET_FILE_POINTER ?
                         (off_t) -1 : (off_t) hi << 32 | (off_t) lo);
        }
#else
        file_size = lseek(rctx->file.fd, 0, SEEK_END);
#endif
        if (file_size == (off_t) -1) {
            ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
                          "record: %V seek failed", &rracf->id);
            goto done;
        }

        if (file_size < 4) {
            goto done;
        }

        if (ngx_read_file(&rctx->file, buf, 4, file_size - 4) != 4) {
            ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
                          "record: %V tag size read failed", &rracf->id);
            goto done;
        }

        p = (u_char *) &tag_size;
        p[0] = buf[3];
        p[1] = buf[2];
        p[2] = buf[1];
        p[3] = buf[0];

        if (tag_size == 0 || tag_size + 4 > file_size) {
            file_size = 0;
            goto done;
        }

        if (ngx_read_file(&rctx->file, buf, 8, file_size - tag_size - 4) != 8)
        {
            ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
                          "record: %V tag read failed", &rracf->id);
            goto done;
        }

        p = (u_char *) &mlen;
        p[0] = buf[3];
        p[1] = buf[2];
        p[2] = buf[1];
        p[3] = 0;

        if (tag_size != mlen + 11) {
            ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
                          "record: %V tag size mismatch: "
                          "tag_size=%uD, mlen=%uD", &rracf->id, tag_size, mlen);
            goto done;
        }

        p = (u_char *) &timestamp;
        p[3] = buf[7];
        p[0] = buf[6];
        p[1] = buf[5];
        p[2] = buf[4];

done:
        rctx->file.offset = file_size;
        rctx->time_shift = timestamp;

        ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                       "record: append offset=%O, time=%uD, tag_size=%uD",
                       file_size, timestamp, tag_size);
    }

    return NGX_OK;
}
Beispiel #28
0
static ngx_int_t
ngx_conf_read_token(ngx_conf_t *cf)
{
    u_char      *start, ch, *src, *dst;
    off_t        file_size;
    size_t       len;
    ssize_t      n, size;
    ngx_uint_t   found, need_space, last_space, sharp_comment, variable;
    ngx_uint_t   quoted, s_quoted, d_quoted, start_line;
    ngx_str_t   *word;
    ngx_buf_t   *b;

    found = 0;
    need_space = 0;
    last_space = 1;
    sharp_comment = 0;
    variable = 0;
    quoted = 0;
    s_quoted = 0;
    d_quoted = 0;

    cf->args->nelts = 0;
    b = cf->conf_file->buffer;
    start = b->pos;
    start_line = cf->conf_file->line;
//Means we have read at which line!,always start the first line when we open the file!!

    file_size = ngx_file_size(&cf->conf_file->file.info);

    for ( ;; ) {
	//b->pos point to the first character we need to parse
	//b->last point to the last character we have put into the buffer!!!
        if (b->pos >= b->last) { // Means the we need to read more data into the buffer!!! 

            if (cf->conf_file->file.offset >= file_size) { //we get the config file's end!!!

                if (cf->args->nelts > 0) {

                    if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
                        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                           "unexpected end of parameter, "
                                           "expecting \";\"");
                        return NGX_ERROR;
                    }

                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                  "unexpected end of file, "
                                  "expecting \";\" or \"}\"");
                    return NGX_ERROR;
                }

                return NGX_CONF_FILE_DONE;
            }

            len = b->pos - start;  //At the beginning,start is zero pos,we must read a whole block or command_line!!!

            if (len == NGX_CONF_BUFFER) {
                cf->conf_file->line = start_line;

                if (d_quoted) {
                    ch = '"';

                } else if (s_quoted) {
                    ch = '\'';

                } else {
                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                       "too long parameter \"%*s...\" started",
                                       10, start);
                    return NGX_ERROR;
                }

                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "too long parameter, probably "
                                   "missing terminating \"%c\" character", ch);
                return NGX_ERROR;
            }

            if (len) { 
			//if the len is buffer has some config line,move the data to the b->start!
                ngx_memmove(b->start, start, len);
            }

            size = (ssize_t) (file_size - cf->conf_file->file.offset);

            if (size > b->end - (b->start + len)) {
                size = b->end - (b->start + len);
            }
			//size no more than buffer_size 4096
            n = ngx_read_file(&cf->conf_file->file, b->start + len, size,cf->conf_file->file.offset);

            if (n == NGX_ERROR) {
                return NGX_ERROR;
            }

            if (n != size) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   ngx_read_file_n " returned "
                                   "only %z bytes instead of %z",
                                   n, size);
                return NGX_ERROR;
            }

            b->pos = b->start + len; //point to the first haven't parsed character!
            b->last = b->pos + n;
            start = b->start; //memmove,so we start a new posistion!!
        }

        ch = *b->pos++; //pos point to the first haven't parsed character!!

        if (ch == LF) {  //judge the char whether is line feed!!
            cf->conf_file->line++;

            if (sharp_comment) {
                sharp_comment = 0;
            }
        }

        if (sharp_comment){
		//Does the this line started with "#",so the subsequent char need to omit!!!
            continue;
        }

        if (quoted) {
		//If quoted mark,we continue,we need to read another quote!!
            quoted = 0;
            continue;
        }

        if (need_space) {
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
                last_space = 1;
                need_space = 0;
                continue;
            }

            if (ch == ';') {
                return NGX_OK;
            }

            if (ch == '{') {
                return NGX_CONF_BLOCK_START;
            }

            if (ch == ')') {
                last_space = 1;
                need_space = 0;

            } else {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"%c\"", ch);
                 return NGX_ERROR;
            }
        }

        if (last_space) {
			//At the beginning,last_space == 1,so we
            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { 
			//omit the control space!!!
                continue;
            }

            start = b->pos - 1;//point to the start ch!!!
            start_line = cf->conf_file->line;

            switch (ch) {

		    case ';':
		    case '{':
			if (cf->args->nelts == 0){
				//";" "{}"  stat the end of command or start of a  block!!!
			    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
					       "unexpected \"%c\"", ch);
			    return NGX_ERROR;
			}

			if (ch == '{') { //If
			    return NGX_CONF_BLOCK_START;
			}

			return NGX_OK;

		    case '}':   
			if (cf->args->nelts != 0) {
			    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
					       "unexpected \"}\"");
			    return NGX_ERROR;
			}

			return NGX_CONF_BLOCK_DONE;
			//"}" stat the end of the whole Block!

		    case '#': //Means the following string are comment content util get a LF!!!
			sharp_comment = 1;
			continue;

		    case '\\': //Means '\' use for comment between command,so we need to omit it!!
			quoted = 1;
			last_space = 0;
			continue;

		    case '"':
			start++;
			d_quoted = 1; //Means we need to find another double quote!!!
			last_space = 0;
			continue;

		    case '\'':	//Means we need to find another single quote!!
			start++;
			s_quoted = 1;
			last_space = 0;
			continue;

		    default:
			last_space = 0;
           	}

        } else {
            if (ch == '{' && variable) {
                continue;
            }

            variable = 0;

            if (ch == '\\') {
                quoted = 1;
                continue;
            }

            if (ch == '$') {
                variable = 1;
                continue;
            }

            if (d_quoted) { //Means we find the another double quote!!
                if (ch == '"') {
                    d_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            } else if (s_quoted) {//Means we find the another single quote!!
                if (ch == '\'') {
                    s_quoted = 0;
                    need_space = 1;
                    found = 1;
                }

            }else if(ch == ' '|| ch== '\t' || ch == CR || ch == LF || ch == ';' || ch == '{'){
//Means we get a parameter!!!
//Means every parameter end with blank,tab or line feed or colon or brace! 
//and save the parameter to a word!!!
                last_space = 1;
                found = 1;
            }

//last_space Means previous space,last_space Means we start with a new parameter!!!
            if (found) { 						//Here,Means we have find!!
                word = ngx_array_push(cf->args); //Here, Means to alloc a space!
                if (word == NULL) {
                    return NGX_ERROR;
                }

                word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
                if (word->data == NULL) {
                    return NGX_ERROR;
                }

                for (dst = word->data, src = start, len = 0;src < b->pos - 1;len++)
                {
                    if (*src == '\\') {
                        switch (src[1]) {
                        case '"':
                        case '\'':
                        case '\\':
                            src++;
                            break;

                        case 't':
                            *dst++ = '\t';
                            src += 2;
                            continue;

                        case 'r':
                            *dst++ = '\r';
                            src += 2;
                            continue;

                        case 'n':
                            *dst++ = '\n';
                            src += 2;
                            continue;
                        }

                    }
                    *dst++ = *src++;
                }
                *dst = '\0';	//add the terminal char
                word->len = len;

                if (ch == ';') {
                    return NGX_OK;
                }

                if (ch == '{') {
                    return NGX_CONF_BLOCK_START;
                }

                found = 0;
            }
        }
    }
}
Beispiel #29
0
static void
ngx_http_push_stream_publisher_body_handler(ngx_http_request_t *r)
{
    ngx_str_t                              *id;
    ngx_str_t                              *event_id, *event_type;
    ngx_http_push_stream_loc_conf_t        *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module);
    ngx_buf_t                              *buf = NULL;
    ngx_chain_t                            *chain;
    ngx_http_push_stream_channel_t         *channel;
    ssize_t                                 n;
    off_t                                   len;

	u_char								   *push_text_body=NULL;

    // check if body message wasn't empty
    if (r->headers_in.content_length_n <= 0) {
        ngx_log_error(NGX_LOG_ERR, (r)->connection->log, 0, "push stream module: Post request was sent with no message");
        ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_EMPTY_POST_REQUEST_MESSAGE);
        return;
    }

    // get and check if has access to request body
    NGX_HTTP_PUSH_STREAM_CHECK_AND_FINALIZE_REQUEST_ON_ERROR(r->request_body->bufs, NULL, r, "push stream module: unexpected publisher message request body buffer location. please report this to the push stream module developers.");

    // get and check channel id value
    id = ngx_http_push_stream_get_channel_id(r, cf);
    NGX_HTTP_PUSH_STREAM_CHECK_AND_FINALIZE_REQUEST_ON_ERROR(id, NULL, r, "push stream module: something goes very wrong, arrived on ngx_http_push_stream_publisher_body_handler without channel id");
    NGX_HTTP_PUSH_STREAM_CHECK_AND_FINALIZE_REQUEST_ON_ERROR(id, NGX_HTTP_PUSH_STREAM_UNSET_CHANNEL_ID, r, "push stream module: something goes very wrong, arrived on ngx_http_push_stream_publisher_body_handler without channel id");
    NGX_HTTP_PUSH_STREAM_CHECK_AND_FINALIZE_REQUEST_ON_ERROR(id, NGX_HTTP_PUSH_STREAM_TOO_LARGE_CHANNEL_ID, r, "push stream module: something goes very wrong, arrived on ngx_http_push_stream_publisher_body_handler with channel id too large");

    // copy request body to a memory buffer
    buf = ngx_create_temp_buf(r->pool, r->headers_in.content_length_n + 1);
    NGX_HTTP_PUSH_STREAM_CHECK_AND_FINALIZE_REQUEST_ON_ERROR(buf, NULL, r, "push stream module: cannot allocate memory for read the message");
    ngx_memset(buf->start, '\0', r->headers_in.content_length_n + 1);

    chain = r->request_body->bufs;
    while ((chain != NULL) && (chain->buf != NULL)) {
        len = ngx_buf_size(chain->buf);
        // if buffer is equal to content length all the content is in this buffer
        if (len >= r->headers_in.content_length_n) {
            buf->start = buf->pos;
            buf->last = buf->pos;
            len = r->headers_in.content_length_n;
        }

        if (chain->buf->in_file) {
            n = ngx_read_file(chain->buf->file, buf->start, len, 0);
            if (n == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_ERR, (r)->connection->log, 0, "push stream module: cannot read file with request body");
                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                return;
            }
            buf->last = buf->last + len;
            ngx_delete_file(chain->buf->file->name.data);
            chain->buf->file->fd = NGX_INVALID_FILE;
        } else {
            buf->last = ngx_copy(buf->start, chain->buf->pos, len);
        }

        chain = chain->next;
        buf->start = buf->last;
    }

    event_id = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_EVENT_ID);
    event_type = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_EVENT_TYPE);

	push_text_body = ngx_http_push_stream_str_replace(buf->pos, (u_char *)"\r\n", (u_char *)"", 0, r->pool);
	push_text_body = ngx_http_push_stream_str_replace(push_text_body, (u_char *)"\n", (u_char *)"", 0, r->pool);
	push_text_body = ngx_http_push_stream_str_replace(push_text_body, (u_char *)"\t", (u_char *)"", 0, r->pool);

	channel = ngx_http_push_stream_add_msg_to_channel(r, id, push_text_body, ngx_strlen(push_text_body), event_id, event_type, r->pool);
	//channel = ngx_http_push_stream_add_msg_to_channel(r, id, buf->pos, ngx_buf_size(buf), event_id, event_type, r->pool);
    if (channel == NULL) {
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return;
    }

    if (cf->channel_info_on_publish) {
        ngx_http_push_stream_send_response_channel_info(r, channel);
    } else {
        ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_OK, NULL);
    }
    ngx_http_finalize_request(r, NGX_OK);
    return;
}
static ngx_int_t
ngx_http_spdy_serverpush_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
   
    off_t                       size;
    ngx_buf_t                  *b;
    ngx_chain_t                *cl, *ll, *out, **ln;
    ngx_http_spdy_stream_t     *stream;
    ngx_http_spdy_out_frame_t  *frame;
   
    ngx_output_chain_ctx_t       *ctx;
    ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
    ngx_http_set_ctx(r, ctx, ngx_http_spdy_serverpush_filter_module);
    //ngx_chain_t *myChain=NULL;
    ngx_http_static_handler(r);
    stream =myStream;
    if (stream == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "spdy body filter \"%V?%V\"", &r->uri, &r->args);

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "Data in server Push ");

    if (myChain == NULL || r->header_only) {

	ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "Ending");
        if (stream->waiting) {
            return NGX_AGAIN;
        }

        r->connection->buffered &= ~NGX_SPDY_WRITE_BUFFERED;

        return NGX_OK;
    }

    size = 0;
    ln = &out;
    ll = myChain;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "into for ");
    for ( ;; ) {
        b = ll->buf;
//#if 1
	if(b->file)
	{	
		ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "file detected push : %d",(b->file_last-b->file_pos));
		ngx_int_t my_size = b->file_last-b->file_pos;
		u_char* my_buf = ngx_pcalloc(r->pool,sizeof(u_char)*my_size);
		ngx_read_file(b->file, my_buf, my_size, 0);
		b->start = my_buf;
		b->pos = my_buf;
		b->last = my_buf+my_size;//+NGX_SPDY_FRAME_HEADER_SIZE;

	}
        if (ngx_buf_size(b) == 0 && !ngx_buf_special(b)) {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                          "zero size buf in spdy body filter "
                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
                          b->temporary,
                          b->recycled,
                          b->in_file,
                          b->start,
                          b->pos,
                          b->last,
                          b->file,
                          b->file_pos,
                          b->file_last);

            ngx_debug_point();
            return NGX_ERROR;
        }
//#endif
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "out of for");
        cl = ngx_alloc_chain_link(r->pool);
        if (cl == NULL) {
            return NGX_ERROR;
        }
	
        size += ngx_buf_size(b);
	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "Size %d ",size);
        
        cl->buf = b;

        *ln = cl;
        ln = &cl->next;

        if (ll->next == NULL) {
            break;
        }

        ll = ll->next;
    }

    if (size > NGX_SPDY_MAX_FRAME_SIZE) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "FIXME: chain too big in spdy filter: %O", size);
        return NGX_ERROR;
    }
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "ONE ");
    frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size,
                                                b->last_buf, out, cl);

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "FOUR ");
    if (frame == NULL) {
        return NGX_ERROR;
    }

    ngx_http_spdy_queue_frame(stream->connection, frame);

    stream->waiting++;

    r->main->blocked++;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "Data in server Push end sai ram ");
    ngx_http_spdy_serverpush_filter_send(r->connection, stream);
    return ngx_http_next_body_filter(r,in);
}