mirror of https://git.kore.io/kore.git
rework disconnecting clients and fix bug where spdy ocnnections could segfault after disconnecting
This commit is contained in:
parent
fdb9004c6d
commit
364dc58219
|
@ -33,7 +33,6 @@ struct netbuf {
|
||||||
u_int32_t offset;
|
u_int32_t offset;
|
||||||
u_int32_t len;
|
u_int32_t len;
|
||||||
u_int8_t type;
|
u_int8_t type;
|
||||||
u_int8_t retain;
|
|
||||||
u_int8_t flags;
|
u_int8_t flags;
|
||||||
|
|
||||||
void *owner;
|
void *owner;
|
||||||
|
@ -47,9 +46,10 @@ struct listener {
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CONN_STATE_UNKNOWN 0
|
#define CONN_STATE_UNKNOWN 0
|
||||||
#define CONN_STATE_SSL_SHAKE 1
|
#define CONN_STATE_SSL_SHAKE 1
|
||||||
#define CONN_STATE_ESTABLISHED 2
|
#define CONN_STATE_ESTABLISHED 2
|
||||||
|
#define CONN_STATE_DISCONNECTING 3
|
||||||
|
|
||||||
#define CONN_PROTO_UNKNOWN 0
|
#define CONN_PROTO_UNKNOWN 0
|
||||||
#define CONN_PROTO_SPDY 1
|
#define CONN_PROTO_SPDY 1
|
||||||
|
@ -59,6 +59,7 @@ struct listener {
|
||||||
#define CONN_WRITE_POSSIBLE 0x02
|
#define CONN_WRITE_POSSIBLE 0x02
|
||||||
|
|
||||||
#define NETBUF_CALL_CB_ALWAYS 0x01
|
#define NETBUF_CALL_CB_ALWAYS 0x01
|
||||||
|
#define NETBUF_FORCE_REMOVE 0x02
|
||||||
|
|
||||||
struct connection {
|
struct connection {
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -79,6 +80,8 @@ struct connection {
|
||||||
|
|
||||||
u_int32_t client_stream_id;
|
u_int32_t client_stream_id;
|
||||||
TAILQ_HEAD(, spdy_stream) spdy_streams;
|
TAILQ_HEAD(, spdy_stream) spdy_streams;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(connection) list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HANDLER_TYPE_STATIC 1
|
#define HANDLER_TYPE_STATIC 1
|
||||||
|
|
20
src/http.c
20
src/http.c
|
@ -222,7 +222,7 @@ void
|
||||||
http_process(void)
|
http_process(void)
|
||||||
{
|
{
|
||||||
struct http_request *req, *next;
|
struct http_request *req, *next;
|
||||||
int (*handler)(struct http_request *);
|
int r, (*handler)(struct http_request *);
|
||||||
|
|
||||||
if (TAILQ_EMPTY(&http_requests))
|
if (TAILQ_EMPTY(&http_requests))
|
||||||
return;
|
return;
|
||||||
|
@ -232,15 +232,16 @@ http_process(void)
|
||||||
next = TAILQ_NEXT(req, list);
|
next = TAILQ_NEXT(req, list);
|
||||||
|
|
||||||
handler = kore_module_handler_find(req->path);
|
handler = kore_module_handler_find(req->path);
|
||||||
if (handler == NULL) {
|
if (handler == NULL)
|
||||||
if (!http_generic_404(req))
|
r = http_generic_404(req);
|
||||||
kore_server_disconnect(req->owner);
|
else
|
||||||
} else {
|
r = handler(req);
|
||||||
if (!handler(req))
|
|
||||||
kore_server_disconnect(req->owner);
|
if (r != KORE_RESULT_ERROR)
|
||||||
}
|
net_send_flush(req->owner);
|
||||||
|
else
|
||||||
|
kore_server_disconnect(req->owner);
|
||||||
|
|
||||||
net_send_flush(req->owner);
|
|
||||||
TAILQ_REMOVE(&http_requests, req, list);
|
TAILQ_REMOVE(&http_requests, req, list);
|
||||||
http_request_free(req);
|
http_request_free(req);
|
||||||
}
|
}
|
||||||
|
@ -265,6 +266,7 @@ http_header_recv(struct netbuf *nb)
|
||||||
if (nb->len > 2 && strncmp((p - 2), "\r\n\r\n", 4))
|
if (nb->len > 2 && strncmp((p - 2), "\r\n\r\n", 4))
|
||||||
return (KORE_RESULT_OK);
|
return (KORE_RESULT_OK);
|
||||||
|
|
||||||
|
nb->flags |= NETBUF_FORCE_REMOVE;
|
||||||
hbuf = kore_strdup((const char *)nb->buf);
|
hbuf = kore_strdup((const char *)nb->buf);
|
||||||
|
|
||||||
h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
|
h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
|
||||||
|
|
29
src/kore.c
29
src/kore.c
|
@ -43,6 +43,9 @@
|
||||||
|
|
||||||
static int efd = -1;
|
static int efd = -1;
|
||||||
static SSL_CTX *ssl_ctx = NULL;
|
static SSL_CTX *ssl_ctx = NULL;
|
||||||
|
|
||||||
|
static TAILQ_HEAD(, connection) disconnected;
|
||||||
|
|
||||||
int server_port = 0;
|
int server_port = 0;
|
||||||
char *server_ip = NULL;
|
char *server_ip = NULL;
|
||||||
|
|
||||||
|
@ -51,16 +54,17 @@ static int kore_server_sslstart(void);
|
||||||
static void kore_event(int, int, void *);
|
static void kore_event(int, int, void *);
|
||||||
static int kore_server_accept(struct listener *);
|
static int kore_server_accept(struct listener *);
|
||||||
static int kore_connection_handle(struct connection *, int);
|
static int kore_connection_handle(struct connection *, int);
|
||||||
|
static void kore_server_final_disconnect(struct connection *);
|
||||||
static int kore_server_bind(struct listener *, const char *, int);
|
static int kore_server_bind(struct listener *, const char *, int);
|
||||||
static int kore_ssl_npn_cb(SSL *, const u_char **, unsigned int *, void *);
|
static int kore_ssl_npn_cb(SSL *, const u_char **, unsigned int *, void *);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct connection *c;
|
|
||||||
struct listener server;
|
struct listener server;
|
||||||
struct epoll_event *events;
|
struct epoll_event *events;
|
||||||
int n, i, *fd;
|
int n, i, *fd;
|
||||||
|
struct connection *c, *cnext;
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
fatal("Usage: kore [config file]");
|
fatal("Usage: kore [config file]");
|
||||||
|
@ -80,6 +84,7 @@ main(int argc, char *argv[])
|
||||||
fatal("epoll_create(): %s", errno_s);
|
fatal("epoll_create(): %s", errno_s);
|
||||||
|
|
||||||
http_init();
|
http_init();
|
||||||
|
TAILQ_INIT(&disconnected);
|
||||||
|
|
||||||
kore_event(server.fd, EPOLLIN, &server);
|
kore_event(server.fd, EPOLLIN, &server);
|
||||||
events = kore_calloc(EPOLL_EVENTS, sizeof(struct epoll_event));
|
events = kore_calloc(EPOLL_EVENTS, sizeof(struct epoll_event));
|
||||||
|
@ -116,12 +121,28 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
http_process();
|
http_process();
|
||||||
|
|
||||||
|
for (c = TAILQ_FIRST(&disconnected); c != NULL; c = cnext) {
|
||||||
|
cnext = TAILQ_NEXT(c, list);
|
||||||
|
TAILQ_REMOVE(&disconnected, c, list);
|
||||||
|
kore_server_final_disconnect(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(server.fd);
|
close(server.fd);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kore_server_disconnect(struct connection *c)
|
||||||
|
{
|
||||||
|
if (c->state != CONN_STATE_DISCONNECTING) {
|
||||||
|
kore_log("preparing %p for disconnection", c);
|
||||||
|
c->state = CONN_STATE_DISCONNECTING;
|
||||||
|
TAILQ_INSERT_TAIL(&disconnected, c, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kore_server_sslstart(void)
|
kore_server_sslstart(void)
|
||||||
{
|
{
|
||||||
|
@ -230,13 +251,13 @@ kore_server_accept(struct listener *l)
|
||||||
return (KORE_RESULT_OK);
|
return (KORE_RESULT_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
kore_server_disconnect(struct connection *c)
|
kore_server_final_disconnect(struct connection *c)
|
||||||
{
|
{
|
||||||
struct netbuf *nb, *next;
|
struct netbuf *nb, *next;
|
||||||
struct spdy_stream *s, *snext;
|
struct spdy_stream *s, *snext;
|
||||||
|
|
||||||
kore_log("kore_server_disconnect(%p)", c);
|
kore_log("kore_server_final_disconnect(%p)", c);
|
||||||
|
|
||||||
close(c->fd);
|
close(c->fd);
|
||||||
if (c->ssl != NULL)
|
if (c->ssl != NULL)
|
||||||
|
|
27
src/net.c
27
src/net.c
|
@ -50,7 +50,6 @@ net_send_queue(struct connection *c, u_int8_t *data, size_t len, int flags,
|
||||||
nb->len = len;
|
nb->len = len;
|
||||||
nb->owner = c;
|
nb->owner = c;
|
||||||
nb->offset = 0;
|
nb->offset = 0;
|
||||||
nb->retain = 0;
|
|
||||||
nb->flags = flags;
|
nb->flags = flags;
|
||||||
nb->type = NETBUF_SEND;
|
nb->type = NETBUF_SEND;
|
||||||
|
|
||||||
|
@ -81,7 +80,6 @@ net_recv_queue(struct connection *c, size_t len, int flags,
|
||||||
nb->len = len;
|
nb->len = len;
|
||||||
nb->owner = c;
|
nb->owner = c;
|
||||||
nb->offset = 0;
|
nb->offset = 0;
|
||||||
nb->retain = 0;
|
|
||||||
nb->flags = flags;
|
nb->flags = flags;
|
||||||
nb->type = NETBUF_RECV;
|
nb->type = NETBUF_RECV;
|
||||||
nb->buf = (u_int8_t *)kore_malloc(nb->len);
|
nb->buf = (u_int8_t *)kore_malloc(nb->len);
|
||||||
|
@ -109,7 +107,7 @@ net_recv_expand(struct connection *c, struct netbuf *nb, size_t len,
|
||||||
nb->buf = (u_int8_t *)kore_realloc(nb->buf, nb->len);
|
nb->buf = (u_int8_t *)kore_realloc(nb->buf, nb->len);
|
||||||
TAILQ_INSERT_HEAD(&(c->recv_queue), nb, list);
|
TAILQ_INSERT_HEAD(&(c->recv_queue), nb, list);
|
||||||
|
|
||||||
return (net_recv(c));
|
return (KORE_RESULT_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -129,8 +127,8 @@ net_send(struct connection *c)
|
||||||
|
|
||||||
r = SSL_write(c->ssl, (nb->buf + nb->offset), (nb->len - nb->offset));
|
r = SSL_write(c->ssl, (nb->buf + nb->offset), (nb->len - nb->offset));
|
||||||
|
|
||||||
//kore_log("net_send(%ld/%ld bytes), progress with %d",
|
kore_log("net_send(%ld/%ld bytes), progress with %d",
|
||||||
// nb->offset, nb->len, r);
|
nb->offset, nb->len, r);
|
||||||
|
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
r = SSL_get_error(c->ssl, r);
|
r = SSL_get_error(c->ssl, r);
|
||||||
|
@ -146,7 +144,7 @@ net_send(struct connection *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
nb->offset += (size_t)r;
|
nb->offset += (size_t)r;
|
||||||
if (nb->offset == nb->len || (nb->flags & NETBUF_CALL_CB_ALWAYS)) {
|
if (nb->offset == nb->len) {
|
||||||
if (nb->offset == nb->len)
|
if (nb->offset == nb->len)
|
||||||
TAILQ_REMOVE(&(c->send_queue), nb, list);
|
TAILQ_REMOVE(&(c->send_queue), nb, list);
|
||||||
|
|
||||||
|
@ -169,6 +167,8 @@ net_send(struct connection *c)
|
||||||
int
|
int
|
||||||
net_send_flush(struct connection *c)
|
net_send_flush(struct connection *c)
|
||||||
{
|
{
|
||||||
|
kore_log("net_send_flush(%p)", c);
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&(c->send_queue)) &&
|
while (!TAILQ_EMPTY(&(c->send_queue)) &&
|
||||||
(c->flags & CONN_WRITE_POSSIBLE)) {
|
(c->flags & CONN_WRITE_POSSIBLE)) {
|
||||||
if (!net_send(c))
|
if (!net_send(c))
|
||||||
|
@ -190,8 +190,8 @@ net_recv(struct connection *c)
|
||||||
nb = TAILQ_FIRST(&(c->recv_queue));
|
nb = TAILQ_FIRST(&(c->recv_queue));
|
||||||
r = SSL_read(c->ssl, (nb->buf + nb->offset), (nb->len - nb->offset));
|
r = SSL_read(c->ssl, (nb->buf + nb->offset), (nb->len - nb->offset));
|
||||||
|
|
||||||
//kore_log("net_recv(%ld/%ld bytes), progress with %d",
|
kore_log("net_recv(%ld/%ld bytes), progress with %d",
|
||||||
// nb->offset, nb->len, r);
|
nb->offset, nb->len, r);
|
||||||
|
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
r = SSL_get_error(c->ssl, r);
|
r = SSL_get_error(c->ssl, r);
|
||||||
|
@ -213,13 +213,10 @@ net_recv(struct connection *c)
|
||||||
return (KORE_RESULT_ERROR);
|
return (KORE_RESULT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
nb->retain++;
|
|
||||||
if (nb->offset == nb->len)
|
|
||||||
TAILQ_REMOVE(&(c->recv_queue), nb, list);
|
|
||||||
r = nb->cb(nb);
|
r = nb->cb(nb);
|
||||||
nb->retain--;
|
if (nb->offset == nb->len ||
|
||||||
|
(nb->flags & NETBUF_FORCE_REMOVE)) {
|
||||||
if (nb->retain == 0 && nb->offset == nb->len) {
|
TAILQ_REMOVE(&(c->recv_queue), nb, list);
|
||||||
free(nb->buf);
|
free(nb->buf);
|
||||||
free(nb);
|
free(nb);
|
||||||
}
|
}
|
||||||
|
@ -233,6 +230,8 @@ net_recv(struct connection *c)
|
||||||
int
|
int
|
||||||
net_recv_flush(struct connection *c)
|
net_recv_flush(struct connection *c)
|
||||||
{
|
{
|
||||||
|
kore_log("net_recv_flush(%p)", c);
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&(c->recv_queue)) &&
|
while (!TAILQ_EMPTY(&(c->recv_queue)) &&
|
||||||
(c->flags & CONN_READ_POSSIBLE)) {
|
(c->flags & CONN_READ_POSSIBLE)) {
|
||||||
if (!net_recv(c))
|
if (!net_recv(c))
|
||||||
|
|
Loading…
Reference in New Issue