Beispiel #1
0
static void proxy_connection_new(liVRequest *vr, liBackendConnection *bcon, proxy_context *ctx) {
	proxy_connection* scon = g_slice_new0(proxy_connection);
	liIOStream *iostream;
	liStream *outplug;
	liStream *http_out;

	proxy_context_acquire(ctx);
	scon->ctx = ctx;
	scon->bcon = bcon;
	iostream = li_iostream_new(vr->wrk, li_event_io_fd(&bcon->watcher), proxy_io_cb, scon);

	/* insert proxy header before actual data */
	outplug = li_stream_plug_new(&vr->wrk->loop);

	li_stream_connect(outplug, &iostream->stream_out);

	proxy_send_headers(vr, outplug->out);
	li_stream_notify_later(outplug);

	http_out = li_stream_http_response_handle(&iostream->stream_in, vr, TRUE, FALSE);

	li_vrequest_handle_indirect(vr, NULL);
	li_vrequest_indirect_connect(vr, outplug, http_out);

	li_iostream_release(iostream);
	li_stream_release(outplug);
	li_stream_release(http_out);
}
Beispiel #2
0
static liHandlerResult proxy_statemachine(liVRequest *vr, proxy_connection *pcon) {
	liPlugin *p = pcon->ctx->plugin;

	switch (pcon->state) {
	case SS_WAIT_FOR_REQUEST:
		/* do *not* wait until we have all data */
		pcon->state = SS_CONNECT;

		/* fall through */
	case SS_CONNECT:
		do {
			pcon->fd = socket(pcon->ctx->socket.addr->plain.sa_family, SOCK_STREAM, 0);
		} while (-1 == pcon->fd && errno == EINTR);
		if (-1 == pcon->fd) {
			if (errno == EMFILE) {
				li_server_out_of_fds(vr->wrk->srv);
			}
			VR_ERROR(vr, "Couldn't open socket: %s", g_strerror(errno));
			return LI_HANDLER_ERROR;
		}
		li_fd_init(pcon->fd);
		ev_io_set(&pcon->fd_watcher, pcon->fd, EV_READ | EV_WRITE);
		ev_io_start(vr->wrk->loop, &pcon->fd_watcher);

		/* fall through */
	case SS_CONNECTING:
		if (-1 == connect(pcon->fd, &pcon->ctx->socket.addr->plain, pcon->ctx->socket.len)) {
			switch (errno) {
			case EINPROGRESS:
			case EALREADY:
			case EINTR:
				pcon->state = SS_CONNECTING;
				return LI_HANDLER_GO_ON;
			case EAGAIN: /* backend overloaded */
				proxy_close(vr, p);
				li_vrequest_backend_overloaded(vr);
				return LI_HANDLER_GO_ON;
			case EISCONN:
				break;
			default:
				VR_ERROR(vr, "Couldn't connect to '%s': %s",
					li_sockaddr_to_string(pcon->ctx->socket, vr->wrk->tmp_str, TRUE)->str,
					g_strerror(errno));
				proxy_close(vr, p);
				li_vrequest_backend_dead(vr);
				return LI_HANDLER_GO_ON;
			}
		}

		pcon->state = SS_CONNECTED;

		/* prepare stream */
		proxy_send_headers(vr, pcon);

		/* fall through */
	case SS_CONNECTED:
		proxy_forward_request(vr, pcon);
		break;

	case SS_DONE:
		break;
	}

	return LI_HANDLER_GO_ON;
}