コード例 #1
0
ファイル: proxy.c プロジェクト: 1514louluo/kore
/*
 * This function is called for backends while they are connecting.
 * In here we check for write events and attempt to connect() to the
 * backend.
 *
 * Once a connection is established we set the backend handle function
 * pointer to the backend_handle_default() callback and setup the reads
 * for both the backend and the client connection we received.
 */
int
backend_handle_connect(struct connection *c)
{
	int			ret;
	struct connection	*src;

	/* We will get a write notification when we can progress. */
	if (!(c->flags & CONN_WRITE_POSSIBLE))
		return (KORE_RESULT_OK);

	kore_connection_stop_idletimer(c);

	/* Attempt connecting. */
	ret = connect(c->fd, (struct sockaddr *)&c->addr.ipv4,
	    sizeof(c->addr.ipv4));

	/* If we failed check why, we are non blocking. */
	if (ret == -1) {
		/* If we got a real error, disconnect. */
		if (errno != EALREADY && errno != EINPROGRESS &&
		    errno != EISCONN) {
			kore_log(LOG_ERR, "connect(): %s", errno_s);
			return (KORE_RESULT_ERROR);
		}

		/* Clean the write flag, we'll be called later. */
		if (errno != EISCONN) {
			c->flags &= ~CONN_WRITE_POSSIBLE;
			kore_connection_start_idletimer(c);
			return (KORE_RESULT_OK);
		}
	}

	/* The connection to the backend succeeded. */
	c->handle = backend_handle_default;

	/* Setup read calls for both backend and its client. */
	net_recv_queue(c, NETBUF_SEND_PAYLOAD_MAX,
	    NETBUF_CALL_CB_ALWAYS, pipe_data);
	net_recv_queue(c->hdlr_extra, NETBUF_SEND_PAYLOAD_MAX,
	    NETBUF_CALL_CB_ALWAYS, pipe_data);

	/* Allow for all events now. */
	kore_connection_start_idletimer(c);
	kore_platform_event_all(c->fd, c);

	/* Allow events from source now. */
	src = c->hdlr_extra;
	kore_platform_event_all(src->fd, src);

	/* Now lets start. */
	return (c->handle(c));
}
コード例 #2
0
ファイル: connection.c プロジェクト: josephglanville/kore
int
kore_connection_accept(struct listener *l, struct connection **out)
{
	socklen_t		len;
	struct connection	*c;

	kore_debug("kore_connection_accept(%p)", l);

	*out = NULL;
	len = sizeof(struct sockaddr_in);

	c = kore_pool_get(&connection_pool);
	if ((c->fd = accept(l->fd, (struct sockaddr *)&(c->sin), &len)) == -1) {
		kore_pool_put(&connection_pool, c);
		kore_debug("accept(): %s", errno_s);
		return (KORE_RESULT_ERROR);
	}

	if (!kore_connection_nonblock(c->fd)) {
		close(c->fd);
		kore_pool_put(&connection_pool, c);
		return (KORE_RESULT_ERROR);
	}

	c->owner = l;
	c->ssl = NULL;
	c->flags = 0;
	c->inflate_started = 0;
	c->deflate_started = 0;
	c->client_stream_id = 0;
	c->proto = CONN_PROTO_UNKNOWN;
	c->state = CONN_STATE_SSL_SHAKE;
	c->wsize_initial = SPDY_INIT_WSIZE;
	c->idle_timer.start = 0;
	c->idle_timer.length = KORE_IDLE_TIMER_MAX;

	TAILQ_INIT(&(c->send_queue));
	TAILQ_INIT(&(c->recv_queue));
	TAILQ_INIT(&(c->spdy_streams));

	kore_worker_connection_add(c);
	kore_connection_start_idletimer(c);

	*out = c;
	return (KORE_RESULT_OK);
}
コード例 #3
0
ファイル: proxy.c プロジェクト: 1514louluo/kore
/*
 * Called for every new connection on a certain ip/port. Which one is
 * configured in the TLS proxy its configuration file.
 */
void
client_setup(struct connection *c)
{
	int			i, fd;
	struct connection	*backend;

	/* Paranoia. */
	if (c->ssl->session == NULL ||
	    c->ssl->session->tlsext_hostname == NULL) {
		kore_connection_disconnect(c);
		return;
	}

	/* Figure out what backend to use. */
	for (i = 0; backends[i].name != NULL; i++) {
		if (!strcasecmp(backends[i].name,
		    c->ssl->session->tlsext_hostname))
			break;
	}

	/* If we don't have any backends, we just disconnect the client. */
	if (backends[i].name == NULL) {
		kore_connection_disconnect(c);
		return;
	}

	/* Create new socket for the backend connection. */
	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		kore_log(LOG_ERR, "socket(): %s", errno_s);
		kore_connection_disconnect(c);
		return;
	}

	/* Set it to non blocking as well. */
	if (!kore_connection_nonblock(fd, 1)) {
		close(fd);
		kore_connection_disconnect(c);
		return;
	}

	/* Grab a new connection from Kore to hook backend into. */
	backend = kore_connection_new(NULL);

	/* Prepare our connection. */
	backend->addrtype = AF_INET;
	backend->addr.ipv4.sin_family = AF_INET;
	backend->addr.ipv4.sin_port = htons(backends[i].port);
	backend->addr.ipv4.sin_addr.s_addr = inet_addr(backends[i].ip);

	/* Set the file descriptor for the backend. */
	backend->fd = fd;

	/* Default write/read callbacks for backend. */
	backend->read = net_read;
	backend->write = net_write;

	/* Connection type (unknown to Kore). */
	backend->proto = CONN_PROTO_UNKNOWN;
	backend->state = CONN_STATE_ESTABLISHED;

	/* The backend idle timer is set first to connection timeout. */
	backend->idle_timer.length = PROXY_CONNECT_TIMEOUT;

	/* The client idle timer is set to default idle time. */
	c->idle_timer.length = PROXY_TIMEOUT;

	/* Now link both the client and the backend connection together. */
	c->hdlr_extra = backend;
	backend->hdlr_extra = c;

	/*
	 * The handle function pointer for the backend is set to the
	 * backend_handle_connect() while connecting.
	 */
	c->handle = client_handle;
	backend->handle = backend_handle_connect;

	/* Set the disconnect method for both connections. */
	c->disconnect = disconnect;
	backend->disconnect = disconnect;

	/* Queue write events for the backend connection for now. */
	kore_platform_schedule_write(backend->fd, backend);

	/* Start idle timer for the backend. */
	kore_connection_start_idletimer(backend);

	/* Set our client connection to established. */
	c->state = CONN_STATE_ESTABLISHED;

	/* Insert the backend into the list of Kore connections. */
	TAILQ_INSERT_TAIL(&connections, backend, list);

	/* Kick off connecting. */
	backend->flags |= CONN_WRITE_POSSIBLE;
	backend->handle(backend);
}
コード例 #4
0
ファイル: connection.c プロジェクト: liexusong/kore
int
kore_connection_handle(struct connection *c)
{
	int			r;
	u_int32_t		len;
	const u_char		*data;

	kore_debug("kore_connection_handle(%p)", c);

	if (c->proto != CONN_PROTO_SPDY)
		kore_connection_stop_idletimer(c);

	switch (c->state) {
	case CONN_STATE_SSL_SHAKE:
		if (c->ssl == NULL) {
			c->ssl = SSL_new(primary_dom->ssl_ctx);
			if (c->ssl == NULL) {
				kore_debug("SSL_new(): %s", ssl_errno_s);
				return (KORE_RESULT_ERROR);
			}

			SSL_set_fd(c->ssl, c->fd);
			SSL_set_accept_state(c->ssl);
		}

		r = SSL_accept(c->ssl);
		if (r <= 0) {
			r = SSL_get_error(c->ssl, r);
			switch (r) {
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
				return (KORE_RESULT_OK);
			default:
				kore_debug("SSL_accept(): %s", ssl_errno_s);
				return (KORE_RESULT_ERROR);
			}
		}

		r = SSL_get_verify_result(c->ssl);
		if (r != X509_V_OK) {
			kore_debug("SSL_get_verify_result(): %s", ssl_errno_s);
			return (KORE_RESULT_ERROR);
		}

		SSL_get0_next_proto_negotiated(c->ssl, &data, &len);
		if (data) {
			if (!memcmp(data, "spdy/3", MIN(6, len))) {
				c->proto = CONN_PROTO_SPDY;
				net_recv_queue(c, SPDY_FRAME_SIZE, 0,
				    NULL, spdy_frame_recv);
			} else if (!memcmp(data, "http/1.1", MIN(8, len))) {
				c->proto = CONN_PROTO_HTTP;
				net_recv_queue(c, HTTP_HEADER_MAX_LEN,
				    NETBUF_CALL_CB_ALWAYS, NULL,
				    http_header_recv);
			} else {
				kore_debug("npn: received unknown protocol");
			}
		} else {
			c->proto = CONN_PROTO_HTTP;
			net_recv_queue(c, HTTP_HEADER_MAX_LEN,
			    NETBUF_CALL_CB_ALWAYS, NULL,
			    http_header_recv);
		}

		c->state = CONN_STATE_ESTABLISHED;
		/* FALLTHROUGH */
	case CONN_STATE_ESTABLISHED:
		if (c->flags & CONN_READ_POSSIBLE) {
			if (!net_recv_flush(c))
				return (KORE_RESULT_ERROR);
		}

		if (c->flags & CONN_WRITE_POSSIBLE) {
			if (!net_send_flush(c))
				return (KORE_RESULT_ERROR);
		}
		break;
	case CONN_STATE_DISCONNECTING:
		break;
	default:
		kore_debug("unknown state on %d (%d)", c->fd, c->state);
		break;
	}

	if (c->proto != CONN_PROTO_SPDY)
		kore_connection_start_idletimer(c);

	return (KORE_RESULT_OK);
}
コード例 #5
0
ファイル: ktunnel.c プロジェクト: 2ion/kore
/*
 * Connect to our target host:port and attach it to a struct connection that
 * Kore understands. We set the disconnect method so we get a callback
 * whenever either of the connections will go away so we can cleanup the
 * one it is attached to.
 */
static int
ktunnel_pipe_create(struct connection *c, const char *host, const char *port)
{
	struct sockaddr_in	sin;
	struct connection	*cpipe;
	u_int16_t		nport;
	int			fd, err;

	nport = kore_strtonum(port, 10, 1, SHRT_MAX, &err);
	if (err == KORE_RESULT_ERROR) {
		kore_log(LOG_ERR, "invalid port given %s", port);
		return (KORE_RESULT_ERROR);
	}

	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		kore_log(LOG_ERR, "socket(): %s", errno_s);
		return (KORE_RESULT_ERROR);
	}

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(nport);
	sin.sin_addr.s_addr = inet_addr(host);

	kore_log(LOG_NOTICE, "Attempting to connect to %s:%s", host, port);

	if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
		close(fd);
		kore_log(LOG_ERR, "connect(): %s", errno_s);
		return (KORE_RESULT_ERROR);
	}

	if (!kore_connection_nonblock(fd)) {
		close(fd);
		return (KORE_RESULT_ERROR);
	}

	cpipe = kore_connection_new(c);
	cpipe->fd = fd;
	cpipe->addr.ipv4 = sin;
	cpipe->read = net_read;
	cpipe->write = net_write;
	cpipe->addrtype = AF_INET;
	cpipe->proto = CONN_PROTO_UNKNOWN;
	cpipe->state = CONN_STATE_ESTABLISHED;

	/* Don't let these connections timeout any time soon. */
	cpipe->idle_timer.length = 10000000000;
	c->idle_timer.length = 10000000000;

	c->hdlr_extra = cpipe;
	cpipe->hdlr_extra = c;
	c->disconnect = ktunnel_pipe_disconnect;
	cpipe->disconnect = ktunnel_pipe_disconnect;

	kore_worker_connection_add(cpipe);
	kore_connection_start_idletimer(cpipe);
	kore_platform_event_all(cpipe->fd, cpipe);

	net_recv_reset(c, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data);
	net_recv_queue(cpipe, NETBUF_SEND_PAYLOAD_MAX, NETBUF_CALL_CB_ALWAYS,
	    ktunnel_pipe_data);

	printf("connection started to %s (%p -> %p)\n", host, c, cpipe);
	return (KORE_RESULT_OK);
}