static ngx_int_t websocket_publish(full_subscriber_t *fsub, ngx_str_t *msg_str) { nchan_msg_t msg; ngx_buf_t buf; static ngx_str_t nopublishing = ngx_string("Publishing not allowed."); if(!fsub->sub.cf->pub.websocket) { return websocket_send_close_frame(fsub, CLOSE_POLICY_VIOLATION, &nopublishing); } ngx_http_request_t *r = fsub->request; init_msg_buf(&buf); buf.start = msg_str->data; buf.pos = buf.start; buf.end = buf.start + msg_str->len; buf.last = buf.end; ngx_memzero(&msg, sizeof(msg)); msg.buf=&buf; if(r->headers_in.content_type) { msg.content_type.data = r->headers_in.content_type->value.data; msg.content_type.len = r->headers_in.content_type->value.len; } fsub->sub.cf->storage_engine->publish(fsub->publish_channel_id, &msg, fsub->sub.cf, (callback_pt )websocket_publish_callback, fsub); return NGX_OK; }
static ngx_int_t websocket_publish(full_subscriber_t *fsub, ngx_buf_t *buf) { static ngx_str_t nopublishing = ngx_string("Publishing not allowed."); static ngx_str_t POST_REQUEST_STRING = {4, (u_char *)"POST "}; if(!fsub->sub.cf->pub.websocket) { return websocket_send_close_frame(fsub, CLOSE_POLICY_VIOLATION, &nopublishing); } #if (NGX_DEBUG_POOL) ERR("ws request pool size: %V", ngx_http_debug_pool_str(fsub->sub.request->pool)); #endif ngx_http_complex_value_t *publisher_upstream_request_url_ccv; publisher_upstream_request_url_ccv = fsub->sub.cf->publisher_upstream_request_url; if(publisher_upstream_request_url_ccv == NULL) { websocket_publish_continue(fsub, buf); } else { nchan_pub_upstream_stuff_t *psr_stuff; ngx_http_post_subrequest_t *psr; nchan_pub_upstream_data_t *psrd; ngx_http_request_t *r = fsub->sub.request; ngx_http_request_t *sr; ngx_http_request_body_t *fakebody; ngx_chain_t *fakebody_chain; ngx_buf_t *fakebody_buf; size_t sz; if(!fsub->upstream_stuff) { if((psr_stuff = ngx_palloc(r->pool, sizeof(*psr_stuff))) == NULL) { ERR("can't allocate memory for publisher auth subrequest"); websocket_respond_status(&fsub->sub, NGX_HTTP_INTERNAL_SERVER_ERROR, NULL); return NGX_ERROR; } fsub->upstream_stuff = psr_stuff; psr = &psr_stuff->psr; psr->data = &psr_stuff->psr_data; psr->handler = websocket_publisher_upstream_handler; psr_stuff->psr_data.fsub = fsub; psr_stuff->psr_data.tmp_pool = NULL; ngx_http_complex_value(r, publisher_upstream_request_url_ccv, &psr_stuff->psr_data.upstream_request_url); } psrd = &fsub->upstream_stuff->psr_data; psr = &fsub->upstream_stuff->psr; if(psrd->tmp_pool) { //previous upstream request's pool ngx_destroy_pool(psrd->tmp_pool); psrd->tmp_pool = NULL; } psrd->buf = *buf; psrd->original_pool = r->pool; psrd->original_cleanup = r->cleanup; r->cleanup = NULL; psrd->tmp_pool = ngx_create_pool(NCHAN_WS_UPSTREAM_TMP_POOL_SIZE, r->connection->log); r->pool = psrd->tmp_pool; //ERR("request %p tmp pool %p", r, r->pool); fakebody = ngx_pcalloc(r->pool, sizeof(*fakebody)); if(ngx_buf_size(buf) > 0) { fakebody_chain = ngx_palloc(r->pool, sizeof(*fakebody_chain)); fakebody_buf = ngx_palloc(r->pool, sizeof(*fakebody_buf)); fakebody->bufs = fakebody_chain; fakebody_chain->next = NULL; fakebody_chain->buf = fakebody_buf; init_msg_buf(fakebody_buf); //just copy the buffer contents. it's inefficient but I don't care at the moment. //this can and should be optimized later sz = ngx_buf_size(buf); fakebody_buf->start = ngx_palloc(r->pool, sz); //huuh? ngx_memcpy(fakebody_buf->start, buf->start, sz); fakebody_buf->end = fakebody_buf->start + sz; fakebody_buf->pos = fakebody_buf->start; fakebody_buf->last = fakebody_buf->end; } else { sz = 0; } ngx_http_subrequest(r, &psrd->upstream_request_url, NULL, &sr, psr, NGX_HTTP_SUBREQUEST_IN_MEMORY); nchan_adjust_subrequest(sr, NGX_HTTP_POST, &POST_REQUEST_STRING, fakebody, sz, NULL); /* //http request sudden close cleanup if((psrd->cln = ngx_http_cleanup_add(sr, 0)) == NULL) { ERR("Unable to add request cleanup for websocket upstream request"); return NGX_ERROR; } psrd->cln->data = fsub; psrd->cln->handler = (ngx_http_cleanup_pt )sudden_upstream_request_abort_handler; */ } return NGX_OK; }