commit 769c78a6e8448563d77ca12b9c80b65cb552ad99
parent a88e56ae25b29a5c76d807b1d78049668a24dac5
Author: Joris Vink <joris@coders.se>
Date: Fri, 27 Nov 2015 16:22:50 +0100
Introduce NOHTTP=1 build option.
This basically turns off the HTTP layer for Kore. It does not
compile in anything for HTTP.
This allows Kore to be used as a network application platform as well.
Added an example for this called nohttp.
Other changes that sneaked in while hacking on this:
* Use calloc(), kill pendantic malloc option.
* Killed off SPDY/3.1 support completely, will be superseded by http2
Note that comes with massive changes to a lot of the core API
functions provided by Kore, these might break your application.
Diffstat:
31 files changed, 565 insertions(+), 1830 deletions(-)
diff --git a/Makefile b/Makefile
@@ -6,30 +6,35 @@ KORE=kore
INSTALL_DIR=$(PREFIX)/bin
INCLUDE_DIR=$(PREFIX)/include/kore
-S_SRC= src/kore.c src/accesslog.c src/auth.c src/buf.c src/cli.c \
- src/config.c src/connection.c src/domain.c src/http.c src/mem.c \
- src/msg.c src/module.c src/net.c src/pool.c src/spdy.c src/timer.c \
- src/validator.c src/utils.c src/websocket.c src/worker.c \
- src/zlib_dict.c
+S_SRC= src/kore.c src/buf.c src/cli.c src/config.c src/connection.c \
+ src/domain.c src/mem.c src/msg.c src/module.c src/net.c \
+ src/pool.c src/timer.c src/utils.c src/worker.c
S_OBJS= $(S_SRC:.c=.o)
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+=-Wsign-compare -Iincludes -g
CFLAGS+=-DPREFIX='"$(PREFIX)"'
-LDFLAGS+=-rdynamic -lssl -lcrypto -lz
+LDFLAGS=-rdynamic -lssl -lcrypto
ifneq ("$(DEBUG)", "")
CFLAGS+=-DKORE_DEBUG
endif
-ifneq ("$(KORE_PEDANTIC_MALLOC)", "")
- CFLAGS+=-DKORE_PEDANTIC_MALLOC
+ifneq ("$(NOHTTP)", "")
+ CFLAGS+=-DKORE_NO_HTTP
+else
+ S_SRC+= src/auth.c src/accesslog.c src/http.c \
+ src/validator.c src/websocket.c src/zlib_dict.c
endif
ifneq ("$(NOTLS)", "")
CFLAGS+=-DKORE_NO_TLS
- LDFLAGS=-rdynamic -lz -lcrypto
+ ifneq ("$(NOHTTP)", "")
+ LDFLAGS=-rdynamic
+ else
+ LDFLAGS=-rdynamic -lcrypto
+ endif
endif
ifneq ("$(PGSQL)", "")
diff --git a/README.md b/README.md
@@ -11,7 +11,6 @@ Because of this Kore is an ideal candidate for building robust, scalable and sec
Features
--------
* Supports SNI
-* Supports SPDY/3.1
* Supports HTTP/1.1
* Websocket support
* Lightweight background tasks
@@ -52,8 +51,8 @@ Building Kore
-------------
Requirements
-* libz
-* openssl >= 1.0.1i
+* openssl (latest is always the safest bet, right?)
+ (note: this requirement drops away when building with NOTLS=1 NOHTTP=1)
Requirements for background tasks (optional)
* pthreads
@@ -64,7 +63,6 @@ Requirements for pgsql (optional)
Normal compilation and installation:
```
-# git clone https://github.com/jorisvink/kore.git
# cd kore
# make
# make install
@@ -77,7 +75,7 @@ those by setting a shell environment variable before running **_make_**.
* PGSQL=1 (compiles in pgsql support)
* DEBUG=1 (enables use of -d for debug)
* NOTLS=1 (compiles Kore without TLS)
-* KORE_PEDANTIC_MALLOC=1 (zero all allocated memory)
+* NOHTTP=1 (compiles Kore without HTTP support)
Example libraries
-----------------
diff --git a/conf/kore.conf.example b/conf/kore.conf.example
@@ -104,10 +104,6 @@ validator v_session function v_session_validate
# a generated DH key (See OpenSSL dhparam).
#tls_dhparam dh2048.pem
-# Specify the amount of seconds a SPDY connection is kept open.
-# You can keep it open indefinitely by setting this to 0.
-#spdy_idle_time 120
-
# Authentication configuration
#
# Using authentication blocks you can define a standard way for
@@ -187,7 +183,6 @@ domain localhost {
static / serve_index
static /intro.jpg serve_intro
static /b64test serve_b64test
- static /spdy-reset serve_spdyreset
static /upload serve_file_upload
static /lock-test serve_lock_test
static /validator serve_validator
diff --git a/examples/generic/conf/generic.conf b/examples/generic/conf/generic.conf
@@ -26,7 +26,6 @@ domain 127.0.0.1 {
static / serve_index
static /intro.jpg serve_intro
static /b64test serve_b64test
- static /spdy-reset serve_spdyreset
static /upload serve_file_upload
static /validator serve_validator
static /params-test serve_params_test
diff --git a/examples/generic/src/example.c b/examples/generic/src/example.c
@@ -25,7 +25,6 @@ int serve_style_css(struct http_request *);
int serve_index(struct http_request *);
int serve_intro(struct http_request *);
int serve_b64test(struct http_request *);
-int serve_spdyreset(struct http_request *);
int serve_file_upload(struct http_request *);
int serve_validator(struct http_request *);
int serve_params_test(struct http_request *);
@@ -133,13 +132,6 @@ serve_b64test(struct http_request *req)
}
int
-serve_spdyreset(struct http_request *req)
-{
- spdy_session_teardown(req->owner, SPDY_SESSION_ERROR_OK);
- return (KORE_RESULT_OK);
-}
-
-int
serve_file_upload(struct http_request *req)
{
int r;
diff --git a/examples/ktunnel/src/ktunnel.c b/examples/ktunnel/src/ktunnel.c
@@ -163,7 +163,7 @@ ktunnel_pipe_data(struct netbuf *nb)
printf("received %d bytes on pipe %p (-> %p)\n", nb->s_off, src, dst);
- net_send_queue(dst, nb->buf, nb->s_off, NULL, NETBUF_LAST_CHAIN);
+ net_send_queue(dst, nb->buf, nb->s_off);
net_send_flush(dst);
net_recv_reset(src, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data);
diff --git a/examples/nohttp/.gitignore b/examples/nohttp/.gitignore
@@ -0,0 +1,5 @@
+*.o
+.objs
+nohttp.so
+assets.h
+cert
diff --git a/examples/nohttp/README.md b/examples/nohttp/README.md
@@ -0,0 +1,16 @@
+Kore NOHTTP example
+
+Note that this example only works if Kore was built with NOHTTP=1.
+
+Run:
+```
+ $ kore run
+```
+
+Test:
+```
+ Connect to the server using openssl s_client, you will notice
+ that anything sent is submitted back to your client.
+
+ $ openssl s_client -connect 127.0.0.1:8888
+```
diff --git a/examples/nohttp/conf/nohttp.conf b/examples/nohttp/conf/nohttp.conf
@@ -0,0 +1,22 @@
+# Kore can be used as a network layer if it was
+# built with NOHTTP=1.
+#
+# With this you can bind a callback for every new
+# connection that has been established. For TLS connections
+# the callback is called after the TLS handshake is completed.
+
+# We must load the module first as we need the callback from it.
+load ./nohttp.so
+
+# Listen on port 8888 and call connection_setup for each new connection.
+bind 127.0.0.1 8888 connection_setup
+
+# TLS dh params.
+tls_dhparam dh2048.pem
+
+# We must still define a domain to use TLS. This might go away
+# in the future for NOHTTP=1
+domain 127.0.0.1 {
+ certfile cert/server.crt
+ certkey cert/server.key
+}
diff --git a/examples/nohttp/src/nohttp.c b/examples/nohttp/src/nohttp.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 Joris Vink <joris@coders.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Example of using Kore as a network application server.
+ *
+ * We will get called for every new connection that has been established.
+ * For TLS connections we will get called after the TLS handshake completed.
+ *
+ * From the setup we can queue up our own read commands and do whatever we
+ * like with the newly connected client.
+ */
+
+#include <kore/kore.h>
+
+void connection_setup(struct connection *);
+int connection_recv_data(struct netbuf *);
+
+void
+connection_setup(struct connection *c)
+{
+ kore_log(LOG_NOTICE, "%p: new connection", c);
+
+ /*
+ * Setup a read command that will read up to 128 bytes and will
+ * always call the callback connection_recv_data even if not all
+ * 128 bytes were read.
+ */
+ net_recv_queue(c, 128, NETBUF_CALL_CB_ALWAYS, connection_recv_data);
+}
+
+/*
+ * This function is called everytime we get up to 128 bytes of data.
+ * The connection can be found under nb->owner.
+ * The data received can be found under nb->buf.
+ * The length of the received data can be found under s_off.
+ */
+int
+connection_recv_data(struct netbuf *nb)
+{
+ struct connection *c = (struct connection *)nb->owner;
+
+ kore_log(LOG_NOTICE, "%p: received %u bytes", c, nb->s_off);
+
+ /* We will just dump these back to the client. */
+ net_send_queue(c, nb->buf, nb->s_off);
+ net_send_flush(c);
+
+ /* Now reset the receive command for the next one. */
+ net_recv_reset(c, 128, connection_recv_data);
+
+ return (KORE_RESULT_OK);
+}
diff --git a/examples/sse/conf/sse.conf b/examples/sse/conf/sse.conf
@@ -5,7 +5,6 @@ load ./sse.so
tls_dhparam dh2048.pem
http_keepalive_time 600
-spdy_idle_time 600
domain 127.0.0.1 {
certfile cert/server.crt
diff --git a/examples/sse/src/sse.c b/examples/sse/src/sse.c
@@ -16,7 +16,6 @@
/*
* Simple example of how SSE (Server Side Events) could be used in Kore.
- * We deal with SSE both over normal HTTP/1.1 and over SPDY connections.
*
* Upon new arrivals, a join event is broadcast to all clients.
* If a client goes away a leave event is broadcasted.
@@ -35,7 +34,6 @@ int subscribe(struct http_request *);
void sse_disconnect(struct connection *);
void sse_send(struct connection *, void *, size_t);
void sse_broadcast(struct connection *, void *, size_t);
-void sse_spdy_stream_closed(struct connection *, struct spdy_stream *);
int check_header(struct http_request *, const char *, const char *);
/*
@@ -43,7 +41,6 @@ int check_header(struct http_request *, const char *, const char *);
* to their hdlr_extra pointer member.
*/
struct sse_state {
- struct spdy_stream *stream;
struct kore_timer *timer;
};
@@ -94,30 +91,14 @@ subscribe(struct http_request *req)
/* Set a disconnection method so we know when this client goes away. */
req->owner->disconnect = sse_disconnect;
- /* For non SPDY clients we do not expect any more data to arrive. */
- if (req->owner->proto != CONN_PROTO_SPDY)
- req->owner->flags |= CONN_READ_BLOCK;
+ /* We do not expect any more data to arrive. */
+ req->owner->flags |= CONN_READ_BLOCK;
/* Allocate a state to be carried by our connection. */
state = kore_malloc(sizeof(*state));
state->stream = req->stream;
req->owner->hdlr_extra = state;
- /* SSE over SPDY will need this extra love. */
- if (req->owner->proto == CONN_PROTO_SPDY) {
- /* Unset the http request attached to our SPDY stream. */
- req->stream->httpreq = NULL;
-
- /*
- * Do not let the stream close unless a RST occurs or
- * until we close it ourselves.
- */
- req->stream->flags |= SPDY_NO_CLOSE;
-
- /* Set a callback in case this stream gets a RST. */
- req->stream->onclose = sse_spdy_stream_closed;
- }
-
/* Now start a timer to send a ping back every 10 second. */
state->timer = kore_timer_add(sse_ping, 10000, req->owner, 0);
@@ -151,23 +132,6 @@ sse_send(struct connection *c, void *data, size_t len)
if (state == NULL)
return;
- /* SPDY connections need this extra bit of magic. */
- if (c->proto == CONN_PROTO_SPDY) {
- if (state->stream == NULL) {
- kore_log(LOG_ERR, "no SPDY stream for sse_send()");
- kore_connection_disconnect(c);
- return;
- }
-
- /*
- * Tell Kore to send a dataframe prelude + increase the
- * length of our stream to be sent.
- */
- if (state->stream->send_size == 0)
- state->stream->flags |= SPDY_DATAFRAME_PRELUDE;
- state->stream->send_size += len;
- }
-
/* Queue outgoing data now. */
net_send_queue(c, data, len, state->stream, NETBUF_LAST_CHAIN);
net_send_flush(c);
@@ -194,12 +158,6 @@ sse_disconnect(struct connection *c)
/* Tell others we are leaving. */
sse_broadcast(c, leaving, strlen(leaving));
- /* Make sure we cleanup our hooked stream if any. */
- if (c->proto == CONN_PROTO_SPDY && state->stream != NULL) {
- state->stream->onclose = NULL;
- spdy_stream_close(c, state->stream, SPDY_REMOVE_NETBUFS);
- }
-
/* Kill our timer and free/remove the state. */
kore_timer_remove(state->timer);
kore_mem_free(state);
@@ -209,23 +167,6 @@ sse_disconnect(struct connection *c)
c->disconnect = NULL;
}
-void
-sse_spdy_stream_closed(struct connection *c, struct spdy_stream *s)
-{
- struct sse_state *state = c->hdlr_extra;
-
- /* Paranoia. */
- if (state->stream != s) {
- state->stream = NULL;
- kore_connection_disconnect(c);
- return;
- }
-
- /* Set our stream to NULL and call sse_disconnect. */
- state->stream = NULL;
- sse_disconnect(c);
-}
-
int
check_header(struct http_request *req, const char *name, const char *value)
{
diff --git a/examples/video_stream/conf/video_stream.conf b/examples/video_stream/conf/video_stream.conf
@@ -5,7 +5,6 @@ load ./video_stream.so init
tls_dhparam dh2048.pem
-spdy_idle_time 600
http_keepalive_time 600
domain 127.0.0.1 {
diff --git a/includes/http.h b/includes/http.h
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#if !defined(KORE_NO_HTTP)
+
#ifndef __H_HTTP_H
#define __H_HTTP_H
@@ -183,7 +185,6 @@ struct http_request {
char *path;
char *agent;
struct connection *owner;
- struct spdy_stream *stream;
struct kore_buf *http_body;
void *hdlr_extra;
char *query_string;
@@ -230,8 +231,8 @@ int http_request_header(struct http_request *,
const char *, char **);
void http_response_header(struct http_request *,
const char *, const char *);
-int http_request_new(struct connection *, struct spdy_stream *,
- const char *, const char *, const char *, const char *,
+int http_request_new(struct connection *, const char *,
+ const char *, const char *, const char *,
struct http_request **);
int http_state_run(struct http_state *, u_int8_t,
struct http_request *);
@@ -294,3 +295,5 @@ enum http_status_code {
}
#endif
#endif /* !__H_HTTP_H */
+
+#endif /* ! KORE_NO_HTTP */
diff --git a/includes/kore.h b/includes/kore.h
@@ -46,8 +46,6 @@ extern "C" {
extern int daemon(int, int);
#endif
-#include "spdy.h"
-
#define KORE_RESULT_ERROR 0
#define KORE_RESULT_OK 1
#define KORE_RESULT_RETRY 2
@@ -95,8 +93,10 @@ extern int daemon(int, int);
#define X509_CN_LENGTH (ub_common_name + 1)
/* XXX hackish. */
+#if !defined(KORE_NO_HTTP)
struct http_request;
-struct spdy_stream;
+#endif
+struct connection;
struct netbuf {
u_int8_t *buf;
@@ -107,7 +107,6 @@ struct netbuf {
u_int8_t flags;
void *owner;
- struct spdy_stream *stream;
void *extra;
int (*cb)(struct netbuf *);
@@ -124,9 +123,9 @@ TAILQ_HEAD(netbuf_head, netbuf);
struct listener {
u_int8_t type;
-
- int fd;
u_int8_t addrtype;
+ int fd;
+ void (*connect)(struct connection *);
union {
struct sockaddr_in ipv4;
@@ -144,10 +143,9 @@ LIST_HEAD(listener_head, listener);
#define CONN_STATE_DISCONNECTING 3
#define CONN_PROTO_UNKNOWN 0
-#define CONN_PROTO_SPDY 1
-#define CONN_PROTO_HTTP 2
-#define CONN_PROTO_WEBSOCKET 3
-#define CONN_PROTO_MSG 4
+#define CONN_PROTO_HTTP 1
+#define CONN_PROTO_WEBSOCKET 2
+#define CONN_PROTO_MSG 3
#define CONN_READ_POSSIBLE 0x01
#define CONN_WRITE_POSSIBLE 0x02
@@ -155,7 +153,6 @@ LIST_HEAD(listener_head, listener);
#define CONN_IDLE_TIMER_ACT 0x10
#define CONN_READ_BLOCK 0x20
#define CONN_CLOSE_EMPTY 0x40
-#define SPDY_CONN_GOAWAY 0x80
#define KORE_IDLE_TIMER_MAX 20000
@@ -202,22 +199,13 @@ struct connection {
u_int64_t start;
} idle_timer;
- u_int8_t inflate_started;
- z_stream z_inflate;
- u_int8_t deflate_started;
- z_stream z_deflate;
-
- u_int32_t wsize_initial;
- u_int32_t spdy_send_wsize;
- u_int32_t spdy_recv_wsize;
-
struct netbuf_head send_queue;
struct netbuf *snb;
struct netbuf *rnb;
- u_int32_t client_stream_id;
- TAILQ_HEAD(, spdy_stream) spdy_streams;
+#if !defined(KORE_NO_HTTP)
TAILQ_HEAD(, http_request) http_requests;
+#endif
TAILQ_ENTRY(connection) list;
TAILQ_ENTRY(connection) flush_list;
@@ -227,6 +215,8 @@ TAILQ_HEAD(connection_list, connection);
extern struct connection_list connections;
extern struct connection_list disconnected;
+#if !defined(KORE_NO_HTTP)
+
struct kore_handler_params {
char *name;
u_int8_t method;
@@ -249,12 +239,14 @@ struct kore_auth {
TAILQ_ENTRY(kore_auth) list;
};
-#define KORE_MODULE_LOAD 1
-#define KORE_MODULE_UNLOAD 2
-
#define HANDLER_TYPE_STATIC 1
#define HANDLER_TYPE_DYNAMIC 2
+#endif
+
+#define KORE_MODULE_LOAD 1
+#define KORE_MODULE_UNLOAD 2
+
struct kore_module {
void *handle;
char *path;
@@ -274,9 +266,10 @@ struct kore_module_handle {
int errors;
regex_t rctx;
struct kore_domain *dom;
+#if !defined(KORE_NO_HTTP)
struct kore_auth *auth;
-
TAILQ_HEAD(, kore_handler_params) params;
+#endif
TAILQ_ENTRY(kore_module_handle) list;
};
@@ -304,6 +297,8 @@ struct kore_domain {
TAILQ_HEAD(kore_domain_h, kore_domain);
+#if !defined(KORE_NO_HTTP)
+
#define KORE_VALIDATOR_TYPE_REGEX 1
#define KORE_VALIDATOR_TYPE_FUNCTION 2
@@ -316,6 +311,7 @@ struct kore_validator {
TAILQ_ENTRY(kore_validator) list;
};
+#endif
#define KORE_BUF_INITIAL 128
#define KORE_BUF_INCREMENT KORE_BUF_INITIAL
@@ -394,7 +390,6 @@ extern int tls_version;
extern DH *tls_dhparam;
extern u_int8_t nlisteners;
-extern u_int64_t spdy_idle_time;
extern u_int16_t cpu_count;
extern u_int8_t worker_count;
extern u_int8_t worker_set_affinity;
@@ -441,10 +436,12 @@ void kore_accesslog_init(void);
void kore_accesslog_worker_init(void);
int kore_accesslog_write(const void *, u_int32_t);
+#if !defined(KORE_NO_HTTP)
int kore_auth_run(struct http_request *, struct kore_auth *);
void kore_auth_init(void);
int kore_auth_new(const char *);
struct kore_auth *kore_auth_lookup(const char *);
+#endif
void kore_timer_init(void);
u_int64_t kore_timer_run(u_int64_t);
@@ -453,8 +450,7 @@ struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t),
u_int64_t, void *, int);
int kore_tls_sni_cb(SSL *, int *, void *);
-int kore_server_bind(const char *, const char *);
-int kore_tls_npn_cb(SSL *, const u_char **, unsigned int *, void *);
+int kore_server_bind(const char *, const char *, const char *);
void kore_tls_info_callback(const SSL *, int, int);
void kore_connection_init(void);
@@ -482,10 +478,6 @@ void *kore_realloc(void *, size_t);
void kore_mem_free(void *);
void kore_mem_init(void);
-#if defined(KORE_PEDANTIC_MALLOC)
-void explicit_bzero(void *, size_t);
-#endif
-
void *kore_pool_get(struct kore_pool *);
void kore_pool_put(struct kore_pool *, void *);
void kore_pool_init(struct kore_pool *, const char *,
@@ -506,19 +498,21 @@ int kore_base64_encode(u_int8_t *, u_int32_t, char **);
int kore_base64_decode(char *, u_int8_t **, u_int32_t *);
void *kore_mem_find(void *, size_t, void *, u_int32_t);
+#if !defined(KORE_NO_HTTP)
void kore_websocket_handshake(struct http_request *,
struct kore_wscbs *);
void kore_websocket_send(struct connection *,
u_int8_t, const void *, size_t);
void kore_websocket_broadcast(struct connection *,
u_int8_t, const void *, size_t, int);
+#endif
void kore_msg_init(void);
void kore_msg_worker_init(void);
void kore_msg_parent_init(void);
void kore_msg_parent_add(struct kore_worker *);
void kore_msg_parent_remove(struct kore_worker *);
-void kore_msg_send(u_int16_t, u_int8_t, void *, u_int32_t);
+void kore_msg_send(u_int16_t, u_int8_t, const void *, u_int32_t);
int kore_msg_register(u_int8_t,
void (*cb)(struct kore_msg *, const void *));
@@ -540,6 +534,7 @@ struct kore_domain *kore_domain_lookup(const char *);
struct kore_module_handle *kore_module_handler_find(const char *,
const char *);
+#if !defined(KORE_NO_HTTP)
void kore_validator_init(void);
void kore_validator_reload(void);
int kore_validator_add(const char *, u_int8_t, const char *);
@@ -547,6 +542,7 @@ int kore_validator_run(struct http_request *, const char *, char *);
int kore_validator_check(struct http_request *,
struct kore_validator *, void *);
struct kore_validator *kore_validator_lookup(const char *);
+#endif
void fatal(const char *, ...) __attribute__((noreturn));
void kore_debug_internal(char *, int, const char *, ...);
@@ -573,11 +569,9 @@ void net_recv_queue(struct connection *, u_int32_t, int,
int (*cb)(struct netbuf *));
void net_recv_expand(struct connection *c, u_int32_t,
int (*cb)(struct netbuf *));
-void net_send_queue(struct connection *, const void *,
- u_int32_t, struct spdy_stream *, int);
+void net_send_queue(struct connection *, const void *, u_int32_t);
void net_send_stream(struct connection *, void *,
- u_int32_t, struct spdy_stream *,
- int (*cb)(struct netbuf *), struct netbuf **);
+ u_int32_t, int (*cb)(struct netbuf *), struct netbuf **);
void kore_buf_free(struct kore_buf *);
struct kore_buf *kore_buf_create(u_int32_t);
@@ -589,26 +583,6 @@ void kore_buf_appendv(struct kore_buf *, const char *, va_list);
void kore_buf_appendb(struct kore_buf *, struct kore_buf *);
void kore_buf_replace_string(struct kore_buf *, char *, void *, size_t);
-struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t);
-int spdy_stream_get_header(struct spdy_header_block *,
- const char *, char **);
-void spdy_update_wsize(struct connection *,
- struct spdy_stream *, u_int32_t);
-
-int spdy_frame_recv(struct netbuf *);
-int spdy_dataframe_begin(struct connection *);
-void spdy_session_teardown(struct connection *c, u_int8_t);
-void spdy_frame_send(struct connection *, u_int16_t,
- u_int8_t, u_int32_t, struct spdy_stream *, u_int32_t);
-void spdy_header_block_add(struct spdy_header_block *,
- char *, char *);
-u_int8_t *spdy_header_block_release(struct connection *,
- struct spdy_header_block *, u_int32_t *);
-void spdy_stream_close(struct connection *,
- struct spdy_stream *, int);
-
-struct spdy_header_block *spdy_header_block_create(int);
-
#if defined(__cplusplus)
}
#endif
diff --git a/includes/spdy.h b/includes/spdy.h
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef __H_SPDY_H
-#define __H_SPDY_H
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/* XXX */
-struct connection;
-struct http_request;
-
-struct spdy_ctrl_frame {
- u_int16_t version;
- u_int16_t type;
- u_int8_t flags;
- u_int32_t length;
-};
-
-struct spdy_data_frame {
- u_int32_t stream_id;
- u_int8_t flags;
- u_int32_t length;
-};
-
-struct spdy_syn_stream {
- u_int32_t stream_id;
- u_int32_t assoc_stream_id;
- u_int8_t slot;
- u_int8_t reserved;
- u_int8_t prio;
-};
-
-struct spdy_header_block {
- u_int8_t *header_block;
- u_int32_t header_block_len;
- u_int32_t header_offset;
- u_int32_t header_pairs;
-};
-
-struct spdy_stream {
- u_int32_t stream_id;
- u_int8_t flags;
- u_int8_t prio;
- u_int64_t post_size;
- u_int64_t send_size;
- u_int32_t frame_size;
- u_int32_t recv_wsize;
- u_int32_t send_wsize;
- void (*onclose)(struct connection *, struct spdy_stream *);
-
- struct http_request *httpreq;
- struct spdy_header_block *hblock;
- TAILQ_ENTRY(spdy_stream) list;
-};
-
-extern const unsigned char SPDY_dictionary_txt[];
-
-#if defined(__cplusplus)
-}
-#endif
-
-#define KORE_SSL_PROTO_STRING "\x08spdy/3.1\x08http/1.1"
-#define SPDY_CONTROL_FRAME(x) ((x & (1 << 31)))
-
-#define SPDY_FRAME_SIZE 8
-#define SPDY_SYNFRAME_SIZE 10
-#define SPDY_ZLIB_DICT_SIZE 1423
-#define SPDY_ZLIB_CHUNK 16348
-#define SPDY_INIT_WSIZE 65536
-
-/* control frames */
-#define SPDY_CTRL_FRAME_SYN_STREAM 1
-#define SPDY_CTRL_FRAME_SYN_REPLY 2
-#define SPDY_CTRL_FRAME_RST_STREAM 3
-#define SPDY_CTRL_FRAME_SETTINGS 4
-#define SPDY_CTRL_FRAME_PING 6
-#define SPDY_CTRL_FRAME_GOAWAY 7
-#define SPDY_CTRL_FRAME_WINDOW 9
-#define SPDY_DATA_FRAME 99
-
-/* session error codes */
-#define SPDY_SESSION_ERROR_OK 0
-#define SPDY_SESSION_ERROR_PROTOCOL 1
-#define SPDY_SESSION_ERROR_INTERNAL 2
-
-/* flags */
-#define FLAG_FIN 0x01
-#define FLAG_UNIDIRECTIONAL 0x02
-
-/* settings */
-#define SETTINGS_UPLOAD_BANDWIDTH 1
-#define SETTINGS_DOWNLOAD_BANDWIDTH 2
-#define SETTINGS_ROUND_TRIP_TIME 3
-#define SETTINGS_MAX_CONCURRENT_STREAMS 4
-#define SETTINGS_CURRENT_CWND 5
-#define SETTINGS_DOWNLOAD_RETRANS_RATE 6
-#define SETTINGS_INITIAL_WINDOW_SIZE 7
-#define SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE 8
-
-#define SPDY_HBLOCK_NORMAL 0
-#define SPDY_HBLOCK_DELAYED_ALLOC 1
-
-#define SPDY_FLOW_WINDOW_MAX 2147483647
-
-/* internal flags (make sure they don't clash with SPDY stream flags) */
-#define SPDY_KORE_FIN 0x10
-#define SPDY_DATAFRAME_PRELUDE 0x20
-#define SPDY_NO_CLOSE 0x40
-
-#define SPDY_KEEP_NETBUFS 0
-#define SPDY_REMOVE_NETBUFS 1
-
-#endif /* !__H_SPDY_H */
diff --git a/includes/tasks.h b/includes/tasks.h
@@ -30,7 +30,9 @@
extern "C" {
#endif
+#if !defined(KORE_NO_HTTP)
struct http_request;
+#endif
struct kore_task {
u_int8_t type;
@@ -38,7 +40,10 @@ struct kore_task {
int result;
pthread_rwlock_t lock;
+#if !defined(KORE_NO_HTTP)
struct http_request *req;
+#endif
+
int fds[2];
int (*entry)(struct kore_task *);
void (*cb)(struct kore_task *);
@@ -66,8 +71,10 @@ void kore_task_destroy(struct kore_task *);
int kore_task_finished(struct kore_task *);
void kore_task_handle(struct kore_task *, int);
+#if !defined(KORE_NO_HTTP)
void kore_task_bind_request(struct kore_task *,
struct http_request *);
+#endif
void kore_task_bind_callback(struct kore_task *,
void (*cb)(struct kore_task *));
void kore_task_create(struct kore_task *,
diff --git a/src/config.c b/src/config.c
@@ -37,23 +37,29 @@
static int configure_include(char **);
static int configure_bind(char **);
static int configure_load(char **);
-static int configure_handler(char **);
static int configure_domain(char **);
static int configure_chroot(char **);
static int configure_runas(char **);
static int configure_workers(char **);
static int configure_pidfile(char **);
-static int configure_accesslog(char **);
-static int configure_certfile(char **);
-static int configure_certkey(char **);
static int configure_rlimit_nofiles(char **);
static int configure_max_connections(char **);
static int configure_accept_threshold(char **);
static int configure_set_affinity(char **);
+static int configure_socket_backlog(char **);
+
+#if !defined(KORE_NO_TLS)
+static int configure_certfile(char **);
+static int configure_certkey(char **);
static int configure_tls_version(char **);
static int configure_tls_cipher(char **);
static int configure_tls_dhparam(char **);
-static int configure_spdy_idle_time(char **);
+static int configure_client_certificates(char **);
+#endif
+
+#if !defined(KORE_NO_HTTP)
+static int configure_handler(char **);
+static int configure_accesslog(char **);
static int configure_http_header_max(char **);
static int configure_http_body_max(char **);
static int configure_http_hsts_enable(char **);
@@ -62,7 +68,6 @@ static int configure_http_request_limit(char **);
static int configure_validator(char **);
static int configure_params(char **);
static int configure_validate(char **);
-static int configure_client_certificates(char **);
static int configure_authentication(char **);
static int configure_authentication_uri(char **);
static int configure_authentication_type(char **);
@@ -70,7 +75,7 @@ static int configure_authentication_value(char **);
static int configure_authentication_validator(char **);
static int configure_websocket_maxframe(char **);
static int configure_websocket_timeout(char **);
-static int configure_socket_backlog(char **);
+#endif
#if defined(KORE_USE_PGSQL)
static int configure_pgsql_conn_max(char **);
@@ -90,12 +95,6 @@ static struct {
{ "include", configure_include },
{ "bind", configure_bind },
{ "load", configure_load },
- { "static", configure_handler },
- { "dynamic", configure_handler },
- { "tls_version", configure_tls_version },
- { "tls_cipher", configure_tls_cipher },
- { "tls_dhparam", configure_tls_dhparam },
- { "spdy_idle_time", configure_spdy_idle_time },
{ "domain", configure_domain },
{ "chroot", configure_chroot },
{ "runas", configure_runas },
@@ -105,10 +104,19 @@ static struct {
{ "worker_accept_threshold", configure_accept_threshold },
{ "worker_set_affinity", configure_set_affinity },
{ "pidfile", configure_pidfile },
- { "accesslog", configure_accesslog },
+ { "socket_backlog", configure_socket_backlog },
+#if !defined(KORE_NO_TLS)
+ { "tls_version", configure_tls_version },
+ { "tls_cipher", configure_tls_cipher },
+ { "tls_dhparam", configure_tls_dhparam },
{ "certfile", configure_certfile },
{ "certkey", configure_certkey },
{ "client_certificates", configure_client_certificates },
+#endif
+#if !defined(KORE_NO_HTTP)
+ { "static", configure_handler },
+ { "dynamic", configure_handler },
+ { "accesslog", configure_accesslog },
{ "http_header_max", configure_http_header_max },
{ "http_body_max", configure_http_body_max },
{ "http_hsts_enable", configure_http_hsts_enable },
@@ -124,7 +132,7 @@ static struct {
{ "authentication_validator", configure_authentication_validator },
{ "websocket_maxframe", configure_websocket_maxframe },
{ "websocket_timeout", configure_websocket_timeout },
- { "socket_backlog", configure_socket_backlog },
+#endif
#if defined(KORE_USE_PGSQL)
{ "pgsql_conn_max", configure_pgsql_conn_max },
#endif
@@ -135,10 +143,14 @@ static struct {
};
char *config_file = NULL;
+
+#if !defined(KORE_NO_HTTP)
static u_int8_t current_method = 0;
static struct kore_auth *current_auth = NULL;
-static struct kore_domain *current_domain = NULL;
static struct kore_module_handle *current_handler = NULL;
+#endif
+
+static struct kore_domain *current_domain = NULL;
void
kore_parse_config(void)
@@ -197,6 +209,7 @@ kore_parse_config_file(char *fpath)
*t = ' ';
}
+#if !defined(KORE_NO_HTTP)
if (!strcmp(p, "}") && current_handler != NULL) {
lineno++;
current_handler = NULL;
@@ -213,6 +226,7 @@ kore_parse_config_file(char *fpath)
current_auth = NULL;
continue;
}
+#endif
if (!strcmp(p, "}") && current_domain != NULL)
domain_sslstart();
@@ -262,7 +276,7 @@ configure_bind(char **argv)
if (argv[1] == NULL || argv[2] == NULL)
return (KORE_RESULT_ERROR);
- return (kore_server_bind(argv[1], argv[2]));
+ return (kore_server_bind(argv[1], argv[2], argv[3]));
}
static int
@@ -275,6 +289,7 @@ configure_load(char **argv)
return (KORE_RESULT_OK);
}
+#if !defined(KORE_NO_TLS)
static int
configure_tls_version(char **argv)
{
@@ -313,7 +328,6 @@ configure_tls_cipher(char **argv)
static int
configure_tls_dhparam(char **argv)
{
-#if !defined(KORE_NO_TLS)
BIO *bio;
if (argv[1] == NULL)
@@ -336,79 +350,6 @@ configure_tls_dhparam(char **argv)
printf("PEM_read_bio_DHparams(): %s\n", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
-#endif
- return (KORE_RESULT_OK);
-}
-
-static int
-configure_spdy_idle_time(char **argv)
-{
- int err;
-
- if (argv[1] == NULL)
- return (KORE_RESULT_ERROR);
-
- spdy_idle_time = kore_strtonum(argv[1], 10, 0, 65535, &err);
- if (err != KORE_RESULT_OK) {
- printf("spdy_idle_time has invalid value: %s\n", argv[1]);
- return (KORE_RESULT_ERROR);
- }
-
- spdy_idle_time = spdy_idle_time * 1000;
- return (KORE_RESULT_OK);
-}
-
-static int
-configure_domain(char **argv)
-{
- if (argv[2] == NULL)
- return (KORE_RESULT_ERROR);
-
- if (current_domain != NULL) {
- printf("previous domain configuration not closed\n");
- return (KORE_RESULT_ERROR);
- }
-
- if (strcmp(argv[2], "{")) {
- printf("missing { for domain directive\n");
- return (KORE_RESULT_ERROR);
- }
-
- if (!kore_domain_new(argv[1])) {
- printf("could not create new domain %s\n", argv[1]);
- return (KORE_RESULT_ERROR);
- }
-
- current_domain = kore_domain_lookup(argv[1]);
- return (KORE_RESULT_OK);
-}
-
-static int
-configure_handler(char **argv)
-{
- int type;
-
- if (current_domain == NULL) {
- printf("missing domain for page handler\n");
- return (KORE_RESULT_ERROR);
- }
-
- if (argv[1] == NULL || argv[2] == NULL)
- return (KORE_RESULT_ERROR);
-
- if (!strcmp(argv[0], "static"))
- type = HANDLER_TYPE_STATIC;
- else if (!strcmp(argv[0], "dynamic"))
- type = HANDLER_TYPE_DYNAMIC;
- else
- return (KORE_RESULT_ERROR);
-
- if (!kore_module_handler_new(argv[1],
- current_domain->domain, argv[2], argv[3], type)) {
- kore_debug("cannot create handler for %s", argv[1]);
- return (KORE_RESULT_ERROR);
- }
-
return (KORE_RESULT_OK);
}
@@ -439,101 +380,6 @@ configure_client_certificates(char **argv)
}
static int
-configure_chroot(char **argv)
-{
- if (chroot_path != NULL) {
- kore_debug("duplicate chroot path specified");
- return (KORE_RESULT_ERROR);
- }
-
- if (argv[1] == NULL)
- return (KORE_RESULT_ERROR);
-
- chroot_path = kore_strdup(argv[1]);
- return (KORE_RESULT_OK);
-}
-
-static int
-configure_runas(char **argv)
-{
- if (runas_user != NULL) {
- kore_debug("duplicate runas user specified");
- return (KORE_RESULT_ERROR);
- }
-
- if (argv[1] == NULL)
- return (KORE_RESULT_ERROR);
-
- runas_user = kore_strdup(argv[1]);
- return (KORE_RESULT_OK);
-}
-
-static int
-configure_workers(char **argv)
-{
- int err;
-
- if (worker_count != 0) {
- kore_debug("duplicate worker directive specified");
- return (KORE_RESULT_ERROR);
- }
-
- if (argv[1] == NULL)
- return (KORE_RESULT_ERROR);
-
- worker_count = kore_strtonum(argv[1], 10, 1, 255, &err);
- if (err != KORE_RESULT_OK) {
- printf("%s is not a correct worker number\n", argv[1]);
- return (KORE_RESULT_ERROR);
- }
-
- return (KORE_RESULT_OK);
-}
-
-static int
-configure_pidfile(char **argv)
-{
- if (argv[1] == NULL)
- return (KORE_RESULT_ERROR);
-
- if (strcmp(kore_pidfile, KORE_PIDFILE_DEFAULT)) {
- kore_debug("duplicate pidfile directive specified");
- return (KORE_RESULT_ERROR);
- }
-
- kore_pidfile = kore_strdup(argv[1]);
- return (KORE_RESULT_OK);
-}
-
-static int
-configure_accesslog(char **argv)
-{
- if (argv[1] == NULL)
- return (KORE_RESULT_ERROR);
-
- if (current_domain == NULL) {
- kore_debug("missing domain for accesslog");
- return (KORE_RESULT_ERROR);
- }
-
- if (current_domain->accesslog != -1) {
- kore_debug("domain %s already has an open accesslog",
- current_domain->domain);
- return (KORE_RESULT_ERROR);
- }
-
- current_domain->accesslog = open(argv[1],
- O_CREAT | O_APPEND | O_WRONLY,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (current_domain->accesslog == -1) {
- kore_debug("open(%s): %s", argv[1], errno_s);
- return (KORE_RESULT_ERROR);
- }
-
- return (KORE_RESULT_OK);
-}
-
-static int
configure_certfile(char **argv)
{
if (argv[1] == NULL)
@@ -573,34 +419,57 @@ configure_certkey(char **argv)
return (KORE_RESULT_OK);
}
+#endif /* !KORE_NO_TLS */
+
static int
-configure_max_connections(char **argv)
+configure_domain(char **argv)
{
- int err;
+ if (argv[2] == NULL)
+ return (KORE_RESULT_ERROR);
- if (argv[1] == NULL)
+ if (current_domain != NULL) {
+ printf("previous domain configuration not closed\n");
return (KORE_RESULT_ERROR);
+ }
- worker_max_connections = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err);
- if (err != KORE_RESULT_OK) {
- printf("bad value for worker_max_connections: %s\n", argv[1]);
+ if (strcmp(argv[2], "{")) {
+ printf("missing { for domain directive\n");
+ return (KORE_RESULT_ERROR);
+ }
+
+ if (!kore_domain_new(argv[1])) {
+ printf("could not create new domain %s\n", argv[1]);
return (KORE_RESULT_ERROR);
}
+ current_domain = kore_domain_lookup(argv[1]);
return (KORE_RESULT_OK);
}
+#if !defined(KORE_NO_HTTP)
static int
-configure_rlimit_nofiles(char **argv)
+configure_handler(char **argv)
{
- int err;
+ int type;
- if (argv[1] == NULL)
+ if (current_domain == NULL) {
+ printf("missing domain for page handler\n");
+ return (KORE_RESULT_ERROR);
+ }
+
+ if (argv[1] == NULL || argv[2] == NULL)
return (KORE_RESULT_ERROR);
- worker_rlimit_nofiles = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err);
- if (err != KORE_RESULT_OK) {
- printf("bad value for worker_rlimit_nofiles: %s\n", argv[1]);
+ if (!strcmp(argv[0], "static"))
+ type = HANDLER_TYPE_STATIC;
+ else if (!strcmp(argv[0], "dynamic"))
+ type = HANDLER_TYPE_DYNAMIC;
+ else
+ return (KORE_RESULT_ERROR);
+
+ if (!kore_module_handler_new(argv[1],
+ current_domain->domain, argv[2], argv[3], type)) {
+ kore_debug("cannot create handler for %s", argv[1]);
return (KORE_RESULT_ERROR);
}
@@ -608,33 +477,27 @@ configure_rlimit_nofiles(char **argv)
}
static int
-configure_accept_threshold(char **argv)
+configure_accesslog(char **argv)
{
- int err;
-
if (argv[1] == NULL)
return (KORE_RESULT_ERROR);
- worker_accept_threshold = kore_strtonum(argv[1], 0, 1, UINT_MAX, &err);
- if (err != KORE_RESULT_OK) {
- printf("bad value for worker_accept_threshold: %s\n", argv[1]);
+ if (current_domain == NULL) {
+ kore_debug("missing domain for accesslog");
return (KORE_RESULT_ERROR);
}
- return (KORE_RESULT_OK);
-}
-
-static int
-configure_set_affinity(char **argv)
-{
- int err;
-
- if (argv[1] == NULL)
+ if (current_domain->accesslog != -1) {
+ kore_debug("domain %s already has an open accesslog",
+ current_domain->domain);
return (KORE_RESULT_ERROR);
+ }
- worker_set_affinity = kore_strtonum(argv[1], 10, 0, 1, &err);
- if (err != KORE_RESULT_OK) {
- printf("bad value for worker_set_affinity: %s\n", argv[1]);
+ current_domain->accesslog = open(argv[1],
+ O_CREAT | O_APPEND | O_WRONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (current_domain->accesslog == -1) {
+ kore_debug("open(%s): %s", argv[1], errno_s);
return (KORE_RESULT_ERROR);
}
@@ -1017,6 +880,143 @@ configure_websocket_timeout(char **argv)
return (KORE_RESULT_OK);
}
+#endif /* ! KORE_NO_HTTP */
+
+static int
+configure_chroot(char **argv)
+{
+ if (chroot_path != NULL) {
+ kore_debug("duplicate chroot path specified");
+ return (KORE_RESULT_ERROR);
+ }
+
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ chroot_path = kore_strdup(argv[1]);
+ return (KORE_RESULT_OK);
+}
+
+static int
+configure_runas(char **argv)
+{
+ if (runas_user != NULL) {
+ kore_debug("duplicate runas user specified");
+ return (KORE_RESULT_ERROR);
+ }
+
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ runas_user = kore_strdup(argv[1]);
+ return (KORE_RESULT_OK);
+}
+
+static int
+configure_workers(char **argv)
+{
+ int err;
+
+ if (worker_count != 0) {
+ kore_debug("duplicate worker directive specified");
+ return (KORE_RESULT_ERROR);
+ }
+
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ worker_count = kore_strtonum(argv[1], 10, 1, 255, &err);
+ if (err != KORE_RESULT_OK) {
+ printf("%s is not a correct worker number\n", argv[1]);
+ return (KORE_RESULT_ERROR);
+ }
+
+ return (KORE_RESULT_OK);
+}
+
+static int
+configure_pidfile(char **argv)
+{
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ if (strcmp(kore_pidfile, KORE_PIDFILE_DEFAULT)) {
+ kore_debug("duplicate pidfile directive specified");
+ return (KORE_RESULT_ERROR);
+ }
+
+ kore_pidfile = kore_strdup(argv[1]);
+ return (KORE_RESULT_OK);
+}
+
+static int
+configure_max_connections(char **argv)
+{
+ int err;
+
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ worker_max_connections = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err);
+ if (err != KORE_RESULT_OK) {
+ printf("bad value for worker_max_connections: %s\n", argv[1]);
+ return (KORE_RESULT_ERROR);
+ }
+
+ return (KORE_RESULT_OK);
+}
+
+static int
+configure_rlimit_nofiles(char **argv)
+{
+ int err;
+
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ worker_rlimit_nofiles = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err);
+ if (err != KORE_RESULT_OK) {
+ printf("bad value for worker_rlimit_nofiles: %s\n", argv[1]);
+ return (KORE_RESULT_ERROR);
+ }
+
+ return (KORE_RESULT_OK);
+}
+
+static int
+configure_accept_threshold(char **argv)
+{
+ int err;
+
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ worker_accept_threshold = kore_strtonum(argv[1], 0, 1, UINT_MAX, &err);
+ if (err != KORE_RESULT_OK) {
+ printf("bad value for worker_accept_threshold: %s\n", argv[1]);
+ return (KORE_RESULT_ERROR);
+ }
+
+ return (KORE_RESULT_OK);
+}
+
+static int
+configure_set_affinity(char **argv)
+{
+ int err;
+
+ if (argv[1] == NULL)
+ return (KORE_RESULT_ERROR);
+
+ worker_set_affinity = kore_strtonum(argv[1], 10, 0, 1, &err);
+ if (err != KORE_RESULT_OK) {
+ printf("bad value for worker_set_affinity: %s\n", argv[1]);
+ return (KORE_RESULT_ERROR);
+ }
+
+ return (KORE_RESULT_OK);
+}
+
static int
configure_socket_backlog(char **argv)
{
diff --git a/src/connection.c b/src/connection.c
@@ -55,37 +55,33 @@ kore_connection_new(void *owner)
c->tls_reneg = 0;
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->spdy_streams));
+#if !defined(KORE_NO_HTTP)
TAILQ_INIT(&(c->http_requests));
+#endif
+
+ TAILQ_INIT(&(c->send_queue));
return (c);
}
int
-kore_connection_accept(struct listener *l, struct connection **out)
+kore_connection_accept(struct listener *listener, struct connection **out)
{
struct connection *c;
struct sockaddr *sin;
socklen_t len;
- kore_debug("kore_connection_accept(%p)", l);
+ kore_debug("kore_connection_accept(%p)", listener);
*out = NULL;
- c = kore_connection_new(l);
+ c = kore_connection_new(listener);
- c->addrtype = l->addrtype;
+ c->addrtype = listener->addrtype;
if (c->addrtype == AF_INET) {
len = sizeof(struct sockaddr_in);
sin = (struct sockaddr *)&(c->addr.ipv4);
@@ -94,7 +90,7 @@ kore_connection_accept(struct listener *l, struct connection **out)
sin = (struct sockaddr *)&(c->addr.ipv6);
}
- if ((c->fd = accept(l->fd, sin, &len)) == -1) {
+ if ((c->fd = accept(listener->fd, sin, &len)) == -1) {
kore_pool_put(&connection_pool, c);
kore_debug("accept(): %s", errno_s);
return (KORE_RESULT_ERROR);
@@ -106,24 +102,30 @@ kore_connection_accept(struct listener *l, struct connection **out)
return (KORE_RESULT_ERROR);
}
+ TAILQ_INSERT_TAIL(&connections, c, list);
+
#if !defined(KORE_NO_TLS)
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;
-
- net_recv_queue(c, http_header_max, NETBUF_CALL_CB_ALWAYS,
- http_header_recv);
+ if (listener->connect != NULL) {
+ listener->connect(c);
+ } else {
+#if !defined(KORE_NO_HTTP)
+ c->proto = CONN_PROTO_HTTP;
+ if (http_keepalive_time != 0)
+ c->idle_timer.length = http_keepalive_time * 1000;
+ net_recv_queue(c, http_header_max,
+ NETBUF_CALL_CB_ALWAYS, http_header_recv);
+#endif
+ }
#endif
- TAILQ_INSERT_TAIL(&connections, c, list);
kore_connection_start_idletimer(c);
*out = c;
@@ -140,11 +142,6 @@ kore_connection_check_timeout(void)
TAILQ_FOREACH(c, &connections, list) {
if (c->proto == CONN_PROTO_MSG)
continue;
- if (c->proto == CONN_PROTO_SPDY &&
- c->idle_timer.length == 0 &&
- !(c->flags & CONN_WRITE_BLOCK) &&
- !(c->flags & CONN_READ_BLOCK))
- continue;
if (!(c->flags & CONN_IDLE_TIMER_ACT))
continue;
kore_connection_check_idletimer(now, c);
@@ -190,8 +187,7 @@ kore_connection_handle(struct connection *c)
{
#if !defined(KORE_NO_TLS)
int r;
- u_int32_t len;
- const u_char *data;
+ struct listener *listener;
char cn[X509_CN_LENGTH];
#endif
@@ -239,6 +235,8 @@ kore_connection_handle(struct connection *c)
"no CN found in client certificate");
return (KORE_RESULT_ERROR);
}
+ } else {
+ c->cert = NULL;
}
r = SSL_get_verify_result(c->ssl);
@@ -248,40 +246,26 @@ kore_connection_handle(struct connection *c)
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;
- c->idle_timer.length = spdy_idle_time;
- net_recv_queue(c, SPDY_FRAME_SIZE, 0,
- spdy_frame_recv);
- } else if (!memcmp(data, "http/1.1", MIN(8, len))) {
- c->proto = CONN_PROTO_HTTP;
- if (http_keepalive_time != 0) {
- c->idle_timer.length =
- http_keepalive_time * 1000;
- }
-
- net_recv_queue(c, http_header_max,
- NETBUF_CALL_CB_ALWAYS,
- http_header_recv);
- } else {
- kore_log(LOG_NOTICE,
- "npn: received unknown protocol");
- return (KORE_RESULT_ERROR);
- }
- } else {
- c->proto = CONN_PROTO_HTTP;
- if (http_keepalive_time != 0) {
- c->idle_timer.length =
- http_keepalive_time * 1000;
+ if (c->owner != NULL) {
+ listener = (struct listener *)c->owner;
+ if (listener->connect != NULL) {
+ listener->connect(c);
+ goto tls_established;
}
+ }
- net_recv_queue(c, http_header_max,
- NETBUF_CALL_CB_ALWAYS,
- http_header_recv);
+#if !defined(KORE_NO_HTTP)
+ c->proto = CONN_PROTO_HTTP;
+ if (http_keepalive_time != 0) {
+ c->idle_timer.length =
+ http_keepalive_time * 1000;
}
+ net_recv_queue(c, http_header_max,
+ NETBUF_CALL_CB_ALWAYS, http_header_recv);
+#endif
+
+tls_established:
c->state = CONN_STATE_ESTABLISHED;
/* FALLTHROUGH */
#endif /* !KORE_NO_TLS */
@@ -312,8 +296,9 @@ void
kore_connection_remove(struct connection *c)
{
struct netbuf *nb, *next;
- struct spdy_stream *s, *snext;
+#if !defined(KORE_NO_HTTP)
struct http_request *req, *rnext;
+#endif
kore_debug("kore_connection_remove(%p)", c);
@@ -332,17 +317,14 @@ kore_connection_remove(struct connection *c)
if (c->hdlr_extra != NULL)
kore_mem_free(c->hdlr_extra);
- if (c->inflate_started)
- inflateEnd(&(c->z_inflate));
- if (c->deflate_started)
- deflateEnd(&(c->z_deflate));
-
+#if !defined(KORE_NO_HTTP)
for (req = TAILQ_FIRST(&(c->http_requests)); req != NULL; req = rnext) {
rnext = TAILQ_NEXT(req, olist);
TAILQ_REMOVE(&(c->http_requests), req, olist);
req->flags |= HTTP_REQUEST_DELETE;
http_request_wakeup(req);
}
+#endif
for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = next) {
next = TAILQ_NEXT(nb, list);
@@ -360,19 +342,6 @@ kore_connection_remove(struct connection *c)
kore_pool_put(&nb_pool, c->rnb);
}
- for (s = TAILQ_FIRST(&(c->spdy_streams)); s != NULL; s = snext) {
- snext = TAILQ_NEXT(s, list);
- TAILQ_REMOVE(&(c->spdy_streams), s, list);
-
- if (s->hblock != NULL) {
- if (s->hblock->header_block != NULL)
- kore_mem_free(s->hblock->header_block);
- kore_mem_free(s->hblock);
- }
-
- kore_mem_free(s);
- }
-
kore_pool_put(&connection_pool, c);
}
@@ -384,10 +353,7 @@ kore_connection_check_idletimer(u_int64_t now, struct connection *c)
d = now - c->idle_timer.start;
if (d >= c->idle_timer.length) {
kore_debug("%p idle for %d ms, expiring", c, d);
- if (c->proto == CONN_PROTO_SPDY)
- spdy_session_teardown(c, SPDY_SESSION_ERROR_OK);
- else
- kore_connection_disconnect(c);
+ kore_connection_disconnect(c);
}
}
diff --git a/src/domain.c b/src/domain.c
@@ -170,8 +170,6 @@ kore_domain_sslstart(struct kore_domain *dom)
SSL_CTX_set_info_callback(dom->ssl_ctx, kore_tls_info_callback);
SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_tls_sni_cb);
- SSL_CTX_set_next_protos_advertised_cb(dom->ssl_ctx,
- kore_tls_npn_cb, NULL);
kore_mem_free(dom->certfile);
kore_mem_free(dom->certkey);
diff --git a/src/http.c b/src/http.c
@@ -19,7 +19,6 @@
#include <ctype.h>
#include <inttypes.h>
-#include "spdy.h"
#include "kore.h"
#include "http.h"
@@ -32,22 +31,17 @@
#endif
static int http_body_recv(struct netbuf *);
-static void http_error_response(struct connection *,
- struct spdy_stream *, int);
+static void http_error_response(struct connection *, int);
static void http_argument_add(struct http_request *, const char *,
void *, u_int32_t, int);
static void http_file_add(struct http_request *, const char *,
const char *, u_int8_t *, u_int32_t);
static void http_response_normal(struct http_request *,
struct connection *, int, void *, u_int32_t);
-static void http_response_spdy(struct http_request *,
- struct connection *, struct spdy_stream *,
- int, void *, u_int32_t);
static struct kore_buf *header_buf;
static char http_version[32];
static u_int16_t http_version_len;
-static char http_version_spdy[32];
static TAILQ_HEAD(, http_request) http_requests;
static TAILQ_HEAD(, http_request) http_requests_sleeping;
static struct kore_pool http_request_pool;
@@ -72,12 +66,6 @@ http_init(void)
header_buf = kore_buf_create(1024);
- l = snprintf(http_version_spdy, sizeof(http_version_spdy),
- "kore (%d.%d.%d-%s)", KORE_VERSION_MAJOR, KORE_VERSION_MINOR,
- KORE_VERSION_PATCH, KORE_VERSION_STATE);
- if (l == -1 || (size_t)l >= sizeof(http_version_spdy))
- fatal("http_init(): http_version_spdy buffer too small");
-
l = snprintf(http_version, sizeof(http_version),
"server: kore (%d.%d.%d-%s)\r\n", KORE_VERSION_MAJOR,
KORE_VERSION_MINOR, KORE_VERSION_PATCH, KORE_VERSION_STATE);
@@ -99,7 +87,7 @@ http_init(void)
}
int
-http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
+http_request_new(struct connection *c, const char *host,
const char *method, const char *path, const char *version,
struct http_request **out)
{
@@ -108,21 +96,21 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
int m, flags;
size_t hostlen, pathlen;
- kore_debug("http_request_new(%p, %p, %s, %s, %s, %s)", c, s,
- host, method, path, version);
+ kore_debug("http_request_new(%p, %s, %s, %s, %s)", c, host,
+ method, path, version);
if ((hostlen = strlen(host)) >= KORE_DOMAINNAME_LEN - 1) {
- http_error_response(c, s, 500);
+ http_error_response(c, 500);
return (KORE_RESULT_ERROR);
}
if ((pathlen = strlen(path)) >= HTTP_URI_LEN - 1) {
- http_error_response(c, s, 414);
+ http_error_response(c, 414);
return (KORE_RESULT_ERROR);
}
if (strcasecmp(version, "http/1.1")) {
- http_error_response(c, s, 505);
+ http_error_response(c, 505);
return (KORE_RESULT_ERROR);
}
@@ -142,7 +130,7 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
m = HTTP_METHOD_HEAD;
flags = HTTP_REQUEST_COMPLETE;
} else {
- http_error_response(c, s, 400);
+ http_error_response(c, 400);
return (KORE_RESULT_ERROR);
}
@@ -152,7 +140,6 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
req->start = 0;
req->owner = c;
req->status = 0;
- req->stream = s;
req->method = m;
req->hdlr = NULL;
req->agent = NULL;
@@ -182,10 +169,8 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
TAILQ_INIT(&(req->arguments));
TAILQ_INIT(&(req->files));
- if (s != NULL) {
- if (!http_request_header(req, "user-agent", &(req->agent)))
- req->agent = kore_strdup("unknown");
- }
+ if (!http_request_header(req, "user-agent", &(req->agent)))
+ req->agent = kore_strdup("unknown");
#if defined(KORE_USE_TASKS)
LIST_INIT(&(req->tasks));
@@ -462,9 +447,6 @@ http_response(struct http_request *req, int status, void *d, u_int32_t l)
req->status = status;
switch (req->owner->proto) {
- case CONN_PROTO_SPDY:
- http_response_spdy(req, req->owner, req->stream, status, d, l);
- break;
case CONN_PROTO_HTTP:
case CONN_PROTO_WEBSOCKET:
http_response_normal(req, req->owner, status, d, l);
@@ -484,10 +466,6 @@ http_response_stream(struct http_request *req, int status, void *base,
req->status = status;
switch (req->owner->proto) {
- case CONN_PROTO_SPDY:
- http_response_spdy(req, req->owner,
- req->stream, status, NULL, len);
- break;
case CONN_PROTO_HTTP:
http_response_normal(req, req->owner, status, NULL, len);
break;
@@ -497,7 +475,7 @@ http_response_stream(struct http_request *req, int status, void *base,
}
if (req->method != HTTP_METHOD_HEAD) {
- net_send_stream(req->owner, base, len, req->stream, cb, &nb);
+ net_send_stream(req->owner, base, len, cb, &nb);
nb->extra = arg;
}
}
@@ -508,22 +486,16 @@ http_request_header(struct http_request *req, const char *header, char **out)
int r;
struct http_header *hdr;
- if (req->owner->proto == CONN_PROTO_SPDY) {
- r = spdy_stream_get_header(req->stream->hblock, header, out);
- } else {
- TAILQ_FOREACH(hdr, &(req->req_headers), list) {
- if (!strcasecmp(hdr->header, header)) {
- r = strlen(hdr->value) + 1;
- *out = kore_malloc(r);
- kore_strlcpy(*out, hdr->value, r);
- return (KORE_RESULT_OK);
- }
+ TAILQ_FOREACH(hdr, &(req->req_headers), list) {
+ if (!strcasecmp(hdr->header, header)) {
+ r = strlen(hdr->value) + 1;
+ *out = kore_malloc(r);
+ kore_strlcpy(*out, hdr->value, r);
+ return (KORE_RESULT_OK);
}
-
- r = KORE_RESULT_ERROR;
}
- return (r);
+ return (KORE_RESULT_ERROR);
}
int
@@ -561,13 +533,13 @@ http_header_recv(struct netbuf *nb)
h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
if (h < 2) {
- http_error_response(c, NULL, 400);
+ http_error_response(c, 400);
return (KORE_RESULT_OK);
}
v = kore_split_string(headers[0], " ", request, 4);
if (v != 3) {
- http_error_response(c, NULL, 400);
+ http_error_response(c, 400);
return (KORE_RESULT_OK);
}
@@ -579,13 +551,13 @@ http_header_recv(struct netbuf *nb)
v = kore_split_string(headers[i], ":", host, 3);
if (v != 2) {
- http_error_response(c, NULL, 400);
+ http_error_response(c, 400);
return (KORE_RESULT_OK);
}
if ((host[1] - host[0]) != 5 ||
strncasecmp(host[0], "host", 4) || host[1] == '\0') {
- http_error_response(c, NULL, 400);
+ http_error_response(c, 400);
return (KORE_RESULT_OK);
}
@@ -595,11 +567,11 @@ http_header_recv(struct netbuf *nb)
}
if (host[0] == NULL) {
- http_error_response(c, NULL, 400);
+ http_error_response(c, 400);
return (KORE_RESULT_OK);
}
- if (!http_request_new(c, NULL, host[1],
+ if (!http_request_new(c, host[1],
request[0], request[1], request[2], &req))
return (KORE_RESULT_OK);
@@ -630,7 +602,7 @@ http_header_recv(struct netbuf *nb)
if (!http_request_header(req, "content-length", &p)) {
kore_debug("expected body but no content-length");
req->flags |= HTTP_REQUEST_DELETE;
- http_error_response(req->owner, NULL, 411);
+ http_error_response(req->owner, 411);
return (KORE_RESULT_OK);
}
@@ -639,7 +611,7 @@ http_header_recv(struct netbuf *nb)
kore_debug("content-length invalid: %s", p);
kore_mem_free(p);
req->flags |= HTTP_REQUEST_DELETE;
- http_error_response(req->owner, NULL, 411);
+ http_error_response(req->owner, 411);
return (KORE_RESULT_OK);
}
@@ -655,7 +627,7 @@ http_header_recv(struct netbuf *nb)
kore_log(LOG_NOTICE, "body too large (%ld > %ld)",
clen, http_body_max);
req->flags |= HTTP_REQUEST_DELETE;
- http_error_response(req->owner, NULL, 411);
+ http_error_response(req->owner, 411);
return (KORE_RESULT_OK);
}
@@ -675,7 +647,7 @@ http_header_recv(struct netbuf *nb)
req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
} else {
kore_debug("bytes_left would become zero (%ld)", clen);
- http_error_response(req->owner, NULL, 500);
+ http_error_response(req->owner, 500);
}
}
@@ -1145,17 +1117,12 @@ http_body_recv(struct netbuf *nb)
}
static void
-http_error_response(struct connection *c, struct spdy_stream *s, int status)
+http_error_response(struct connection *c, int status)
{
- kore_debug("http_error_response(%p, %p, %d)", c, s, status);
+ kore_debug("http_error_response(%p, %d)", c, status);
switch (c->proto) {
- case CONN_PROTO_SPDY:
- http_response_spdy(NULL, c, s, status, NULL, 0);
- break;
case CONN_PROTO_HTTP:
- if (s != NULL)
- kore_log(LOG_NOTICE, "http_error_response: s != NULL");
http_response_normal(NULL, c, status, NULL, 0);
break;
default:
@@ -1165,61 +1132,6 @@ http_error_response(struct connection *c, struct spdy_stream *s, int status)
}
static void
-http_response_spdy(struct http_request *req, struct connection *c,
- struct spdy_stream *s, int status, void *d, u_int32_t len)
-{
- u_int32_t hlen;
- struct http_header *hdr;
- u_int8_t *htext;
- struct spdy_header_block *hblock;
- char sbuf[512];
-
- (void)snprintf(sbuf, sizeof(sbuf), "%d %s",
- status, http_status_text(status));
-
- hblock = spdy_header_block_create(SPDY_HBLOCK_NORMAL);
- spdy_header_block_add(hblock, ":status", sbuf);
- spdy_header_block_add(hblock, ":version", "HTTP/1.1");
- spdy_header_block_add(hblock, ":server", http_version_spdy);
-
- if (http_hsts_enable) {
- (void)snprintf(sbuf, sizeof(sbuf),
- "max-age=%" PRIu64 "; includeSubDomains", http_hsts_enable);
- spdy_header_block_add(hblock,
- ":strict-transport-security", sbuf);
- }
-
- if (req != NULL) {
- TAILQ_FOREACH(hdr, &(req->resp_headers), list)
- spdy_header_block_add(hblock, hdr->header, hdr->value);
- }
-
- htext = spdy_header_block_release(c, hblock, &hlen);
- if (htext == NULL) {
- spdy_session_teardown(c, SPDY_SESSION_ERROR_INTERNAL);
- return;
- }
-
- spdy_frame_send(c, SPDY_CTRL_FRAME_SYN_REPLY, 0, hlen, s, 0);
- net_send_queue(c, htext, hlen, NULL, NETBUF_LAST_CHAIN);
- kore_mem_free(htext);
-
- if (len > 0 && req != NULL && req->method != HTTP_METHOD_HEAD) {
- s->send_size += len;
- s->flags |= SPDY_DATAFRAME_PRELUDE;
-
- if (d != NULL)
- net_send_queue(c, d, len, s, NETBUF_LAST_CHAIN);
- }
-
- if ((req != NULL && req->method == HTTP_METHOD_HEAD) ||
- (len == 0 && !(s->flags & SPDY_NO_CLOSE))) {
- spdy_frame_send(c, SPDY_DATA_FRAME, FLAG_FIN, 0, s, 0);
- spdy_stream_close(c, s, SPDY_KEEP_NETBUFS);
- }
-}
-
-static void
http_response_normal(struct http_request *req, struct connection *c,
int status, void *d, u_int32_t len)
{
@@ -1286,11 +1198,10 @@ http_response_normal(struct http_request *req, struct connection *c,
}
kore_buf_append(header_buf, "\r\n", 2);
- net_send_queue(c, header_buf->data, header_buf->offset,
- NULL, NETBUF_LAST_CHAIN);
+ net_send_queue(c, header_buf->data, header_buf->offset);
if (d != NULL && req != NULL && req->method != HTTP_METHOD_HEAD)
- net_send_queue(c, d, len, NULL, NETBUF_LAST_CHAIN);
+ net_send_queue(c, d, len);
if (!(c->flags & CONN_CLOSE_EMPTY))
net_recv_reset(c, http_header_max, http_header_recv);
diff --git a/src/kore.c b/src/kore.c
@@ -68,12 +68,21 @@ version(void)
{
printf("kore %d.%d.%d-%s ", KORE_VERSION_MAJOR, KORE_VERSION_MINOR,
KORE_VERSION_PATCH, KORE_VERSION_STATE);
+#if defined(KORE_NO_TLS)
+ printf("no-tls ");
+#endif
+#if defined(KORE_NO_HTTP)
+ printf("no-http ");
+#endif
#if defined(KORE_USE_PGSQL)
printf("pgsql ");
#endif
#if defined(KORE_USE_TASKS)
printf("tasks ");
#endif
+#if defined(KORE_DEBUG)
+ printf("debug ");
+#endif
printf("\n");
exit(0);
@@ -136,10 +145,12 @@ main(int argc, char *argv[])
LIST_INIT(&listeners);
kore_log_init();
+#if !defined(KORE_NO_HTTP)
kore_auth_init();
+ kore_validator_init();
+#endif
kore_domain_init();
kore_module_init();
- kore_validator_init();
kore_server_sslstart();
if (config_file == NULL)
@@ -147,7 +158,10 @@ main(int argc, char *argv[])
kore_parse_config();
kore_platform_init();
+
+#if !defined(KORE_NO_HTTP)
kore_accesslog_init();
+#endif
sig_recv = 0;
signal(SIGHUP, kore_signal);
@@ -175,17 +189,6 @@ main(int argc, char *argv[])
#if !defined(KORE_NO_TLS)
int
-kore_tls_npn_cb(SSL *ssl, const u_char **data, unsigned int *len, void *arg)
-{
- kore_debug("kore_tls_npn_cb(): sending protocols");
-
- *data = (const unsigned char *)KORE_SSL_PROTO_STRING;
- *len = strlen(KORE_SSL_PROTO_STRING);
-
- return (SSL_TLSEXT_ERR_OK);
-}
-
-int
kore_tls_sni_cb(SSL *ssl, int *ad, void *arg)
{
struct kore_domain *dom;
@@ -225,7 +228,7 @@ kore_tls_info_callback(const SSL *ssl, int flags, int ret)
#endif
int
-kore_server_bind(const char *ip, const char *port)
+kore_server_bind(const char *ip, const char *port, const char *ccb)
{
struct listener *l;
int on, r;
@@ -295,6 +298,18 @@ kore_server_bind(const char *ip, const char *port)
return (KORE_RESULT_ERROR);
}
+ if (ccb != NULL) {
+ l->connect = kore_module_getsym(ccb);
+ if (l->connect == NULL) {
+ printf("no such callback: '%s'\n", ccb);
+ close(l->fd);
+ kore_mem_free(l);
+ return (KORE_RESULT_ERROR);
+ }
+ } else {
+ l->connect = NULL;
+ }
+
nlisteners++;
LIST_INSERT_HEAD(&listeners, l, list);
diff --git a/src/mem.c b/src/mem.c
@@ -49,7 +49,7 @@ kore_malloc(size_t len)
fatal("kore_malloc(): zero size");
mlen = sizeof(u_int32_t) + len + sizeof(struct meminfo);
- if ((ptr = malloc(mlen)) == NULL)
+ if ((ptr = calloc(1, mlen)) == NULL)
fatal("kore_malloc(%d): %d", len, errno);
plen = (u_int32_t *)ptr;
@@ -59,10 +59,6 @@ kore_malloc(size_t len)
mem = KORE_MEMINFO(addr);
mem->magic = KORE_MEM_MAGIC;
-#if defined(KORE_PEDANTIC_MALLOC)
- explicit_bzero(addr, len);
-#endif
-
return (addr);
}
@@ -114,10 +110,6 @@ kore_mem_free(void *ptr)
if (mem->magic != KORE_MEM_MAGIC)
fatal("kore_mem_free(): magic boundary not found");
-#if defined(KORE_PEDANTIC_MALLOC)
- explicit_bzero(ptr, KORE_MEMSIZE(ptr));
-#endif
-
addr = (u_int8_t *)ptr - sizeof(u_int32_t);
free(addr);
}
@@ -134,11 +126,3 @@ kore_strdup(const char *str)
return (nstr);
}
-
-#if defined(KORE_PEDANTIC_MALLOC)
-void
-explicit_bzero(void *addr, size_t len)
-{
- bzero(addr, len);
-}
-#endif
diff --git a/src/module.c b/src/module.c
@@ -129,7 +129,9 @@ kore_module_reload(int cbs)
}
}
+#if !defined(KORE_NO_HTTP)
kore_validator_reload();
+#endif
}
int
@@ -141,6 +143,7 @@ kore_module_loaded(void)
return (1);
}
+#if !defined(KORE_NO_HTTP)
int
kore_module_handler_new(const char *path, const char *domain,
const char *func, const char *auth, int type)
@@ -216,6 +219,8 @@ kore_module_handler_find(const char *domain, const char *path)
return (NULL);
}
+#endif /* !KORE_NO_HTTP */
+
void *
kore_module_getsym(const char *symbol)
{
diff --git a/src/msg.c b/src/msg.c
@@ -34,8 +34,11 @@ static int msg_recv_packet(struct netbuf *);
static int msg_recv_data(struct netbuf *);
static void msg_disconnected_parent(struct connection *);
static void msg_disconnected_worker(struct connection *);
+
+#if !defined(KORE_NO_HTTP)
static void msg_type_accesslog(struct kore_msg *, const void *);
static void msg_type_websocket(struct kore_msg *, const void *);
+#endif
void
kore_msg_init(void)
@@ -54,7 +57,9 @@ kore_msg_parent_init(void)
kore_msg_parent_add(kw);
}
+#if !defined(KORE_NO_HTTP)
kore_msg_register(KORE_MSG_ACCESSLOG, msg_type_accesslog);
+#endif
}
void
@@ -86,7 +91,9 @@ kore_msg_parent_remove(struct kore_worker *kw)
void
kore_msg_worker_init(void)
{
+#if !defined(KORE_NO_HTTP)
kore_msg_register(KORE_MSG_WEBSOCKET, msg_type_websocket);
+#endif
worker->msg[1] = kore_connection_new(NULL);
worker->msg[1]->fd = worker->pipe[1];
@@ -120,7 +127,7 @@ kore_msg_register(u_int8_t id, void (*cb)(struct kore_msg *, const void *))
}
void
-kore_msg_send(u_int16_t dst, u_int8_t id, void *data, u_int32_t len)
+kore_msg_send(u_int16_t dst, u_int8_t id, const void *data, u_int32_t len)
{
struct kore_msg m;
@@ -129,8 +136,8 @@ kore_msg_send(u_int16_t dst, u_int8_t id, void *data, u_int32_t len)
m.length = len;
m.src = worker->id;
- net_send_queue(worker->msg[1], &m, sizeof(m), NULL, NETBUF_LAST_CHAIN);
- net_send_queue(worker->msg[1], data, len, NULL, NETBUF_LAST_CHAIN);
+ net_send_queue(worker->msg[1], &m, sizeof(m));
+ net_send_queue(worker->msg[1], data, len);
net_send_flush(worker->msg[1]);
}
@@ -175,8 +182,7 @@ msg_recv_data(struct netbuf *nb)
/* This allows the worker to receive the correct id. */
msg->dst = *(u_int8_t *)c->hdlr_extra;
- net_send_queue(c, nb->buf, nb->s_off,
- NULL, NETBUF_LAST_CHAIN);
+ net_send_queue(c, nb->buf, nb->s_off);
net_send_flush(c);
}
}
@@ -199,6 +205,7 @@ msg_disconnected_worker(struct connection *c)
c->hdlr_extra = NULL;
}
+#if !defined(KORE_NO_HTTP)
static void
msg_type_accesslog(struct kore_msg *msg, const void *data)
{
@@ -213,12 +220,12 @@ msg_type_websocket(struct kore_msg *msg, const void *data)
TAILQ_FOREACH(c, &connections, list) {
if (c->proto == CONN_PROTO_WEBSOCKET) {
- net_send_queue(c, data, msg->length,
- NULL, NETBUF_LAST_CHAIN);
+ net_send_queue(c, data, msg->length);
net_send_flush(c);
}
}
}
+#endif
static struct msg_type *
msg_type_lookup(u_int8_t id)
diff --git a/src/net.c b/src/net.c
@@ -37,35 +37,31 @@ net_init(void)
}
void
-net_send_queue(struct connection *c, const void *data, u_int32_t len,
- struct spdy_stream *s, int before)
+net_send_queue(struct connection *c, const void *data, u_int32_t len)
{
const u_int8_t *d;
struct netbuf *nb;
u_int32_t avail;
- kore_debug("net_send_queue(%p, %p, %d, %p, %d)",
- c, data, len, s, before);
+ kore_debug("net_send_queue(%p, %p, %d)", c, data, len);
d = data;
- if (before == NETBUF_LAST_CHAIN) {
- nb = TAILQ_LAST(&(c->send_queue), netbuf_head);
- if (nb != NULL && !(nb->flags & NETBUF_IS_STREAM) &&
- nb->stream == s && nb->b_len < nb->m_len) {
- avail = nb->m_len - nb->b_len;
- if (len < avail) {
- memcpy(nb->buf + nb->b_len, d, len);
- nb->b_len += len;
+ nb = TAILQ_LAST(&(c->send_queue), netbuf_head);
+ if (nb != NULL && !(nb->flags & NETBUF_IS_STREAM) &&
+ nb->b_len < nb->m_len) {
+ avail = nb->m_len - nb->b_len;
+ if (len < avail) {
+ memcpy(nb->buf + nb->b_len, d, len);
+ nb->b_len += len;
+ return;
+ } else if (len > avail) {
+ memcpy(nb->buf + nb->b_len, d, avail);
+ nb->b_len += avail;
+
+ len -= avail;
+ d += avail;
+ if (len == 0)
return;
- } else if (len > avail) {
- memcpy(nb->buf + nb->b_len, d, avail);
- nb->b_len += avail;
-
- len -= avail;
- d += avail;
- if (len == 0)
- return;
- }
}
}
@@ -74,7 +70,6 @@ net_send_queue(struct connection *c, const void *data, u_int32_t len,
nb->cb = NULL;
nb->owner = c;
nb->s_off = 0;
- nb->stream = s;
nb->b_len = len;
nb->type = NETBUF_SEND;
@@ -87,27 +82,22 @@ net_send_queue(struct connection *c, const void *data, u_int32_t len,
if (len > 0)
memcpy(nb->buf, d, nb->b_len);
- if (before == NETBUF_BEFORE_CHAIN) {
- TAILQ_INSERT_BEFORE(c->snb, nb, list);
- } else {
- TAILQ_INSERT_TAIL(&(c->send_queue), nb, list);
- }
+ TAILQ_INSERT_TAIL(&(c->send_queue), nb, list);
}
void
net_send_stream(struct connection *c, void *data, u_int32_t len,
- struct spdy_stream *s, int (*cb)(struct netbuf *), struct netbuf **out)
+ int (*cb)(struct netbuf *), struct netbuf **out)
{
struct netbuf *nb;
- kore_debug("net_send_stream(%p, %p, %d, %p)", c, data, len, s);
+ kore_debug("net_send_stream(%p, %p, %d)", c, data, len);
nb = kore_pool_get(&nb_pool);
nb->cb = cb;
nb->owner = c;
nb->s_off = 0;
nb->buf = data;
- nb->stream = s;
nb->b_len = len;
nb->m_len = nb->b_len;
nb->type = NETBUF_SEND;
@@ -155,7 +145,6 @@ net_recv_queue(struct connection *c, u_int32_t len, int flags,
c->rnb->b_len = len;
c->rnb->m_len = len;
c->rnb->extra = NULL;
- c->rnb->stream = NULL;
c->rnb->flags = flags;
c->rnb->type = NETBUF_RECV;
c->rnb->buf = kore_malloc(c->rnb->b_len);
@@ -183,22 +172,7 @@ net_send(struct connection *c)
c->snb = TAILQ_FIRST(&(c->send_queue));
if (c->snb->b_len != 0) {
- if (c->snb->stream != NULL &&
- (c->snb->stream->flags & SPDY_DATAFRAME_PRELUDE)) {
- if (!spdy_dataframe_begin(c)) {
- c->snb = NULL;
- return (KORE_RESULT_OK);
- }
-
- c->snb = TAILQ_FIRST(&(c->send_queue));
- }
-
smin = c->snb->b_len - c->snb->s_off;
- if (c->snb->stream != NULL &&
- c->snb->stream->frame_size > 0) {
- smin = MIN(smin, c->snb->stream->frame_size);
- }
-
len = MIN(NETBUF_SEND_PAYLOAD_MAX, smin);
if (!c->write(c, len, &r))
@@ -211,8 +185,6 @@ net_send(struct connection *c)
c->snb->s_off += (size_t)r;
c->snb->flags &= ~NETBUF_MUST_RESEND;
- if (c->snb->stream != NULL)
- spdy_update_wsize(c, c->snb->stream, r);
}
if (c->snb->s_off == c->snb->b_len ||
@@ -249,7 +221,7 @@ net_recv_flush(struct connection *c)
kore_debug("net_recv_flush(%p)", c);
if (c->rnb == NULL)
- fatal("net_recv_flush(): c->rnb == NULL");
+ return (KORE_RESULT_OK);
while (c->flags & CONN_READ_POSSIBLE) {
if (!c->read(c, &r))
@@ -275,12 +247,11 @@ net_recv_flush(struct connection *c)
void
net_remove_netbuf(struct netbuf_head *list, struct netbuf *nb)
{
- kore_debug("net_remove_netbuf(%p, %p, %p)", list, nb, nb->stream);
+ kore_debug("net_remove_netbuf(%p, %p)", list, nb);
if (nb->type == NETBUF_RECV)
fatal("net_remove_netbuf(): cannot remove recv netbuf");
- nb->stream = NULL;
if (nb->flags & NETBUF_MUST_RESEND) {
kore_debug("retaining %p (MUST_RESEND)", nb);
nb->flags |= NETBUF_FORCE_REMOVE;
diff --git a/src/pool.c b/src/pool.c
@@ -64,10 +64,6 @@ kore_pool_get(struct kore_pool *pool)
pool->inuse++;
-#if defined(KORE_PEDANTIC_MALLOC)
- explicit_bzero(ptr, pool->elen);
-#endif
-
return (ptr);
}
@@ -76,10 +72,6 @@ kore_pool_put(struct kore_pool *pool, void *ptr)
{
struct kore_pool_entry *entry;
-#if defined(KORE_PEDANTIC_MALLOC)
- explicit_bzero(ptr, pool->elen);
-#endif
-
entry = (struct kore_pool_entry *)
((u_int8_t *)ptr - sizeof(struct kore_pool_entry));
diff --git a/src/spdy.c b/src/spdy.c
@@ -1,1025 +0,0 @@
-/*
- * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/param.h>
-
-#include <limits.h>
-
-#include "spdy.h"
-#include "kore.h"
-#include "http.h"
-
-static int spdy_ctrl_frame_syn_stream(struct netbuf *);
-static int spdy_ctrl_frame_rst_stream(struct netbuf *);
-static int spdy_ctrl_frame_settings(struct netbuf *);
-static int spdy_ctrl_frame_ping(struct netbuf *);
-static int spdy_ctrl_frame_window(struct netbuf *);
-static int spdy_ctrl_frame_goaway(struct netbuf *);
-static int spdy_data_frame_recv(struct netbuf *);
-
-static void spdy_block_write(struct connection *);
-static void spdy_enable_write(struct connection *);
-
-static int spdy_zlib_inflate(struct connection *, u_int8_t *,
- size_t, u_int8_t **, u_int32_t *);
-static int spdy_zlib_deflate(struct connection *, u_int8_t *,
- size_t, u_int8_t **, u_int32_t *);
-
-u_int64_t spdy_idle_time = 120000;
-u_int32_t spdy_recv_wsize = SPDY_INIT_WSIZE;
-
-int
-spdy_frame_recv(struct netbuf *nb)
-{
- struct spdy_stream *s;
- struct spdy_ctrl_frame ctrl;
- struct spdy_data_frame data;
- int (*cb)(struct netbuf *), r;
- struct connection *c = (struct connection *)nb->owner;
-
- kore_debug("spdy_frame_recv(%p)", nb);
-
- if (SPDY_CONTROL_FRAME(net_read32(nb->buf))) {
- ctrl.version = net_read16(nb->buf) & 0x7fff;
- ctrl.type = net_read16(nb->buf + 2);
- ctrl.flags = *(u_int8_t *)(nb->buf + 4);
- ctrl.length = net_read32(nb->buf + 4) & 0xffffff;
-
- kore_debug("received control frame %d", ctrl.type);
-
- if ((int)ctrl.length < 0) {
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- if (ctrl.version != 3) {
- kore_debug("protocol mismatch (recv version %u)",
- ctrl.version);
-
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- switch (ctrl.type) {
- case SPDY_CTRL_FRAME_SYN_STREAM:
- cb = spdy_ctrl_frame_syn_stream;
- break;
- case SPDY_CTRL_FRAME_RST_STREAM:
- cb = spdy_ctrl_frame_rst_stream;
- break;
- case SPDY_CTRL_FRAME_SETTINGS:
- cb = spdy_ctrl_frame_settings;
- break;
- case SPDY_CTRL_FRAME_PING:
- cb = spdy_ctrl_frame_ping;
- break;
- case SPDY_CTRL_FRAME_WINDOW:
- cb = spdy_ctrl_frame_window;
- break;
- case SPDY_CTRL_FRAME_GOAWAY:
- cb = spdy_ctrl_frame_goaway;
- break;
- default:
- cb = NULL;
- break;
- }
-
- r = KORE_RESULT_OK;
-
- if (cb != NULL) {
- net_recv_expand(c, ctrl.length, cb);
- } else {
- kore_debug("no callback for type %u", ctrl.type);
- }
- } else {
- data.stream_id = net_read32(nb->buf) & ~(1 << 31);
- if ((s = spdy_stream_lookup(c, data.stream_id)) == NULL) {
- if (!(c->flags & SPDY_CONN_GOAWAY)) {
- kore_debug("recv dataframe for bad stream: %u",
- data.stream_id);
- r = KORE_RESULT_ERROR;
- } else {
- r = KORE_RESULT_OK;
- }
- } else if (s->flags & FLAG_FIN) {
- kore_debug("received data frame but FLAG_FIN was set");
- r = KORE_RESULT_ERROR;
- } else {
- data.flags = *(u_int8_t *)(nb->buf + 4);
- data.length = net_read32(nb->buf + 4) & 0xffffff;
- if ((int)data.length < 0) {
- r = KORE_RESULT_ERROR;
- } else {
- r = KORE_RESULT_OK;
- net_recv_expand(c, data.length,
- spdy_data_frame_recv);
- }
- }
- }
-
- if (r != KORE_RESULT_OK) {
- r = KORE_RESULT_OK;
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- }
-
- return (r);
-}
-
-int
-spdy_dataframe_begin(struct connection *c)
-{
- struct spdy_stream *s = c->snb->stream;
-
- kore_debug("spdy_dataframe_begin(%p): s:%u fz:%d sz:%d wz:%d cwz:%d",
- c, s->stream_id, s->frame_size, s->send_size, s->send_wsize,
- c->spdy_send_wsize);
-
- if (s->frame_size != 0 || s->send_size == 0) {
- fatal("spdy_dataframe_begin(): s:%u fz:%d - sz:%d",
- s->stream_id, s->frame_size, s->send_size);
- }
-
- if ((int)s->send_wsize <= 0 || (int)c->spdy_send_wsize <= 0) {
- kore_debug("no space for new dataframe right now");
- spdy_block_write(c);
- return (KORE_RESULT_ERROR);
- }
-
- s->frame_size = MIN(NETBUF_SEND_PAYLOAD_MAX, s->send_size);
-
- kore_debug("spdy_dataframe_begin(): %u: fz:%d wz:%d cwz:%d",
- s->stream_id, s->frame_size, s->send_size, c->spdy_send_wsize);
-
- s->flags &= ~SPDY_DATAFRAME_PRELUDE;
- spdy_frame_send(c, SPDY_DATA_FRAME, 0, s->frame_size, s, 0);
-
- return (KORE_RESULT_OK);
-}
-
-void
-spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags,
- u_int32_t len, struct spdy_stream *s, u_int32_t misc)
-{
- u_int8_t nb[16];
- u_int32_t length;
-
- kore_debug("spdy_frame_send(%p, %u, %u, %u, %p, %u)",
- c, type, flags, len, s, misc);
-
- switch (type) {
- case SPDY_CTRL_FRAME_SYN_REPLY:
- case SPDY_DATA_FRAME:
- if (s == NULL)
- fatal("spdy_frame_send(): stream is NULL for %d", type);
- break;
- }
-
- length = 0;
- memset(nb, 0, sizeof(nb));
- switch (type) {
- case SPDY_CTRL_FRAME_PING:
- case SPDY_CTRL_FRAME_SYN_REPLY:
- net_write16(&nb[0], 3);
- nb[0] |= (1 << 7);
- net_write16(&nb[2], type);
-
- if (type != SPDY_CTRL_FRAME_PING) {
- net_write32(&nb[4], len + 4);
- nb[4] = flags;
- net_write32(&nb[8], s->stream_id);
- } else {
- net_write32(&nb[4], len);
- nb[4] = flags;
- net_write32(&nb[8], misc);
- }
-
- length = 12;
- break;
- case SPDY_CTRL_FRAME_GOAWAY:
- net_write16(&nb[0], 3);
- nb[0] |= (1 << 7);
- net_write16(&nb[2], type);
- net_write32(&nb[4], len);
- nb[4] = flags;
- length = 8;
- break;
- case SPDY_CTRL_FRAME_WINDOW:
- net_write16(&nb[0], 3);
- nb[0] |= (1 << 7);
- net_write16(&nb[2], type);
- net_write32(&nb[4], len);
- nb[4] = flags;
- net_write32(&nb[8], (s != NULL) ? s->stream_id : 0);
- net_write32(&nb[12], misc);
- length = 16;
- break;
- case SPDY_DATA_FRAME:
- net_write32(&nb[0], s->stream_id);
- nb[0] &= ~(1 << 7);
- net_write32(&nb[4], len);
- nb[4] = flags;
- length = 8;
- break;
- }
-
- if (type == SPDY_DATA_FRAME && !(flags & FLAG_FIN)) {
- net_send_queue(c, nb, length, NULL, NETBUF_BEFORE_CHAIN);
- } else {
- net_send_queue(c, nb, length, NULL, NETBUF_LAST_CHAIN);
- }
-}
-
-struct spdy_stream *
-spdy_stream_lookup(struct connection *c, u_int32_t id)
-{
- struct spdy_stream *s;
-
- TAILQ_FOREACH(s, &(c->spdy_streams), list) {
- if (s->stream_id == id)
- return (s);
- }
-
- return (NULL);
-}
-
-struct spdy_header_block *
-spdy_header_block_create(int delayed_alloc)
-{
- struct spdy_header_block *hblock;
-
- kore_debug("spdy_header_block_create()");
-
- hblock = kore_malloc(sizeof(*hblock));
- if (delayed_alloc == SPDY_HBLOCK_NORMAL) {
- hblock->header_block = kore_malloc(128);
- hblock->header_block_len = 128;
- hblock->header_offset = 4;
- } else {
- hblock->header_block = NULL;
- hblock->header_block_len = 0;
- hblock->header_offset = 0;
- }
-
- hblock->header_pairs = 0;
-
- return (hblock);
-}
-
-void
-spdy_header_block_add(struct spdy_header_block *hblock, char *name, char *value)
-{
- u_int8_t *p;
- u_int32_t nlen, vlen, tlen;
-
- kore_debug("spdy_header_block_add(%p, %s, %s)", hblock, name, value);
-
- nlen = strlen(name);
- vlen = strlen(value);
-
- tlen = nlen + 4 + vlen + 4;
- if ((tlen + hblock->header_offset) > hblock->header_block_len) {
- hblock->header_block_len += nlen + vlen + 128;
- hblock->header_block = kore_realloc(hblock->header_block,
- hblock->header_block_len);
- }
-
- p = hblock->header_block + hblock->header_offset;
- net_write32(p, nlen);
- memcpy((p + 4), (u_int8_t *)name, nlen);
- hblock->header_offset += 4 + nlen;
-
- p = hblock->header_block + hblock->header_offset;
- net_write32(p, vlen);
- memcpy((p + 4), (u_int8_t *)value, vlen);
- hblock->header_offset += 4 + vlen;
-
- hblock->header_pairs++;
-}
-
-u_int8_t *
-spdy_header_block_release(struct connection *c,
- struct spdy_header_block *hblock, u_int32_t *len)
-{
- u_int8_t *deflated;
-
- kore_debug("spdy_header_block_release(%p, %p)", hblock, len);
-
- net_write32(hblock->header_block, hblock->header_pairs);
- if (!spdy_zlib_deflate(c, hblock->header_block, hblock->header_offset,
- &deflated, len)) {
- kore_mem_free(hblock->header_block);
- kore_mem_free(hblock);
- return (NULL);
- }
-
- kore_mem_free(hblock->header_block);
- kore_mem_free(hblock);
-
- return (deflated);
-}
-
-int
-spdy_stream_get_header(struct spdy_header_block *s,
- const char *header, char **out)
-{
- char *cmp;
- u_int8_t *p, *end;
- u_int32_t i, nlen, vlen;
-
- kore_debug("spdy_stream_get_header(%p, %s) <%d>", s, header,
- s->header_pairs);
-
- p = s->header_block + 4;
- end = s->header_block + s->header_block_len;
-
- if (p >= end) {
- kore_debug("p >= end when looking for headers");
- return (KORE_RESULT_ERROR);
- }
-
- for (i = 0; i < s->header_pairs; i++) {
- nlen = net_read32(p);
- if ((int)nlen < 0 || (p + nlen + 4) > end) {
- kore_debug("nlen out of bounds on %u (%u)", i, nlen);
- return (KORE_RESULT_ERROR);
- }
-
- vlen = net_read32(p + nlen + 4);
- if ((int)vlen < 0 || (p + nlen + vlen + 8) > end) {
- kore_debug("vlen out of bounds on %u (%u)", i, vlen);
- return (KORE_RESULT_ERROR);
- }
-
- cmp = (char *)(p + 4);
- if (!strncasecmp(cmp, header, nlen)) {
- cmp = (char *)(p + nlen + 8);
- *out = kore_malloc(vlen + 1);
- kore_strlcpy(*out, cmp, vlen + 1);
- return (KORE_RESULT_OK);
- }
-
- p += nlen + vlen + 8;
- }
-
- return (KORE_RESULT_ERROR);
-}
-
-void
-spdy_session_teardown(struct connection *c, u_int8_t err)
-{
- u_int8_t d[8];
-
- kore_debug("spdy_session_teardown(%p, %u)", c, err);
-
- net_write32((u_int8_t *)&d[0], c->client_stream_id);
- net_write32((u_int8_t *)&d[4], err);
-
- spdy_frame_send(c, SPDY_CTRL_FRAME_GOAWAY, 0, 8, NULL, 0);
- net_send_queue(c, d, sizeof(d), NULL, NETBUF_LAST_CHAIN);
-
- c->flags &= ~CONN_READ_POSSIBLE;
- c->flags |= CONN_READ_BLOCK;
-
- net_send_flush(c);
- kore_connection_disconnect(c);
-}
-
-void
-spdy_update_wsize(struct connection *c, struct spdy_stream *s, u_int32_t len)
-{
- s->send_size -= len;
- s->frame_size -= len;
- s->send_wsize -= len;
- c->spdy_send_wsize -= len;
-
- kore_debug("spdy_update_wsize(): s:%u fz:%d sz:%d wz:%d cwz:%d",
- s->stream_id, s->frame_size, s->send_size,
- s->send_wsize, c->spdy_send_wsize);
-
- if (s->frame_size == 0 && s->send_size > 0) {
- kore_debug("spdy_update_wsize(): starting new data frame");
- s->flags |= SPDY_DATAFRAME_PRELUDE;
- }
-
- if (s->send_size == 0 && !(s->flags & SPDY_NO_CLOSE)) {
- if (!(s->flags & SPDY_KORE_FIN)) {
- s->flags |= SPDY_KORE_FIN;
- kore_debug("sending final frame %u", s->stream_id);
- spdy_frame_send(c, SPDY_DATA_FRAME, FLAG_FIN, 0, s, 0);
- }
-
- if (s->flags & (SPDY_KORE_FIN | FLAG_FIN)) {
- spdy_stream_close(c, s, SPDY_KEEP_NETBUFS);
- return;
- }
-
- kore_debug("%u remains half open\n", s->stream_id);
- }
-
- if ((int)s->send_wsize <= 0 || (int)c->spdy_send_wsize <= 0) {
- kore_debug("flow control kicked in for %p:%p", c, s);
- spdy_block_write(c);
- }
-}
-
-void
-spdy_stream_close(struct connection *c, struct spdy_stream *s, int rb)
-{
- struct http_request *req;
- struct netbuf *nb, *nt;
-
- kore_debug("spdy_stream_close(%p, %p) <%d>", c, s, s->stream_id);
-
- if (s->onclose != NULL)
- s->onclose(c, s);
-
- if (rb) {
- for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = nt) {
- nt = TAILQ_NEXT(nb, list);
- if (nb->stream == s) {
- kore_debug("spdy_stream_close: killing %p", nb);
- net_remove_netbuf(&(c->send_queue), nb);
- }
- }
- }
-
- TAILQ_REMOVE(&(c->spdy_streams), s, list);
- if (s->hblock != NULL) {
- if (s->hblock->header_block != NULL)
- kore_mem_free(s->hblock->header_block);
- kore_mem_free(s->hblock);
- }
-
- if (s->httpreq != NULL) {
- req = s->httpreq;
- req->stream = NULL;
- req->flags |= HTTP_REQUEST_DELETE;
- }
-
- kore_mem_free(s);
-}
-
-static int
-spdy_ctrl_frame_syn_stream(struct netbuf *nb)
-{
- struct spdy_stream *s;
- struct spdy_syn_stream syn;
- struct spdy_ctrl_frame ctrl;
- u_int8_t *src;
- char *host, *method, *path, *version;
- struct connection *c = (struct connection *)nb->owner;
-
- ctrl.version = net_read16(nb->buf) & 0x7fff;
- ctrl.type = net_read16(nb->buf + 2);
- ctrl.flags = *(u_int8_t *)(nb->buf + 4);
- ctrl.length = net_read32(nb->buf + 4) & 0xffffff;
-
- syn.stream_id = net_read32(nb->buf + 8);
- syn.assoc_stream_id = net_read32(nb->buf + 12);
- syn.prio = net_read16(nb->buf + 16) & 0xe000;
- syn.slot = net_read16(nb->buf + 16) & 0x7;
-
- kore_debug("spdy_ctrl_frame_syn_stream()");
- kore_debug("stream_id: %u", syn.stream_id);
- kore_debug("length : %u", ctrl.length);
-
- if (c->spdy_send_wsize > 0 && (c->flags & CONN_WRITE_BLOCK))
- spdy_enable_write(c);
-
- if ((int)ctrl.length < 0) {
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- if ((syn.stream_id % 2) == 0 || syn.stream_id == 0) {
- kore_debug("client sent incorrect id for SPDY_SYN_STREAM (%u)",
- syn.stream_id);
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- if (syn.stream_id < c->client_stream_id) {
- kore_debug("client sent incorrect id SPDY_SYN_STREAM (%u < %u)",
- syn.stream_id, c->client_stream_id);
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- if ((s = spdy_stream_lookup(c, syn.stream_id)) != NULL) {
- kore_debug("duplicate SPDY_SYN_STREAM (%u)", syn.stream_id);
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- s = kore_malloc(sizeof(*s));
- s->send_size = 0;
- s->frame_size = 0;
- s->httpreq = NULL;
- s->onclose = NULL;
- s->prio = syn.prio;
- s->flags = ctrl.flags;
- s->recv_wsize = spdy_recv_wsize;
- s->send_wsize = c->wsize_initial;
- s->stream_id = syn.stream_id;
- s->hblock = spdy_header_block_create(SPDY_HBLOCK_DELAYED_ALLOC);
-
- src = (nb->buf + SPDY_FRAME_SIZE + SPDY_SYNFRAME_SIZE);
- kore_debug("compressed headers are %u bytes long", ctrl.length - 10);
- if (!spdy_zlib_inflate(c, src, (ctrl.length - SPDY_SYNFRAME_SIZE),
- &(s->hblock->header_block), &(s->hblock->header_block_len))) {
- kore_mem_free(s->hblock->header_block);
- kore_mem_free(s->hblock);
- kore_mem_free(s);
- spdy_session_teardown(c, SPDY_SESSION_ERROR_INTERNAL);
- return (KORE_RESULT_OK);
- }
-
- s->hblock->header_pairs = net_read32(s->hblock->header_block);
- if ((int)s->hblock->header_pairs < 0) {
- kore_mem_free(s->hblock->header_block);
- kore_mem_free(s->hblock);
- kore_mem_free(s);
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- kore_debug("got %u headers", s->hblock->header_pairs);
-
- path = NULL;
- host = NULL;
- method = NULL;
- version = NULL;
-
-#define GET_HEADER(n, r) \
- if (!spdy_stream_get_header(s->hblock, n, r)) { \
- kore_mem_free(s->hblock->header_block); \
- kore_mem_free(s->hblock); \
- kore_mem_free(s); \
- kore_debug("no such header: %s", n); \
- if (path != NULL) \
- kore_mem_free(path); \
- if (host != NULL) \
- kore_mem_free(host); \
- if (method != NULL) \
- kore_mem_free(method); \
- if (version != NULL) \
- kore_mem_free(version); \
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); \
- return (KORE_RESULT_OK); \
- }
-
- GET_HEADER(":path", &path);
- GET_HEADER(":method", &method);
- GET_HEADER(":host", &host);
- GET_HEADER(":version", &version);
-
- c->client_stream_id = s->stream_id;
- TAILQ_INSERT_TAIL(&(c->spdy_streams), s, list);
-
- /*
- * We don't care so much for what http_request_new() tells us here,
- * we just have to clean up after passing our stuff to it.
- */
- (void)http_request_new(c, s, host, method, path, version,
- (struct http_request **)&(s->httpreq));
-
- kore_mem_free(path);
- kore_mem_free(method);
- kore_mem_free(host);
- kore_mem_free(version);
- net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
-
- kore_debug("SPDY_SYN_STREAM: %u:%u:%u", s->stream_id,
- s->flags, s->prio);
-
- return (KORE_RESULT_OK);
-}
-
-static int
-spdy_ctrl_frame_rst_stream(struct netbuf *nb)
-{
- struct spdy_stream *s;
- u_int32_t stream_id;
- struct connection *c = (struct connection *)nb->owner;
-
- stream_id = net_read32(nb->buf + SPDY_FRAME_SIZE);
- if ((stream_id % 2) == 0) {
- kore_debug("received RST for non-client stream %u", stream_id);
- return (KORE_RESULT_ERROR);
- }
-
- if ((s = spdy_stream_lookup(c, stream_id)) == NULL) {
- kore_debug("received RST for unknown stream %u", stream_id);
- return (KORE_RESULT_ERROR);
- }
-
- spdy_stream_close(c, s, SPDY_REMOVE_NETBUFS);
- net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
-
- return (KORE_RESULT_OK);
-}
-
-static int
-spdy_ctrl_frame_settings(struct netbuf *nb)
-{
- struct spdy_stream *s;
- u_int8_t *buf;
- u_int32_t ecount, i, id, val, length, diff;
- struct connection *c = (struct connection *)nb->owner;
-
- ecount = net_read32(nb->buf + SPDY_FRAME_SIZE);
- length = net_read32(nb->buf + 4) & 0xffffff;
- if ((int)ecount < 0 || (int)length < 0) {
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- kore_debug("SPDY_SETTINGS: %u settings present", ecount);
-
- if (length != ((ecount * 8) + 4)) {
- kore_debug("ecount is not correct (%u != %u)", length,
- (ecount * 8) + 4);
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- buf = nb->buf + SPDY_FRAME_SIZE + 4;
- for (i = 0; i < ecount; i++) {
- id = net_read32(buf) & 0xffffff;
- val = net_read32(buf + 4);
-
- if ((int)val < 0) {
- buf += 8;
- continue;
- }
-
- switch (id) {
- case SETTINGS_INITIAL_WINDOW_SIZE:
- diff = val - c->wsize_initial;
- c->wsize_initial = val;
- TAILQ_FOREACH(s, &(c->spdy_streams), list)
- s->send_wsize += diff;
- kore_debug("updated wsize with %d", diff);
- break;
- default:
- kore_debug("no handling for setting %u:%u", id, val);
- break;
- }
-
- buf += 8;
- }
-
- net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
-
- return (KORE_RESULT_OK);
-}
-
-static int
-spdy_ctrl_frame_ping(struct netbuf *nb)
-{
- u_int32_t id;
- struct connection *c = (struct connection *)nb->owner;
-
- id = ntohl(*(u_int32_t *)(nb->buf + SPDY_FRAME_SIZE));
- kore_debug("SPDY_PING: %u", id);
-
- /* XXX todo - check if we sent the ping. */
- if ((id % 2) == 0) {
- kore_debug("received malformed client PING (%u)", id);
- spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
- return (KORE_RESULT_OK);
- }
-
- spdy_frame_send(c, SPDY_CTRL_FRAME_PING, 0, 4, NULL, id);
- net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
-
- return (KORE_RESULT_OK);
-}
-
-static int
-spdy_ctrl_frame_window(struct netbuf *nb)
-{
- int r;
- struct spdy_stream *s;
- u_int32_t stream_id, window_size;
- struct connection *c = (struct connection *)nb->owner;
-
- stream_id = net_read32(nb->buf + SPDY_FRAME_SIZE);
- window_size = net_read32(nb->buf + SPDY_FRAME_SIZE + 4);
- kore_debug("window_update: %u for %u", window_size, stream_id);
-
- r = KORE_RESULT_OK;
- if ((s = spdy_stream_lookup(c, stream_id)) != NULL) {
- s->send_wsize += window_size;
- if ((u_int64_t)s->send_wsize > SPDY_FLOW_WINDOW_MAX) {
- kore_debug("window_update: size too large");
- return (KORE_RESULT_ERROR);
- }
-
- if (c->flags & CONN_WRITE_BLOCK &&
- s->send_wsize > 0 && c->spdy_send_wsize > 0) {
- kore_debug("stream %u no longer blocked", s->stream_id);
- spdy_enable_write(c);
- r = net_send_flush(c);
- }
- } else {
- c->spdy_send_wsize += window_size;
- if ((u_int64_t)c->spdy_send_wsize > SPDY_FLOW_WINDOW_MAX) {
- kore_debug("window_update: size too large");
- return (KORE_RESULT_ERROR);
- }
-
- if (c->flags & CONN_WRITE_BLOCK && c->spdy_send_wsize > 0) {
- kore_debug("session %p no longer blocked", c);
- spdy_enable_write(c);
- r = net_send_flush(c);
- }
- }
-
- net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
-
- return (r);
-}
-
-static int
-spdy_ctrl_frame_goaway(struct netbuf *nb)
-{
- struct connection *c = (struct connection *)nb->owner;
-
- kore_debug("spdy_ctrl_frame_goaway(%p)", c);
-
- c->flags |= SPDY_CONN_GOAWAY;
- kore_connection_disconnect(c);
-
- return (KORE_RESULT_OK);
-}
-
-static int
-spdy_data_frame_recv(struct netbuf *nb)
-{
- struct spdy_stream *s;
- int err;
- struct http_request *req;
- struct spdy_data_frame data;
- char *content;
- struct connection *c = (struct connection *)nb->owner;
-
- data.stream_id = net_read32(nb->buf) & ~(1 << 31);
- data.flags = *(u_int8_t *)(nb->buf + 4);
- data.length = net_read32(nb->buf + 4) & 0xffffff;
- kore_debug("SPDY_SESSION_DATA: %u:%u:%u", data.stream_id,
- data.flags, data.length);
-
- if ((int)data.length < 0)
- return (KORE_RESULT_ERROR);
-
- if ((s = spdy_stream_lookup(c, data.stream_id)) == NULL) {
- kore_debug("session data for non-existant stream");
- /* stream error */
- return (KORE_RESULT_ERROR);
- }
-
- req = (struct http_request *)s->httpreq;
- if (req == NULL || !(req->flags & HTTP_REQUEST_EXPECT_BODY)) {
- kore_debug("data frame for non post received");
- /* stream error */
- return (KORE_RESULT_ERROR);
- }
-
- if (req->http_body == NULL) {
- if (!spdy_stream_get_header(s->hblock,
- "content-length", &content)) {
- kore_debug("no content-length found for body");
- return (KORE_RESULT_ERROR);
- }
-
- s->post_size = kore_strtonum(content, 10, 0, LLONG_MAX, &err);
- if (err == KORE_RESULT_ERROR) {
- kore_debug("bad content-length: %s", content);
- kore_mem_free(content);
- return (KORE_RESULT_ERROR);
- }
-
- kore_mem_free(content);
-
- if (s->post_size == 0) {
- req->flags |= HTTP_REQUEST_COMPLETE;
- req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
- net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
- return (KORE_RESULT_OK);
- }
-
- if (s->post_size > http_body_max) {
- kore_log(LOG_NOTICE, "body data too large (%ld > %ld)",
- s->post_size, http_body_max);
- return (KORE_RESULT_ERROR);
- }
-
- req->http_body = kore_buf_create(s->post_size);
- }
-
- if ((req->http_body->offset + data.length) > s->post_size) {
- kore_debug("POST would grow too large");
- return (KORE_RESULT_ERROR);
- }
-
- kore_buf_append(req->http_body, (nb->buf + SPDY_FRAME_SIZE),
- data.length);
-
- if (data.flags & FLAG_FIN || req->http_body->offset == s->post_size) {
- if (req->http_body->offset != s->post_size) {
- kore_debug("FLAG_FIN before all POST data received");
- return (KORE_RESULT_ERROR);
- }
-
- s->post_size = 0;
- s->flags |= FLAG_FIN;
- req->flags |= HTTP_REQUEST_COMPLETE;
- req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
- }
-
- net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
-
- /*
- * XXX - This can be implemented better so we can stagger
- * window updates a bit and not constantly hit flow control.
- */
- s->recv_wsize -= data.length;
- spdy_frame_send(c, SPDY_CTRL_FRAME_WINDOW, 0, 8, s, data.length);
- s->recv_wsize += data.length;
-
- c->spdy_recv_wsize -= data.length;
- spdy_frame_send(c, SPDY_CTRL_FRAME_WINDOW, 0, 8, NULL, data.length);
- c->spdy_recv_wsize += data.length;
-
- kore_debug("data frame recv: wz:%d cwz:%d", s->recv_wsize,
- c->spdy_recv_wsize);
-
- return (KORE_RESULT_OK);
-}
-
-static void
-spdy_block_write(struct connection *c)
-{
- kore_debug("spdy_block_write(%p)", c);
-
- c->flags |= CONN_WRITE_BLOCK;
- c->flags &= ~CONN_WRITE_POSSIBLE;
-}
-
-static void
-spdy_enable_write(struct connection *c)
-{
- kore_debug("spdy_enable_write(%p)", c);
-
- c->flags &= ~CONN_WRITE_BLOCK;
- c->flags |= CONN_WRITE_POSSIBLE;
-}
-
-static int
-spdy_zlib_inflate(struct connection *c, u_int8_t *src, size_t len,
- u_int8_t **dst, u_int32_t *olen)
-{
- size_t have;
- int r, ret;
- u_char inflate_buffer[SPDY_ZLIB_CHUNK];
-
- kore_debug("spdy_zlib_inflate(%p, %p, %d)", c, src, len);
-
- if (c->inflate_started == 0) {
- c->z_inflate.avail_in = 0;
- c->z_inflate.next_in = Z_NULL;
- c->z_inflate.zalloc = Z_NULL;
- c->z_inflate.zfree = Z_NULL;
- if ((r = inflateInit(&(c->z_inflate))) != Z_OK) {
- kore_debug("inflateInit() failed: %d", r);
- return (KORE_RESULT_ERROR);
- }
-
- c->inflate_started = 1;
- }
-
- *olen = 0;
- *dst = NULL;
-
- ret = -1;
- c->z_inflate.avail_in = len;
- c->z_inflate.next_in = src;
- while (ret == -1) {
- c->z_inflate.avail_out = SPDY_ZLIB_CHUNK;
- c->z_inflate.next_out = inflate_buffer;
-
- r = inflate(&(c->z_inflate), Z_SYNC_FLUSH);
- switch (r) {
- case Z_NEED_DICT:
- r = inflateSetDictionary(&(c->z_inflate),
- SPDY_dictionary_txt, SPDY_ZLIB_DICT_SIZE);
- if (r != Z_OK) {
- inflateEnd(&(c->z_inflate));
- kore_debug("inflateSetDictionary(): %d", r);
- return (KORE_RESULT_ERROR);
- }
-
- continue;
- case Z_BUF_ERROR:
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- ret = KORE_RESULT_ERROR;
- kore_debug("inflate(): %d", r);
- break;
- case Z_OK:
- have = SPDY_ZLIB_CHUNK - c->z_inflate.avail_out;
- *olen += have;
- *dst = kore_realloc(*dst, *olen);
- memcpy((*dst) + (*olen - have), inflate_buffer, have);
-
- if (c->z_inflate.avail_in != 0 ||
- c->z_inflate.avail_out == 0)
- break;
- /* FALLTHROUGH */
- case Z_STREAM_END:
- ret = KORE_RESULT_OK;
- break;
- }
- }
-
- return (ret);
-}
-
-static int
-spdy_zlib_deflate(struct connection *c, u_int8_t *src, size_t len,
- u_int8_t **dst, u_int32_t *olen)
-{
- size_t have;
- int r, ret;
- u_char deflate_buffer[SPDY_ZLIB_CHUNK];
-
- kore_debug("spdy_zlib_deflate(%p, %p, %d)", c, src, len);
-
- if (c->deflate_started == 0) {
- c->z_deflate.avail_in = 0;
- c->z_deflate.next_in = Z_NULL;
- c->z_deflate.zalloc = Z_NULL;
- c->z_deflate.zfree = Z_NULL;
- if ((r = deflateInit(&(c->z_deflate), -1)) != Z_OK) {
- kore_debug("deflateInit() failed: %d", r);
- return (KORE_RESULT_ERROR);
- }
-
- r = deflateSetDictionary(&(c->z_deflate), SPDY_dictionary_txt,
- SPDY_ZLIB_DICT_SIZE);
- if (r != Z_OK) {
- deflateEnd(&(c->z_deflate));
- kore_debug("deflateSetDictionary(): %d", r);
- return (KORE_RESULT_ERROR);
- }
-
- c->deflate_started = 1;
- }
-
- *olen = 0;
- *dst = NULL;
-
- ret = -1;
- c->z_deflate.avail_in = len;
- c->z_deflate.next_in = src;
- while (ret == -1) {
- c->z_deflate.avail_out = SPDY_ZLIB_CHUNK;
- c->z_deflate.next_out = deflate_buffer;
-
- r = deflate(&(c->z_deflate), Z_SYNC_FLUSH);
- switch (r) {
- case Z_BUF_ERROR:
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- ret = KORE_RESULT_ERROR;
- kore_debug("deflate(): %d", r);
- break;
- case Z_OK:
- have = SPDY_ZLIB_CHUNK - c->z_deflate.avail_out;
- *olen += have;
- *dst = kore_realloc(*dst, *olen);
- memcpy((*dst) + (*olen - have), deflate_buffer, have);
-
- if (c->z_deflate.avail_in == 0 &&
- c->z_deflate.avail_out != 0)
- ret = KORE_RESULT_OK;
- break;
- }
- }
-
- return (ret);
-}
diff --git a/src/tasks.c b/src/tasks.c
@@ -56,7 +56,9 @@ void
kore_task_create(struct kore_task *t, int (*entry)(struct kore_task *))
{
t->cb = NULL;
+#if !defined(KORE_NO_HTTP)
t->req = NULL;
+#endif
t->entry = entry;
t->type = KORE_TYPE_TASK;
t->state = KORE_TASK_STATE_CREATED;
@@ -91,6 +93,7 @@ kore_task_run(struct kore_task *t)
pthread_cond_signal(&(tt->cond));
}
+#if !defined(KORE_NO_HTTP)
void
kore_task_bind_request(struct kore_task *t, struct http_request *req)
{
@@ -104,13 +107,15 @@ kore_task_bind_request(struct kore_task *t, struct http_request *req)
http_request_sleep(req);
}
+#endif
void
kore_task_bind_callback(struct kore_task *t, void (*cb)(struct kore_task *))
{
+#if !defined(KORE_NO_HTTP)
if (t->req != NULL)
fatal("cannot bind requests and cbs at the same time");
-
+#endif
t->cb = cb;
}
@@ -119,10 +124,12 @@ kore_task_destroy(struct kore_task *t)
{
kore_debug("kore_task_destroy: %p", t);
+#if !defined(KORE_NO_HTTP)
if (t->req != NULL) {
t->req = NULL;
LIST_REMOVE(t, rlist);
}
+#endif
pthread_rwlock_wrlock(&(t->lock));
@@ -198,16 +205,20 @@ kore_task_handle(struct kore_task *t, int finished)
{
kore_debug("kore_task_handle: %p, %d", t, finished);
+#if !defined(KORE_NO_HTTP)
if (t->req != NULL)
http_request_wakeup(t->req);
+#endif
if (finished) {
kore_platform_disable_read(t->fds[0]);
kore_task_set_state(t, KORE_TASK_STATE_FINISHED);
+#if !defined(KORE_NO_HTTP)
if (t->req != NULL) {
if (t->req->flags & HTTP_REQUEST_DELETE)
kore_task_destroy(t);
}
+#endif
}
if (t->cb != NULL)
diff --git a/src/websocket.c b/src/websocket.c
@@ -121,7 +121,7 @@ kore_websocket_send(struct connection *c, u_int8_t op, const void *data,
frame = kore_buf_create(len);
websocket_frame_build(frame, op, data, len);
- net_send_queue(c, frame->data, frame->offset, NULL, NETBUF_LAST_CHAIN);
+ net_send_queue(c, frame->data, frame->offset);
kore_buf_free(frame);
}
@@ -137,8 +137,7 @@ kore_websocket_broadcast(struct connection *src, u_int8_t op, const void *data,
TAILQ_FOREACH(c, &connections, list) {
if (c != src && c->proto == CONN_PROTO_WEBSOCKET) {
- net_send_queue(c, frame->data, frame->offset,
- NULL, NETBUF_LAST_CHAIN);
+ net_send_queue(c, frame->data, frame->offset);
net_send_flush(c);
}
}
diff --git a/src/worker.c b/src/worker.c
@@ -27,7 +27,10 @@
#include <signal.h>
#include "kore.h"
+
+#if !defined(KORE_NO_HTTP)
#include "http.h"
+#endif
#if defined(KORE_USE_PGSQL)
#include "pgsql.h"
@@ -271,7 +274,10 @@ kore_worker_entry(struct kore_worker *kw)
signal(SIGINT, SIG_IGN);
net_init();
+#if !defined(KORE_NO_HTTP)
http_init();
+ kore_accesslog_worker_init();
+#endif
kore_timer_init();
kore_connection_init();
kore_domain_load_crl();
@@ -281,7 +287,6 @@ kore_worker_entry(struct kore_worker *kw)
next_lock = 0;
idle_check = 0;
kore_platform_event_init();
- kore_accesslog_worker_init();
kore_msg_worker_init();
#if defined(KORE_USE_PGSQL)
@@ -330,7 +335,9 @@ kore_worker_entry(struct kore_worker *kw)
next_lock = now + WORKER_LOCK_TIMEOUT;
}
+#if !defined(KORE_NO_HTTP)
http_process();
+#endif
if ((now - idle_check) >= 10000) {
idle_check = now;
@@ -339,8 +346,13 @@ kore_worker_entry(struct kore_worker *kw)
kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
+#if !defined(KORE_NO_HTTP)
if (quit && http_request_count == 0)
break;
+#else
+ if (quit)
+ break;
+#endif
}
kore_connection_prune(KORE_CONNECTION_PRUNE_ALL);