Allow applications to create new connections in our event loop.

This commit is contained in:
Joris Vink 2014-09-17 08:25:45 +02:00
parent b2f870a36f
commit 7771adbec2
5 changed files with 183 additions and 100 deletions

View File

@ -160,6 +160,10 @@ struct connection {
void *hdlr_extra;
X509 *cert;
void (*disconnect)(struct connection *);
int (*read)(struct connection *, int *);
int (*write)(struct connection *, int, int *);
u_int8_t addrtype;
union {
struct sockaddr_in ipv4;
@ -359,6 +363,7 @@ void kore_platform_disable_read(int);
void kore_platform_enable_accept(void);
void kore_platform_disable_accept(void);
void kore_platform_event_wait(u_int64_t);
void kore_platform_event_all(int, void *);
void kore_platform_schedule_read(int, void *);
void kore_platform_event_schedule(int, int, int, void *);
void kore_platform_worker_setcpu(struct kore_worker *);
@ -376,15 +381,18 @@ int kore_ssl_sni_cb(SSL *, int *, void *);
int kore_server_bind(const char *, const char *);
int kore_ssl_npn_cb(SSL *, const u_char **, unsigned int *, void *);
void kore_connection_init(void);
int kore_connection_nonblock(int);
int kore_connection_handle(struct connection *);
void kore_connection_remove(struct connection *);
void kore_connection_disconnect(struct connection *);
void kore_connection_start_idletimer(struct connection *);
void kore_connection_stop_idletimer(struct connection *);
void kore_connection_check_idletimer(u_int64_t, struct connection *);
int kore_connection_accept(struct listener *, struct connection **);
void kore_connection_init(void);
struct connection *kore_connection_new(void *);
int kore_connection_nonblock(int);
int kore_connection_handle(struct connection *);
void kore_connection_remove(struct connection *);
void kore_connection_disconnect(struct connection *);
void kore_connection_start_idletimer(struct connection *);
void kore_connection_stop_idletimer(struct connection *);
void kore_connection_check_idletimer(u_int64_t,
struct connection *);
int kore_connection_accept(struct listener *,
struct connection **);
u_int64_t kore_time_ms(void);
void kore_log_init(void);
@ -457,6 +465,10 @@ int net_recv(struct connection *);
int net_send(struct connection *);
int net_send_flush(struct connection *);
int net_recv_flush(struct connection *);
int net_read(struct connection *, int *);
int net_read_ssl(struct connection *, int *);
int net_write(struct connection *, int, int *);
int net_write_ssl(struct connection *, int, int *);
void net_remove_netbuf(struct netbuf_head *, struct netbuf *);
void net_recv_queue(struct connection *, u_int32_t, int,
struct netbuf **, int (*cb)(struct netbuf *));

View File

@ -145,10 +145,7 @@ kore_platform_event_wait(u_int64_t timer)
if (c == NULL)
break;
kore_platform_event_schedule(c->fd,
EVFILT_READ, EV_ADD, c);
kore_platform_event_schedule(c->fd,
EVFILT_WRITE, EV_ADD | EV_ONESHOT, c);
kore_platform_event_all(c->fd, c);
}
break;
case KORE_TYPE_CONNECTION:
@ -186,6 +183,13 @@ kore_platform_event_wait(u_int64_t timer)
}
}
void
kore_platform_event_all(int fd, void *c)
{
kore_platform_event_schedule(fd, EVFILT_READ, EV_ADD, c);
kore_platform_event_schedule(fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, c);
}
void
kore_platform_event_schedule(int fd, int type, int flags, void *data)
{

View File

@ -33,6 +33,38 @@ kore_connection_init(void)
sizeof(struct connection), worker_max_connections);
}
struct connection *
kore_connection_new(void *owner)
{
struct connection *c;
c = kore_pool_get(&connection_pool);
c->ssl = NULL;
c->flags = 0;
c->cert = NULL;
c->owner = owner;
c->disconnect = NULL;
c->hdlr_extra = NULL;
c->inflate_started = 0;
c->deflate_started = 0;
c->client_stream_id = 0;
c->proto = CONN_PROTO_UNKNOWN;
c->type = KORE_TYPE_CONNECTION;
c->wsize_initial = SPDY_INIT_WSIZE;
c->spdy_send_wsize = SPDY_INIT_WSIZE;
c->spdy_recv_wsize = 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));
TAILQ_INIT(&(c->http_requests));
return (c);
}
int
kore_connection_accept(struct listener *l, struct connection **out)
{
@ -43,8 +75,7 @@ kore_connection_accept(struct listener *l, struct connection **out)
kore_debug("kore_connection_accept(%p)", l);
*out = NULL;
c = kore_pool_get(&connection_pool);
c->type = KORE_TYPE_CONNECTION;
c = kore_connection_new(l);
c->addrtype = l->addrtype;
if (c->addrtype == AF_INET) {
@ -67,31 +98,16 @@ kore_connection_accept(struct listener *l, struct connection **out)
return (KORE_RESULT_ERROR);
}
c->owner = l;
c->ssl = NULL;
c->flags = 0;
c->cert = NULL;
c->hdlr_extra = NULL;
c->inflate_started = 0;
c->deflate_started = 0;
c->client_stream_id = 0;
c->proto = CONN_PROTO_UNKNOWN;
c->wsize_initial = SPDY_INIT_WSIZE;
c->spdy_send_wsize = SPDY_INIT_WSIZE;
c->spdy_recv_wsize = 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));
TAILQ_INIT(&(c->http_requests));
#if !defined(KORE_BENCHMARK)
c->state = CONN_STATE_SSL_SHAKE;
c->write = net_write_ssl;
c->read = net_read_ssl;
#else
c->state = CONN_STATE_ESTABLISHED;
c->proto = CONN_PROTO_HTTP;
c->write = net_write;
c->read = net_read;
if (http_keepalive_time != 0)
c->idle_timer.length = http_keepalive_time * 1000;
@ -112,6 +128,9 @@ kore_connection_disconnect(struct connection *c)
if (c->state != CONN_STATE_DISCONNECTING) {
kore_debug("preparing %p for disconnection", c);
c->state = CONN_STATE_DISCONNECTING;
if (c->disconnect)
c->disconnect(c);
kore_worker_connection_move(c);
}
}

View File

@ -131,9 +131,7 @@ kore_platform_event_wait(u_int64_t timer)
if (c == NULL)
break;
kore_platform_event_schedule(c->fd,
EPOLLIN | EPOLLOUT |
EPOLLRDHUP | EPOLLET, 0, c);
kore_platform_event_all(c->fd, c);
}
break;
case KORE_TYPE_CONNECTION:
@ -164,6 +162,13 @@ kore_platform_event_wait(u_int64_t timer)
}
}
void
kore_platform_event_all(int fd, void *c)
{
kore_platform_event_schedule(fd,
EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET, 0, c);
}
void
kore_platform_event_schedule(int fd, int type, int flags, void *udata)
{

167
src/net.c
View File

@ -176,37 +176,11 @@ net_send(struct connection *c)
len = MIN(NETBUF_SEND_PAYLOAD_MAX, smin);
#if !defined(KORE_BENCHMARK)
r = SSL_write(c->ssl,
(c->snb->buf + c->snb->s_off), len);
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
switch (r) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
c->snb->flags |= NETBUF_MUST_RESEND;
c->flags &= ~CONN_WRITE_POSSIBLE;
return (KORE_RESULT_OK);
default:
kore_debug("SSL_write(): %s",
ssl_errno_s);
return (KORE_RESULT_ERROR);
}
}
#else
r = write(c->fd, (c->snb->buf + c->snb->s_off), len);
if (r <= -1) {
switch (errno) {
case EINTR:
case EAGAIN:
c->flags &= ~CONN_WRITE_POSSIBLE;
return (KORE_RESULT_OK);
default:
kore_debug("write: %s", errno_s);
return (KORE_RESULT_ERROR);
}
}
#endif
if (!c->write(c, len, &r))
return (KORE_RESULT_ERROR);
if (!(c->flags & CONN_WRITE_POSSIBLE))
return (KORE_RESULT_OK);
kore_debug("net_send(%p/%d/%d bytes), progress with %d",
c->snb, c->snb->s_off, c->snb->b_len, r);
@ -253,37 +227,11 @@ net_recv(struct connection *c)
return (KORE_RESULT_ERROR);
}
#if !defined(KORE_BENCHMARK)
r = SSL_read(c->ssl,
(c->rnb->buf + c->rnb->s_off),
(c->rnb->b_len - c->rnb->s_off));
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
switch (r) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
c->flags &= ~CONN_READ_POSSIBLE;
return (KORE_RESULT_OK);
default:
kore_debug("SSL_read(): %s", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
}
#else
r = read(c->fd, (c->rnb->buf + c->rnb->s_off),
(c->rnb->b_len - c->rnb->s_off));
if (r <= 0) {
switch (errno) {
case EINTR:
case EAGAIN:
c->flags &= ~CONN_READ_POSSIBLE;
return (KORE_RESULT_OK);
default:
kore_debug("read(): %s", errno_s);
return (KORE_RESULT_ERROR);
}
}
#endif
if (!c->read(c, &r))
return (KORE_RESULT_ERROR);
if (!(c->flags & CONN_READ_POSSIBLE))
return (KORE_RESULT_OK);
kore_debug("net_recv(%ld/%ld bytes), progress with %d",
c->rnb->s_off, c->rnb->b_len, r);
@ -340,6 +288,101 @@ net_remove_netbuf(struct netbuf_head *list, struct netbuf *nb)
kore_pool_put(&nb_pool, nb);
}
#if !defined(KORE_BENCHMARK)
int
net_write_ssl(struct connection *c, int len, int *written)
{
int r;
r = SSL_write(c->ssl, (c->snb->buf + c->snb->s_off), len);
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
switch (r) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
c->snb->flags |= NETBUF_MUST_RESEND;
c->flags &= ~CONN_WRITE_POSSIBLE;
return (KORE_RESULT_OK);
default:
kore_debug("SSL_write(): %s", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
}
*written = r;
return (KORE_RESULT_OK);
}
int
net_read_ssl(struct connection *c, int *bytes)
{
int r;
r = SSL_read(c->ssl, (c->rnb->buf + c->rnb->s_off),
(c->rnb->b_len - c->rnb->s_off));
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
switch (r) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
c->flags &= ~CONN_READ_POSSIBLE;
return (KORE_RESULT_OK);
default:
kore_debug("SSL_read(): %s", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
}
*bytes = r;
return (KORE_RESULT_OK);
}
#endif
int
net_write(struct connection *c, int len, int *written)
{
int r;
r = write(c->fd, (c->snb->buf + c->snb->s_off), len);
if (r <= -1) {
switch (errno) {
case EINTR:
case EAGAIN:
c->flags &= ~CONN_WRITE_POSSIBLE;
return (KORE_RESULT_OK);
default:
kore_debug("write: %s", errno_s);
return (KORE_RESULT_ERROR);
}
}
*written = r;
return (KORE_RESULT_OK);
}
int
net_read(struct connection *c, int *bytes)
{
int r;
r = read(c->fd, (c->rnb->buf + c->rnb->s_off),
(c->rnb->b_len - c->rnb->s_off));
if (r <= 0) {
switch (errno) {
case EINTR:
case EAGAIN:
c->flags &= ~CONN_READ_POSSIBLE;
return (KORE_RESULT_OK);
default:
kore_debug("read(): %s", errno_s);
return (KORE_RESULT_ERROR);
}
}
*bytes = r;
return (KORE_RESULT_OK);
}
u_int16_t
net_read16(u_int8_t *b)
{