Exemplo n.º 1
0
static ngx_int_t chunked_respond_message(subscriber_t *sub,  nchan_msg_t *msg) {
  static u_char           chunk_start[15]; //that's enough
  static u_char          *chunk_end=(u_char *)"\r\n";
  
  full_subscriber_t      *fsub = (full_subscriber_t  *)sub;
  ngx_buf_t              *msg_buf = msg->buf;
  ngx_int_t               rc;
  nchan_request_ctx_t    *ctx = ngx_http_get_module_ctx(fsub->sub.request, nchan_module);
  
  if (ngx_buf_size(msg_buf) == 0) {
    //empty messages are skipped, because a zero-length chunk finalizes the request
    return NGX_OK;
  }
  
  nchan_buf_and_chain_t   bc[3];
  
  bc[0].chain.buf = &bc[0].buf;
  bc[0].chain.next = &bc[1].chain;
  
  ngx_memzero(&bc[0].buf, sizeof(ngx_buf_t));
  bc[0].buf.memory = 1;
  bc[0].buf.start = chunk_start;
  bc[0].buf.pos = chunk_start;
  bc[0].buf.end = ngx_snprintf(chunk_start, 15, "%xi\r\n", ngx_buf_size(msg_buf));
  bc[0].buf.last = bc[0].buf.end;
  
  bc[1].chain.buf = &bc[1].buf;
  bc[1].chain.next = &bc[2].chain;
  
  ngx_memcpy(&bc[1].buf, msg_buf, sizeof(*msg_buf));
  bc[1].buf.last_buf = 0;
  bc[1].buf.last_in_chain = 0;
  bc[1].buf.flush = 0;
  
  bc[2].chain.buf = &bc[2].buf;
  bc[2].chain.next = NULL;
  
  ngx_memzero(&bc[2].buf, sizeof(ngx_buf_t));
  bc[2].buf.start = chunk_end;
  bc[2].buf.pos = chunk_end;
  bc[2].buf.end = chunk_end + 2;
  bc[2].buf.last = bc[2].buf.end;
  bc[2].buf.memory = 1;
  bc[2].buf.last_buf = 0;
  bc[2].buf.last_in_chain = 1;
  bc[2].buf.flush = 1;
  
  ctx->prev_msg_id = fsub->sub.last_msgid;
  update_subscriber_last_msg_id(sub, msg);
  ctx->msg_id = fsub->sub.last_msgid;
  
  chunked_ensure_headers_sent(fsub);
  
  DBG("%p output msg to subscriber", sub);
  
  rc = nchan_output_filter(fsub->sub.request, &bc[0].chain);
  
  return rc;
}
Exemplo n.º 2
0
static ngx_int_t chunked_enqueue(subscriber_t *sub) {
  ngx_int_t           rc;
  full_subscriber_t  *fsub = (full_subscriber_t *)sub;
  DBG("%p output status to subscriber", sub);
  rc = longpoll_enqueue(sub);
  fsub->data.finalize_request = 0;
  chunked_ensure_headers_sent(fsub);
  sub->enqueued = 1;
  return rc;
}
Exemplo n.º 3
0
static ngx_int_t chunked_respond_status(subscriber_t *sub, ngx_int_t status_code, const ngx_str_t *status_line){
  nchan_buf_and_chain_t     bc;
  ngx_chain_t              *chain = NULL;
  
  full_subscriber_t        *fsub = (full_subscriber_t  *)sub;
  
  if(chain == NULL) {
    bc.chain.buf=&bc.buf;
    bc.chain.next=NULL;
    ngx_memzero(&bc.buf, sizeof(ngx_buf_t));
    bc.buf.last_buf = 1;
    bc.buf.last_in_chain = 1;
    bc.buf.flush = 1;
    bc.buf.memory = 1;
    chain = &bc.chain;
  }
  
  bc.buf.start = (u_char *)"0\r\n\r\n";
  bc.buf.end = bc.buf.start + 5;
  bc.buf.pos = bc.buf.start;
  bc.buf.last = bc.buf.end;
  
  if(status_code == NGX_HTTP_NO_CONTENT || status_code == NGX_HTTP_NOT_MODIFIED) {
    //ignore
    return NGX_OK;
  }
  
  if(fsub->data.shook_hands == 0 && status_code >= 400 && status_code <600) {
    nchan_respond_status(sub->request, status_code, status_line, 1);
    return NGX_OK;
  }
  
  chunked_ensure_headers_sent(fsub);
  
  nchan_output_filter(fsub->sub.request, chain);
  
  if(status_code >=400 && status_code <599) {
    fsub->data.cln->handler = (ngx_http_cleanup_pt )empty_handler;
    fsub->sub.request->keepalive=0;
    fsub->data.finalize_request=1;
    sub->fn->dequeue(sub);
  }

  return NGX_OK;
}
Exemplo n.º 4
0
static ngx_int_t chunked_respond_status(subscriber_t *sub, ngx_int_t status_code, const ngx_str_t *status_line){
  nchan_buf_and_chain_t     bc;
  ngx_chain_t              *chain = NULL;
  
  full_subscriber_t        *fsub = (full_subscriber_t  *)sub;
  
  if(chain == NULL) {
    bc.chain.buf=&bc.buf;
    bc.chain.next=NULL;
    ngx_memzero(&bc.buf, sizeof(ngx_buf_t));
    bc.buf.last_buf = 1;
    bc.buf.last_in_chain = 1;
    bc.buf.flush = 1;
    bc.buf.memory = 1;
    chain = &bc.chain;
  }
  
  bc.buf.start = (u_char *)"0\r\n\r\n";
  bc.buf.end = bc.buf.start + 5;
  bc.buf.pos = bc.buf.start;
  bc.buf.last = bc.buf.end;
  
  if(status_code == NGX_HTTP_NO_CONTENT || (status_code == NGX_HTTP_NOT_MODIFIED && !status_line)) {
    //ignore
    return NGX_OK;
  }
  
  if(fsub->data.shook_hands == 0 && status_code >= 400 && status_code < 600) {
    nchan_respond_status(sub->request, status_code, status_line, 1);
    return NGX_OK;
  }
  
  chunked_ensure_headers_sent(fsub);
  
  nchan_output_filter(fsub->sub.request, chain);
  
  subscriber_maybe_dequeue_after_status_response(fsub, status_code);

  return NGX_OK;
}
Exemplo n.º 5
0
static ngx_int_t chunked_respond_message(subscriber_t *sub,  nchan_msg_t *msg) {
  full_subscriber_t      *fsub = (full_subscriber_t  *)sub;
  nchan_request_ctx_t    *ctx = ngx_http_get_module_ctx(fsub->sub.request, ngx_nchan_module);
  chunksizebuf_t         *chunksizebuf = nchan_reuse_queue_push(ctx->output_str_queue);
  u_char                 *chunk_start = &chunksizebuf->chr[0];
  static u_char          *chunk_end=(u_char *)"\r\n";
  ngx_file_t             *file_copy;
  nchan_buf_and_chain_t  *bc = nchan_bufchain_pool_reserve(ctx->bcp, 3);
  ngx_chain_t            *chain;
  ngx_buf_t              *buf, *msg_buf = &msg->buf;
  ngx_int_t               rc;
  
  if(fsub->data.timeout_ev.timer_set) {
    ngx_del_timer(&fsub->data.timeout_ev);
    ngx_add_timer(&fsub->data.timeout_ev, sub->cf->subscriber_timeout * 1000);
  }
  
  ctx->prev_msg_id = fsub->sub.last_msgid;
  update_subscriber_last_msg_id(sub, msg);
  ctx->msg_id = fsub->sub.last_msgid;
  
  if (ngx_buf_size(msg_buf) == 0) {
    //empty messages are skipped, because a zero-length chunk finalizes the request
    return NGX_OK;
  }
  
  //chunk size
  chain = &bc->chain;
  buf = chain->buf;
  ngx_memzero(buf, sizeof(*buf));
  buf->memory = 1;
  buf->start = chunk_start;
  buf->pos = chunk_start;
  buf->end = ngx_snprintf(chunk_start, 15, "%xi\r\n", ngx_buf_size(msg_buf));
  buf->last = buf->end;
  
  //message
  chain = chain->next;
  buf = chain->buf;
  *buf = *msg_buf;
  if(buf->file) {
    file_copy = nchan_bufchain_pool_reserve_file(ctx->bcp);
    nchan_msg_buf_open_fd_if_needed(buf, file_copy, NULL);
  }
  buf->last_buf = 0;
  buf->last_in_chain = 0;
  buf->flush = 0;
  
  //trailing newlines
  chain = chain->next;
  buf = chain->buf;
  ngx_memzero(buf, sizeof(*buf));
  buf->start = chunk_end;
  buf->pos = chunk_end;
  buf->end = chunk_end + 2;
  buf->last = buf->end;
  buf->memory = 1;
  buf->last_buf = 0;
  buf->last_in_chain = 1;
  buf->flush = 1;
  
  chunked_ensure_headers_sent(fsub);
  
  DBG("%p output msg to subscriber", sub);
  
  rc = nchan_output_msg_filter(fsub->sub.request, msg, &bc->chain);
  
  return rc;
}