//print information about a channel ngx_int_t nchan_channel_info(ngx_http_request_t *r, ngx_uint_t messages, ngx_uint_t subscribers, time_t last_seen, nchan_msg_id_t *msgid) { ngx_buf_t *b; ngx_str_t *content_type; ngx_str_t *accept_header = NULL; if(r->headers_in.accept) { accept_header = &r->headers_in.accept->value; } b = nchan_channel_info_buf(accept_header, messages, subscribers, last_seen, msgid, &content_type); return nchan_respond_membuf(r, NGX_HTTP_OK, content_type, b, 0); }
static ngx_int_t websocket_publish_callback(ngx_int_t status, nchan_channel_t *ch, full_subscriber_t *fsub) { time_t last_seen = 0; ngx_uint_t subscribers = 0; ngx_uint_t messages = 0; nchan_msg_id_t *msgid = NULL; ngx_http_request_t *r = fsub->sub.request; ngx_str_t *accept_header = NULL; ngx_buf_t *tmp_buf; nchan_buf_and_chain_t *bc = nchan_bufchain_pool_reserve(fsub->ctx->bcp, 1); if(ch) { subscribers = ch->subscribers; last_seen = ch->last_seen; messages = ch->messages; msgid = &ch->last_published_msg_id; } if(websocket_release(&fsub->sub, 0) == NGX_ABORT) { //zombie publisher //nothing more to do, we're finished here return NGX_OK; } switch(status) { case NCHAN_MESSAGE_QUEUED: case NCHAN_MESSAGE_RECEIVED: if(fsub->sub.cf->sub.websocket) { //don't reply with status info, this websocket is used for subscribing too, //so it should only be recieving messages return NGX_OK; } if(r->headers_in.accept) { accept_header = &r->headers_in.accept->value; } tmp_buf = nchan_channel_info_buf(accept_header, messages, subscribers, last_seen, msgid, NULL); ngx_memcpy(&bc->buf, tmp_buf, sizeof(*tmp_buf)); bc->buf.last_buf=1; nchan_output_filter(fsub->sub.request, websocket_frame_header_chain(fsub, WEBSOCKET_TEXT_LAST_FRAME_BYTE, ngx_buf_size((&bc->buf)), &bc->chain)); break; case NGX_ERROR: case NGX_HTTP_INTERNAL_SERVER_ERROR: assert(0); break; } return NGX_OK; }
static ngx_int_t websocket_publish_callback(ngx_int_t status, nchan_channel_t *ch, full_subscriber_t *fsub) { time_t last_seen = 0; ngx_uint_t subscribers = 0; ngx_uint_t messages = 0; ngx_http_request_t *r = fsub->request; ngx_str_t *accept_header = NULL; ngx_buf_t *tmp_buf; if(ch) { subscribers = ch->subscribers; last_seen = ch->last_seen; messages = ch->messages; } switch(status) { case NCHAN_MESSAGE_QUEUED: case NCHAN_MESSAGE_RECEIVED: if(fsub->sub.cf->sub.websocket) { //don't reply with status info, this websocket is used for subscribing too, //so it should only be recieving messages return NGX_OK; } if(r->headers_in.accept) { accept_header = &r->headers_in.accept->value; } tmp_buf = nchan_channel_info_buf(accept_header, messages, subscribers, last_seen, NULL); ngx_memcpy(&fsub->msg_buf, tmp_buf, sizeof(*tmp_buf)); fsub->msg_buf.last_buf=1; nchan_output_filter(fsub->request, websocket_frame_header_chain(fsub, WEBSOCKET_TEXT_LAST_FRAME_BYTE, ngx_buf_size((&fsub->msg_buf)))); break; case NGX_ERROR: case NGX_HTTP_INTERNAL_SERVER_ERROR: assert(0); break; } return NGX_OK; }
//print information about a channel static ngx_int_t nchan_channel_info(ngx_http_request_t *r, ngx_uint_t messages, ngx_uint_t subscribers, time_t last_seen) { ngx_buf_t *b; ngx_str_t *content_type; ngx_str_t *accept_header = NULL; if(r->headers_in.accept) { accept_header = &r->headers_in.accept->value; } b = nchan_channel_info_buf(accept_header, messages, subscribers, last_seen, &content_type); //not sure why this is needed, but content-type directly from the request can't be reliably used in the response //(it probably can, but i'm just doing it wrong) /*if(content_type != &TEXT_PLAIN) { ERR("WTF why must i do this %p %V", content_type, content_type); content_type_copy.len = content_type->len; content_type_copy.data = ngx_palloc(r->pool, content_type_copy.len); assert(content_type_copy.data); ngx_memcpy(content_type_copy.data, content_type->data, content_type_copy.len); content_type = &content_type_copy; }*/ return nchan_respond_membuf(r, NGX_HTTP_OK, content_type, b, 0); }