Пример #1
0
static void stream_http_response_data(liStreamHttpResponse* shr) {
	if (NULL == shr->stream.source) return;

	if (!shr->response_headers_finished) {
		switch (li_http_response_parse(shr->vr, &shr->parse_response_ctx)) {
		case LI_HANDLER_GO_ON:
			check_response_header(shr);
			if (NULL == shr->stream.source) return;
			break;
		case LI_HANDLER_ERROR:
			VR_ERROR(shr->vr, "%s", "Parsing response header failed");
			li_vrequest_error(shr->vr);
			return;
		case LI_HANDLER_WAIT_FOR_EVENT:
			if (shr->stream.source->out->is_closed) {
				VR_ERROR(shr->vr, "%s", "Parsing response header failed (eos)");
				li_vrequest_error(shr->vr);
			}
			return;
		default:
			return;
		}
	}

	if (shr->transfer_encoding_chunked) {
		if (!li_filter_chunked_decode(shr->vr, shr->stream.out, shr->stream.source->out, &shr->chunked_decode_state)) {
			if (NULL != shr->vr) {
				VR_ERROR(shr->vr, "%s", "Decoding chunks failed");
				li_vrequest_error(shr->vr);
			} else {
				li_stream_reset(&shr->stream);
			}
		}
		if (shr->stream.source->out->is_closed) {
			li_stream_disconnect(&shr->stream);
		}
	} else {
		li_chunkqueue_steal_all(shr->stream.out, shr->stream.source->out);
		if (shr->stream.source->out->is_closed) {
			shr->stream.out->is_closed = TRUE;
			li_stream_disconnect(&shr->stream);
		}
	}
	li_stream_notify(&shr->stream);
}
Пример #2
0
static void proxy_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
	proxy_connection *pcon = (proxy_connection*) w->data;

	if (pcon->state == SS_CONNECTING) {
		if (LI_HANDLER_GO_ON != proxy_statemachine(pcon->vr, pcon)) {
			li_vrequest_error(pcon->vr);
		}
		return;
	}

	if (revents & EV_READ) {
		if (pcon->proxy_in->is_closed) {
			li_ev_io_rem_events(loop, w, EV_READ);
		} else {
			switch (li_network_read(pcon->vr, w->fd, pcon->proxy_in, &pcon->proxy_in_buffer)) {
			case LI_NETWORK_STATUS_SUCCESS:
				break;
			case LI_NETWORK_STATUS_FATAL_ERROR:
				VR_ERROR(pcon->vr, "(%s) network read fatal error", pcon->ctx->socket_str->str);
				li_vrequest_error(pcon->vr);
				return;
			case LI_NETWORK_STATUS_CONNECTION_CLOSE:
				pcon->proxy_in->is_closed = TRUE;
				ev_io_stop(loop, w);
				close(pcon->fd);
				pcon->fd = -1;
				li_vrequest_backend_finished(pcon->vr);
				break;
			case LI_NETWORK_STATUS_WAIT_FOR_EVENT:
				break;
			}
		}
	}

	if (pcon->fd != -1 && (revents & EV_WRITE)) {
		if (pcon->proxy_out->length > 0) {
			switch (li_network_write(pcon->vr, w->fd, pcon->proxy_out, 256*1024)) {
			case LI_NETWORK_STATUS_SUCCESS:
				break;
			case LI_NETWORK_STATUS_FATAL_ERROR:
				VR_ERROR(pcon->vr, "(%s) network write fatal error", pcon->ctx->socket_str->str);
				li_vrequest_error(pcon->vr);
				return;
			case LI_NETWORK_STATUS_CONNECTION_CLOSE:
				pcon->proxy_in->is_closed = TRUE;
				ev_io_stop(loop, w);
				close(pcon->fd);
				pcon->fd = -1;
				li_vrequest_backend_finished(pcon->vr);
				break;
			case LI_NETWORK_STATUS_WAIT_FOR_EVENT:
				break;
			}
		}
		if (pcon->proxy_out->length == 0) {
			li_ev_io_rem_events(loop, w, EV_WRITE);
		}
	}

	if (!pcon->response_headers_finished && LI_HANDLER_GO_ON == li_http_response_parse(pcon->vr, &pcon->parse_response_ctx)) {
		/* "ignore" 1xx response headers */
		if (!(pcon->vr->response.http_status >= 100 && pcon->vr->response.http_status < 200)) {
			pcon->response_headers_finished = TRUE;
			li_vrequest_handle_response_headers(pcon->vr);
		}
	}

	if (pcon->response_headers_finished) {
		li_chunkqueue_steal_all(pcon->vr->out, pcon->proxy_in);
		pcon->vr->out->is_closed = pcon->proxy_in->is_closed;
		li_vrequest_handle_response_body(pcon->vr);
	}

	/* only possible if we didn't found a header */
	if (pcon->proxy_in->is_closed && !pcon->vr->out->is_closed) {
		VR_ERROR(pcon->vr, "(%s) unexpected end-of-file (perhaps the proxy process died)", pcon->ctx->socket_str->str);
		li_vrequest_error(pcon->vr);
	}
}
Пример #3
0
static void fastcgi_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
	fastcgi_connection *fcon = (fastcgi_connection*) w->data;

	if (fcon->state == FS_CONNECTING) {
		if (LI_HANDLER_GO_ON != fastcgi_statemachine(fcon->vr, fcon)) {
			li_vrequest_error(fcon->vr);
		}
		return;
	}

	if (revents & EV_READ) {
		if (fcon->fcgi_in->is_closed) {
			li_ev_io_rem_events(loop, w, EV_READ);
		} else {
			switch (li_network_read(fcon->vr, w->fd, fcon->fcgi_in, &fcon->fcgi_in_buffer)) {
			case LI_NETWORK_STATUS_SUCCESS:
				break;
			case LI_NETWORK_STATUS_FATAL_ERROR:
				VR_ERROR(fcon->vr, "(%s) network read fatal error", fcon->ctx->socket_str->str);
				li_vrequest_error(fcon->vr);
				return;
			case LI_NETWORK_STATUS_CONNECTION_CLOSE:
				fcon->fcgi_in->is_closed = TRUE;
				ev_io_stop(loop, w);
				close(fcon->fd);
				fcon->fd = -1;
				li_vrequest_backend_finished(fcon->vr);
				break;
			case LI_NETWORK_STATUS_WAIT_FOR_EVENT:
				break;
			}
		}
	}

	if (fcon->fd != -1 && (revents & EV_WRITE)) {
		if (fcon->fcgi_out->length > 0) {
			switch (li_network_write(fcon->vr, w->fd, fcon->fcgi_out, 256*1024)) {
			case LI_NETWORK_STATUS_SUCCESS:
				break;
			case LI_NETWORK_STATUS_FATAL_ERROR:
				VR_ERROR(fcon->vr, "(%s) network write fatal error", fcon->ctx->socket_str->str);
				li_vrequest_error(fcon->vr);
				return;
			case LI_NETWORK_STATUS_CONNECTION_CLOSE:
				fcon->fcgi_in->is_closed = TRUE;
				ev_io_stop(loop, w);
				close(fcon->fd);
				fcon->fd = -1;
				li_vrequest_backend_finished(fcon->vr);
				break;
			case LI_NETWORK_STATUS_WAIT_FOR_EVENT:
				break;
			}
		}
		if (fcon->fcgi_out->length == 0) {
			li_ev_io_rem_events(loop, w, EV_WRITE);
		}
	}

	if (!fastcgi_parse_response(fcon)) return;

	if (!fcon->response_headers_finished) {
		switch (li_http_response_parse(fcon->vr, &fcon->parse_response_ctx)) {
		case LI_HANDLER_GO_ON:
			fcon->response_headers_finished = TRUE;
			li_vrequest_handle_response_headers(fcon->vr);
			break;
		case LI_HANDLER_ERROR:
			VR_ERROR(fcon->vr, "Parsing response header failed for: %s", fcon->ctx->socket_str->str);
			li_vrequest_error(fcon->vr);
			break;
		default:
			break;
		}
	}

	if (fcon->response_headers_finished) {
		li_chunkqueue_steal_all(fcon->vr->out, fcon->stdout);
		fcon->vr->out->is_closed = fcon->stdout->is_closed;
		li_vrequest_handle_response_body(fcon->vr);
	}

	if (fcon->fcgi_in->is_closed && !fcon->vr->out->is_closed) {
		VR_ERROR(fcon->vr, "(%s) unexpected end-of-file (perhaps the fastcgi process died)", fcon->ctx->socket_str->str);
		li_vrequest_error(fcon->vr);
	}
}