rework disconnecting clients and fix bug where spdy ocnnections could segfault after disconnecting

This commit is contained in:
Joris Vink 2013-05-02 09:10:35 +02:00
parent fdb9004c6d
commit 364dc58219
4 changed files with 56 additions and 31 deletions

View File

@ -33,7 +33,6 @@ struct netbuf {
u_int32_t offset;
u_int32_t len;
u_int8_t type;
u_int8_t retain;
u_int8_t flags;
void *owner;
@ -47,9 +46,10 @@ struct listener {
struct sockaddr_in sin;
};
#define CONN_STATE_UNKNOWN 0
#define CONN_STATE_SSL_SHAKE 1
#define CONN_STATE_ESTABLISHED 2
#define CONN_STATE_UNKNOWN 0
#define CONN_STATE_SSL_SHAKE 1
#define CONN_STATE_ESTABLISHED 2
#define CONN_STATE_DISCONNECTING 3
#define CONN_PROTO_UNKNOWN 0
#define CONN_PROTO_SPDY 1
@ -59,6 +59,7 @@ struct listener {
#define CONN_WRITE_POSSIBLE 0x02
#define NETBUF_CALL_CB_ALWAYS 0x01
#define NETBUF_FORCE_REMOVE 0x02
struct connection {
int fd;
@ -79,6 +80,8 @@ struct connection {
u_int32_t client_stream_id;
TAILQ_HEAD(, spdy_stream) spdy_streams;
TAILQ_ENTRY(connection) list;
};
#define HANDLER_TYPE_STATIC 1

View File

@ -222,7 +222,7 @@ void
http_process(void)
{
struct http_request *req, *next;
int (*handler)(struct http_request *);
int r, (*handler)(struct http_request *);
if (TAILQ_EMPTY(&http_requests))
return;
@ -232,15 +232,16 @@ http_process(void)
next = TAILQ_NEXT(req, list);
handler = kore_module_handler_find(req->path);
if (handler == NULL) {
if (!http_generic_404(req))
kore_server_disconnect(req->owner);
} else {
if (!handler(req))
kore_server_disconnect(req->owner);
}
if (handler == NULL)
r = http_generic_404(req);
else
r = handler(req);
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);
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))
return (KORE_RESULT_OK);
nb->flags |= NETBUF_FORCE_REMOVE;
hbuf = kore_strdup((const char *)nb->buf);
h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);

View File

@ -43,6 +43,9 @@
static int efd = -1;
static SSL_CTX *ssl_ctx = NULL;
static TAILQ_HEAD(, connection) disconnected;
int server_port = 0;
char *server_ip = NULL;
@ -51,16 +54,17 @@ static int kore_server_sslstart(void);
static void kore_event(int, int, void *);
static int kore_server_accept(struct listener *);
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_ssl_npn_cb(SSL *, const u_char **, unsigned int *, void *);
int
main(int argc, char *argv[])
{
struct connection *c;
struct listener server;
struct epoll_event *events;
int n, i, *fd;
struct connection *c, *cnext;
if (argc != 2)
fatal("Usage: kore [config file]");
@ -80,6 +84,7 @@ main(int argc, char *argv[])
fatal("epoll_create(): %s", errno_s);
http_init();
TAILQ_INIT(&disconnected);
kore_event(server.fd, EPOLLIN, &server);
events = kore_calloc(EPOLL_EVENTS, sizeof(struct epoll_event));
@ -116,12 +121,28 @@ main(int argc, char *argv[])
}
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);
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
kore_server_sslstart(void)
{
@ -230,13 +251,13 @@ kore_server_accept(struct listener *l)
return (KORE_RESULT_OK);
}
void
kore_server_disconnect(struct connection *c)
static void
kore_server_final_disconnect(struct connection *c)
{
struct netbuf *nb, *next;
struct spdy_stream *s, *snext;
kore_log("kore_server_disconnect(%p)", c);
kore_log("kore_server_final_disconnect(%p)", c);
close(c->fd);
if (c->ssl != NULL)

View File

@ -50,7 +50,6 @@ net_send_queue(struct connection *c, u_int8_t *data, size_t len, int flags,
nb->len = len;
nb->owner = c;
nb->offset = 0;
nb->retain = 0;
nb->flags = flags;
nb->type = NETBUF_SEND;
@ -81,7 +80,6 @@ net_recv_queue(struct connection *c, size_t len, int flags,
nb->len = len;
nb->owner = c;
nb->offset = 0;
nb->retain = 0;
nb->flags = flags;
nb->type = NETBUF_RECV;
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);
TAILQ_INSERT_HEAD(&(c->recv_queue), nb, list);
return (net_recv(c));
return (KORE_RESULT_OK);
}
int
@ -129,8 +127,8 @@ net_send(struct connection *c)
r = SSL_write(c->ssl, (nb->buf + nb->offset), (nb->len - nb->offset));
//kore_log("net_send(%ld/%ld bytes), progress with %d",
// nb->offset, nb->len, r);
kore_log("net_send(%ld/%ld bytes), progress with %d",
nb->offset, nb->len, r);
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
@ -146,7 +144,7 @@ net_send(struct connection *c)
}
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)
TAILQ_REMOVE(&(c->send_queue), nb, list);
@ -169,6 +167,8 @@ net_send(struct connection *c)
int
net_send_flush(struct connection *c)
{
kore_log("net_send_flush(%p)", c);
while (!TAILQ_EMPTY(&(c->send_queue)) &&
(c->flags & CONN_WRITE_POSSIBLE)) {
if (!net_send(c))
@ -190,8 +190,8 @@ net_recv(struct connection *c)
nb = TAILQ_FIRST(&(c->recv_queue));
r = SSL_read(c->ssl, (nb->buf + nb->offset), (nb->len - nb->offset));
//kore_log("net_recv(%ld/%ld bytes), progress with %d",
// nb->offset, nb->len, r);
kore_log("net_recv(%ld/%ld bytes), progress with %d",
nb->offset, nb->len, r);
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
@ -213,13 +213,10 @@ net_recv(struct connection *c)
return (KORE_RESULT_ERROR);
}
nb->retain++;
if (nb->offset == nb->len)
TAILQ_REMOVE(&(c->recv_queue), nb, list);
r = nb->cb(nb);
nb->retain--;
if (nb->retain == 0 && nb->offset == nb->len) {
if (nb->offset == nb->len ||
(nb->flags & NETBUF_FORCE_REMOVE)) {
TAILQ_REMOVE(&(c->recv_queue), nb, list);
free(nb->buf);
free(nb);
}
@ -233,6 +230,8 @@ net_recv(struct connection *c)
int
net_recv_flush(struct connection *c)
{
kore_log("net_recv_flush(%p)", c);
while (!TAILQ_EMPTY(&(c->recv_queue)) &&
(c->flags & CONN_READ_POSSIBLE)) {
if (!net_recv(c))