Example #1
0
ngx_int_t nchan_msg_buf_open_fd_if_needed(ngx_buf_t *buf, ngx_file_t *file, ngx_http_request_t *r) {
  if(buf->in_file) {
    //open file fd if necessary
    if(!file) {
      if(r) {
        if((file = ngx_pcalloc(r->pool, sizeof(*file))) == NULL) {
          ERR("couldn't allocate memory for file struct while responding with msg");
          return NGX_ERROR;
        }
      }
      else {
        //no file given, can't allocate from NULL pool
        return NGX_ERROR;
      }
    }
    
    ngx_memcpy(file, buf->file, sizeof(*file));
    if(file->fd == NGX_INVALID_FILE) {
      file->fd = nchan_fdcache_get(&file->name);
      if(file->fd == NGX_INVALID_FILE) {
        ERR("can't create output chain, file in buffer won't open");
        return NGX_ERROR;
      }
    }
    buf->file = file;
  }
  return NGX_OK;
}
Example #2
0
static ngx_int_t es_respond_message(subscriber_t *sub,  nchan_msg_t *msg) {
  static ngx_str_t        terminal_newlines=ngx_string("\n\n");
  full_subscriber_t      *fsub = (full_subscriber_t  *)sub;
  u_char                 *cur = NULL, *last = NULL;
  ngx_buf_t              *msg_buf = msg->buf;
  ngx_buf_t               databuf;
  ngx_pool_t             *pool;
  nchan_buf_and_chain_t  *bc;
  size_t                  len;
  ngx_chain_t            *first_link = NULL, *last_link = NULL;
  ngx_file_t             *msg_file;
  ngx_int_t               rc;
  nchan_request_ctx_t    *ctx = ngx_http_get_module_ctx(fsub->sub.request, nchan_module);
  
  
  ctx->prev_msg_id = fsub->sub.last_msgid;
  update_subscriber_last_msg_id(sub, msg);
  ctx->msg_id = fsub->sub.last_msgid;
  
  es_ensure_headers_sent(fsub);
  
  DBG("%p output msg to subscriber", sub);
  
  pool = ngx_create_pool(NGX_DEFAULT_LINEBREAK_POOL_SIZE, ngx_cycle->log);
  assert(pool);
  
  ngx_memcpy(&databuf, msg_buf, sizeof(*msg_buf));
  databuf.last_buf = 0;
  
  if(!databuf.in_file) {
    cur = msg_buf->start;
    last = msg_buf->end;
    do {
      databuf.start = cur;
      databuf.pos = cur;
      databuf.end = last;
      databuf.last = last;
      
      cur = ngx_strlchr(cur, last, '\n');
      if(cur == NULL) {
        //sweet, no newlines!
        //let's get out of this hellish loop
        databuf.end = last;
        databuf.last = last;
        cur = last + 1;
      }
      else {
        cur++; //include the newline
        databuf.end = cur;
        databuf.last = cur;
      }
      
      create_dataline_bufchain(pool, &first_link, &last_link, &databuf);
      
    } while(cur <= last);
  } 
  else {
    //great, we've gotta scan this whole damn file for line breaks.
    //EventStream really isn't designed for large chunks of data
    off_t       fcur, flast;
    ngx_fd_t    fd;
    int         chr_int;
    FILE       *stream;
    
    msg_file = ngx_palloc(pool, sizeof(*msg_file));
    databuf.file = msg_file;
    ngx_memcpy(msg_file, msg_buf->file, sizeof(*msg_file));
    
    if(msg_file->fd == NGX_INVALID_FILE) {
      msg_file->fd = nchan_fdcache_get(&msg_file->name);
    }
    fd = msg_file->fd;
    
    stream = fdopen(dup(fd), "r");
    
    fcur = databuf.file_pos;
    flast = databuf.file_last;
    
    fseek(stream, fcur, SEEK_SET);
    
    do {
      databuf.file_pos = fcur;
      databuf.file_last = flast;
      
      //getc that shit
      for(;;) {
        chr_int = getc(stream);
        if(chr_int == EOF) {
          break;
        }
        else if(chr_int == (int )'\n') {
          fcur++;
          break;
        }
        fcur++;
      }
      
      databuf.file_last = fcur;
      create_dataline_bufchain(pool, &first_link, &last_link, &databuf);
      
    } while(fcur < flast);
    
    fclose(stream);
  }
  
  //now 2 newlines at the end
  if(last_link) {
    bc = ngx_palloc(pool, sizeof(*bc));
    last_link->next=&bc->chain;
    ngx_init_set_membuf(&bc->buf, terminal_newlines.data, terminal_newlines.data + terminal_newlines.len);
    
    bc->buf.flush = 1;
    bc->buf.last_buf = 0;
    
    bc->chain.next = NULL;
    bc->chain.buf = &bc->buf;
    
    last_link = &bc->chain;
  }
  //okay, this crazy data chain is finished. now how about the mesage tag?
  len = 10 + 2*NGX_INT_T_LEN;
  bc = ngx_palloc(pool, sizeof(*bc) + len);
  ngx_memzero(&bc->buf, sizeof(bc->buf));
  cur = (u_char *)&bc[1];
  ngx_init_set_membuf(&bc->buf, cur, ngx_snprintf(cur, len, "id: %V\n", msgid_to_str(&sub->last_msgid)));

  bc->chain.buf = &bc->buf;
  bc->chain.next = first_link;
  first_link=&bc->chain;
  
  
  rc = nchan_output_filter(fsub->sub.request, first_link);
  
  ngx_destroy_pool(pool);
  
  return rc;
}