ngx_buf_t *nchan_channel_info_buf(ngx_str_t *accept_header, ngx_uint_t messages, ngx_uint_t subscribers, time_t last_seen, ngx_str_t **generated_content_type) { ngx_buf_t *b = &channel_info_buf; ngx_uint_t len; const ngx_str_t *format = &NCHAN_CHANNEL_INFO_PLAIN; time_t time_elapsed = ngx_time() - last_seen; ngx_memcpy(&channel_info_content_type, &TEXT_PLAIN, sizeof(TEXT_PLAIN));; b->start = channel_info_buf_str; b->pos = b->start; b->last_buf = 1; b->last_in_chain = 1; b->flush = 1; b->memory = 1; if(accept_header) { //lame content-negotiation (without regard for qvalues) u_char *accept = accept_header->data; size_t len = accept_header->len; size_t rem; u_char *cur = accept; u_char *priority=&accept[len-1]; for(rem=len; (cur = ngx_strnstr(cur, "text/", rem))!=NULL; cur += sizeof("text/")-1) { rem=len - ((size_t)(cur-accept)+sizeof("text/")-1); if(ngx_strncmp(cur+sizeof("text/")-1, "plain", rem<5 ? rem : 5)==0) { if(priority) { format = &NCHAN_CHANNEL_INFO_PLAIN; priority = cur+sizeof("text/")-1; //content-type is already set by default } } nchan_match_channel_info_subtype(sizeof("text/")-1, cur, rem, &priority, &format, &channel_info_content_type); } cur = accept; for(rem=len; (cur = ngx_strnstr(cur, "application/", rem))!=NULL; cur += sizeof("application/")-1) { rem=len - ((size_t)(cur-accept)+sizeof("application/")-1); nchan_match_channel_info_subtype(sizeof("application/")-1, cur, rem, &priority, &format, &channel_info_content_type); } } if(generated_content_type) { *generated_content_type = &channel_info_content_type; } len = format->len - 8 - 1 + 3*NGX_INT_T_LEN; //minus 8 sprintf assert(len < 512); b->last = ngx_sprintf(b->start, (char *)format->data, messages, last_seen==0 ? -1 : (ngx_int_t) time_elapsed, subscribers); b->end = b->last; return b; }
ngx_buf_t *nchan_channel_info_buf(ngx_str_t *accept_header, ngx_uint_t messages, ngx_uint_t subscribers, time_t last_seen, nchan_msg_id_t *last_msgid, ngx_str_t **generated_content_type) { ngx_buf_t *b = &channel_info_buf; ngx_uint_t len; const ngx_str_t *format = &NCHAN_CHANNEL_INFO_PLAIN; time_t time_elapsed = ngx_time() - last_seen; static nchan_msg_id_t zero_msgid = NCHAN_ZERO_MSGID; if(!last_msgid) { last_msgid = &zero_msgid; } ngx_memcpy(&channel_info_content_type, &NCHAN_CONTENT_TYPE_TEXT_PLAIN, sizeof(NCHAN_CONTENT_TYPE_TEXT_PLAIN)); b->start = channel_info_buf_str; b->pos = b->start; b->last_buf = 1; b->last_in_chain = 1; b->flush = 1; b->memory = 1; if(accept_header) { //lame content-negotiation (without regard for qvalues) u_char *accept = accept_header->data; len = accept_header->len; size_t rem; u_char *cur = accept; u_char *priority=&accept[len-1]; for(rem=len; (cur = ngx_strnstr(cur, "text/", rem))!=NULL; cur += sizeof("text/")-1) { rem=len - ((size_t)(cur-accept)+sizeof("text/")-1); if(ngx_strncmp(cur+sizeof("text/")-1, "plain", rem<5 ? rem : 5)==0) { if(priority) { format = &NCHAN_CHANNEL_INFO_PLAIN; priority = cur+sizeof("text/")-1; //content-type is already set by default } } nchan_match_channel_info_subtype(sizeof("text/")-1, cur, rem, &priority, &format, &channel_info_content_type); } cur = accept; for(rem=len; (cur = ngx_strnstr(cur, "application/", rem))!=NULL; cur += sizeof("application/")-1) { rem=len - ((size_t)(cur-accept)+sizeof("application/")-1); nchan_match_channel_info_subtype(sizeof("application/")-1, cur, rem, &priority, &format, &channel_info_content_type); } } if(generated_content_type) { *generated_content_type = &channel_info_content_type; } len = format->len - 8 - 1 + 3*NGX_INT_T_LEN; //minus 8 sprintf if(len > 512) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "NCHAN: Channel info string too long: max: 512, is: %i", len); len = 512; } b->last = ngx_sprintf(b->start, (char *)format->data, messages, last_seen==0 ? -1 : (ngx_int_t) time_elapsed, subscribers, msgid_to_str(last_msgid)); b->end = b->last; return b; }