int fcgi_demux_response(fastcgiResponse *fr) { int fin = 0; while (fin == 0) { fastcgi_response_packet packet; /* check if we have at least one packet */ if (0 != fastcgi_get_packet(fr, &packet)) { /* no full packet */ break; } switch(packet.type) { case FCGI_STDOUT: if (packet.len == 0) break; char *c; size_t blen; if (NULL != (c = buffer_search_string_len(packet.b, CONST_STR_LEN("\r\n\r\n")))) { blen = packet.b->used - (c - packet.b->ptr) - 4; //packet.b->used = (c - packet.b->ptr) + 3; c += 4; /* point the the start of the response */ } buffer_append_string_len(fr->format_buf, c, blen); //analyze format buffer get pubsub command break; case FCGI_STDERR: if (packet.len == 0) break; break; case FCGI_END_REQUEST: fin = 1; break; default: break; } buffer_free(packet.b); } return fin; }
static int proxy_demux_response(server *srv, handler_ctx *hctx) { int fin = 0; int b; ssize_t r; plugin_data *p = hctx->plugin_data; connection *con = hctx->remote_conn; int proxy_fd = hctx->fd; /* check how much we have to read */ if (ioctl(hctx->fd, FIONREAD, &b)) { log_error_write(srv, __FILE__, __LINE__, "sd", "ioctl failed: ", proxy_fd); return -1; } if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sd", "proxy - have to read:", b); } if (b > 0) { if (hctx->response->used == 0) { /* avoid too small buffer */ buffer_prepare_append(hctx->response, b + 1); hctx->response->used = 1; } else { buffer_prepare_append(hctx->response, b); } if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) { if (errno == EAGAIN) return 0; log_error_write(srv, __FILE__, __LINE__, "sds", "unexpected end-of-file (perhaps the proxy process died):", proxy_fd, strerror(errno)); return -1; } /* this should be catched by the b > 0 above */ assert(r); hctx->response->used += r; hctx->response->ptr[hctx->response->used - 1] = '\0'; #if 0 log_error_write(srv, __FILE__, __LINE__, "sdsbs", "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":"); #endif if (0 == con->got_response) { con->got_response = 1; buffer_prepare_copy(hctx->response_header, 128); } if (0 == con->file_started) { char *c; /* search for the \r\n\r\n in the string */ if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) { size_t hlen = c - hctx->response->ptr + 4; size_t blen = hctx->response->used - hlen - 1; /* found */ buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4); #if 0 log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header); #endif /* parse the response header */ proxy_response_parse(srv, con, p, hctx->response_header); /* enable chunked-transfer-encoding */ if (con->request.http_version == HTTP_VERSION_1_1 && !(con->parsed_response & HTTP_CONTENT_LENGTH)) { con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; } con->file_started = 1; if (blen) { http_chunk_append_mem(srv, con, c + 4, blen + 1); } hctx->response->used = 0; joblist_append(srv, con); } } else { http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used); joblist_append(srv, con); hctx->response->used = 0; } } else { /* reading from upstream done */ con->file_finished = 1; http_chunk_append_mem(srv, con, NULL, 0); joblist_append(srv, con); fin = 1; } return fin; }