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.
This commit is contained in:
Joris Vink 2015-11-27 16:22:50 +01:00
parent a88e56ae25
commit 769c78a6e8
31 changed files with 578 additions and 1843 deletions

View File

@ -6,30 +6,35 @@ KORE=kore
INSTALL_DIR=$(PREFIX)/bin INSTALL_DIR=$(PREFIX)/bin
INCLUDE_DIR=$(PREFIX)/include/kore INCLUDE_DIR=$(PREFIX)/include/kore
S_SRC= src/kore.c src/accesslog.c src/auth.c src/buf.c src/cli.c \ S_SRC= src/kore.c src/buf.c src/cli.c src/config.c src/connection.c \
src/config.c src/connection.c src/domain.c src/http.c src/mem.c \ src/domain.c src/mem.c src/msg.c src/module.c src/net.c \
src/msg.c src/module.c src/net.c src/pool.c src/spdy.c src/timer.c \ src/pool.c src/timer.c src/utils.c src/worker.c
src/validator.c src/utils.c src/websocket.c src/worker.c \
src/zlib_dict.c
S_OBJS= $(S_SRC:.c=.o) S_OBJS= $(S_SRC:.c=.o)
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+=-Wsign-compare -Iincludes -g CFLAGS+=-Wsign-compare -Iincludes -g
CFLAGS+=-DPREFIX='"$(PREFIX)"' CFLAGS+=-DPREFIX='"$(PREFIX)"'
LDFLAGS+=-rdynamic -lssl -lcrypto -lz LDFLAGS=-rdynamic -lssl -lcrypto
ifneq ("$(DEBUG)", "") ifneq ("$(DEBUG)", "")
CFLAGS+=-DKORE_DEBUG CFLAGS+=-DKORE_DEBUG
endif endif
ifneq ("$(KORE_PEDANTIC_MALLOC)", "") ifneq ("$(NOHTTP)", "")
CFLAGS+=-DKORE_PEDANTIC_MALLOC 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 endif
ifneq ("$(NOTLS)", "") ifneq ("$(NOTLS)", "")
CFLAGS+=-DKORE_NO_TLS CFLAGS+=-DKORE_NO_TLS
LDFLAGS=-rdynamic -lz -lcrypto ifneq ("$(NOHTTP)", "")
LDFLAGS=-rdynamic
else
LDFLAGS=-rdynamic -lcrypto
endif
endif endif
ifneq ("$(PGSQL)", "") ifneq ("$(PGSQL)", "")

View File

@ -11,7 +11,6 @@ Because of this Kore is an ideal candidate for building robust, scalable and sec
Features Features
-------- --------
* Supports SNI * Supports SNI
* Supports SPDY/3.1
* Supports HTTP/1.1 * Supports HTTP/1.1
* Websocket support * Websocket support
* Lightweight background tasks * Lightweight background tasks
@ -52,8 +51,8 @@ Building Kore
------------- -------------
Requirements Requirements
* libz * openssl (latest is always the safest bet, right?)
* openssl >= 1.0.1i (note: this requirement drops away when building with NOTLS=1 NOHTTP=1)
Requirements for background tasks (optional) Requirements for background tasks (optional)
* pthreads * pthreads
@ -64,7 +63,6 @@ Requirements for pgsql (optional)
Normal compilation and installation: Normal compilation and installation:
``` ```
# git clone https://github.com/jorisvink/kore.git
# cd kore # cd kore
# make # make
# make install # make install
@ -77,7 +75,7 @@ those by setting a shell environment variable before running **_make_**.
* PGSQL=1 (compiles in pgsql support) * PGSQL=1 (compiles in pgsql support)
* DEBUG=1 (enables use of -d for debug) * DEBUG=1 (enables use of -d for debug)
* NOTLS=1 (compiles Kore without TLS) * NOTLS=1 (compiles Kore without TLS)
* KORE_PEDANTIC_MALLOC=1 (zero all allocated memory) * NOHTTP=1 (compiles Kore without HTTP support)
Example libraries Example libraries
----------------- -----------------

View File

@ -104,10 +104,6 @@ validator v_session function v_session_validate
# a generated DH key (See OpenSSL dhparam). # a generated DH key (See OpenSSL dhparam).
#tls_dhparam dh2048.pem #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 # Authentication configuration
# #
# Using authentication blocks you can define a standard way for # Using authentication blocks you can define a standard way for
@ -187,7 +183,6 @@ domain localhost {
static / serve_index static / serve_index
static /intro.jpg serve_intro static /intro.jpg serve_intro
static /b64test serve_b64test static /b64test serve_b64test
static /spdy-reset serve_spdyreset
static /upload serve_file_upload static /upload serve_file_upload
static /lock-test serve_lock_test static /lock-test serve_lock_test
static /validator serve_validator static /validator serve_validator

View File

@ -26,7 +26,6 @@ domain 127.0.0.1 {
static / serve_index static / serve_index
static /intro.jpg serve_intro static /intro.jpg serve_intro
static /b64test serve_b64test static /b64test serve_b64test
static /spdy-reset serve_spdyreset
static /upload serve_file_upload static /upload serve_file_upload
static /validator serve_validator static /validator serve_validator
static /params-test serve_params_test static /params-test serve_params_test

View File

@ -25,7 +25,6 @@ int serve_style_css(struct http_request *);
int serve_index(struct http_request *); int serve_index(struct http_request *);
int serve_intro(struct http_request *); int serve_intro(struct http_request *);
int serve_b64test(struct http_request *); int serve_b64test(struct http_request *);
int serve_spdyreset(struct http_request *);
int serve_file_upload(struct http_request *); int serve_file_upload(struct http_request *);
int serve_validator(struct http_request *); int serve_validator(struct http_request *);
int serve_params_test(struct http_request *); int serve_params_test(struct http_request *);
@ -132,13 +131,6 @@ serve_b64test(struct http_request *req)
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
int
serve_spdyreset(struct http_request *req)
{
spdy_session_teardown(req->owner, SPDY_SESSION_ERROR_OK);
return (KORE_RESULT_OK);
}
int int
serve_file_upload(struct http_request *req) serve_file_upload(struct http_request *req)
{ {

View File

@ -163,7 +163,7 @@ ktunnel_pipe_data(struct netbuf *nb)
printf("received %d bytes on pipe %p (-> %p)\n", nb->s_off, src, dst); 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_send_flush(dst);
net_recv_reset(src, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data); net_recv_reset(src, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data);

5
examples/nohttp/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.o
.objs
nohttp.so
assets.h
cert

16
examples/nohttp/README.md Normal file
View File

@ -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
```

View File

@ -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
}

View File

@ -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);
}

View File

@ -5,7 +5,6 @@ load ./sse.so
tls_dhparam dh2048.pem tls_dhparam dh2048.pem
http_keepalive_time 600 http_keepalive_time 600
spdy_idle_time 600
domain 127.0.0.1 { domain 127.0.0.1 {
certfile cert/server.crt certfile cert/server.crt

View File

@ -16,7 +16,6 @@
/* /*
* Simple example of how SSE (Server Side Events) could be used in Kore. * 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. * Upon new arrivals, a join event is broadcast to all clients.
* If a client goes away a leave event is broadcasted. * 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_disconnect(struct connection *);
void sse_send(struct connection *, void *, size_t); void sse_send(struct connection *, void *, size_t);
void sse_broadcast(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 *); 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. * to their hdlr_extra pointer member.
*/ */
struct sse_state { struct sse_state {
struct spdy_stream *stream;
struct kore_timer *timer; 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. */ /* Set a disconnection method so we know when this client goes away. */
req->owner->disconnect = sse_disconnect; req->owner->disconnect = sse_disconnect;
/* For non SPDY clients we do not expect any more data to arrive. */ /* We do not expect any more data to arrive. */
if (req->owner->proto != CONN_PROTO_SPDY) req->owner->flags |= CONN_READ_BLOCK;
req->owner->flags |= CONN_READ_BLOCK;
/* Allocate a state to be carried by our connection. */ /* Allocate a state to be carried by our connection. */
state = kore_malloc(sizeof(*state)); state = kore_malloc(sizeof(*state));
state->stream = req->stream; state->stream = req->stream;
req->owner->hdlr_extra = state; 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. */ /* Now start a timer to send a ping back every 10 second. */
state->timer = kore_timer_add(sse_ping, 10000, req->owner, 0); 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) if (state == NULL)
return; 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. */ /* Queue outgoing data now. */
net_send_queue(c, data, len, state->stream, NETBUF_LAST_CHAIN); net_send_queue(c, data, len, state->stream, NETBUF_LAST_CHAIN);
net_send_flush(c); net_send_flush(c);
@ -194,12 +158,6 @@ sse_disconnect(struct connection *c)
/* Tell others we are leaving. */ /* Tell others we are leaving. */
sse_broadcast(c, leaving, strlen(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. */ /* Kill our timer and free/remove the state. */
kore_timer_remove(state->timer); kore_timer_remove(state->timer);
kore_mem_free(state); kore_mem_free(state);
@ -209,23 +167,6 @@ sse_disconnect(struct connection *c)
c->disconnect = NULL; 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 int
check_header(struct http_request *req, const char *name, const char *value) check_header(struct http_request *req, const char *name, const char *value)
{ {

View File

@ -5,7 +5,6 @@ load ./video_stream.so init
tls_dhparam dh2048.pem tls_dhparam dh2048.pem
spdy_idle_time 600
http_keepalive_time 600 http_keepalive_time 600
domain 127.0.0.1 { domain 127.0.0.1 {

View File

@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#if !defined(KORE_NO_HTTP)
#ifndef __H_HTTP_H #ifndef __H_HTTP_H
#define __H_HTTP_H #define __H_HTTP_H
@ -183,7 +185,6 @@ struct http_request {
char *path; char *path;
char *agent; char *agent;
struct connection *owner; struct connection *owner;
struct spdy_stream *stream;
struct kore_buf *http_body; struct kore_buf *http_body;
void *hdlr_extra; void *hdlr_extra;
char *query_string; char *query_string;
@ -230,8 +231,8 @@ int http_request_header(struct http_request *,
const char *, char **); const char *, char **);
void http_response_header(struct http_request *, void http_response_header(struct http_request *,
const char *, const char *); const char *, const char *);
int http_request_new(struct connection *, struct spdy_stream *, int http_request_new(struct connection *, const char *,
const char *, const char *, const char *, const char *, const char *, const char *, const char *,
struct http_request **); struct http_request **);
int http_state_run(struct http_state *, u_int8_t, int http_state_run(struct http_state *, u_int8_t,
struct http_request *); struct http_request *);
@ -294,3 +295,5 @@ enum http_status_code {
} }
#endif #endif
#endif /* !__H_HTTP_H */ #endif /* !__H_HTTP_H */
#endif /* ! KORE_NO_HTTP */

View File

@ -46,8 +46,6 @@ extern "C" {
extern int daemon(int, int); extern int daemon(int, int);
#endif #endif
#include "spdy.h"
#define KORE_RESULT_ERROR 0 #define KORE_RESULT_ERROR 0
#define KORE_RESULT_OK 1 #define KORE_RESULT_OK 1
#define KORE_RESULT_RETRY 2 #define KORE_RESULT_RETRY 2
@ -95,8 +93,10 @@ extern int daemon(int, int);
#define X509_CN_LENGTH (ub_common_name + 1) #define X509_CN_LENGTH (ub_common_name + 1)
/* XXX hackish. */ /* XXX hackish. */
#if !defined(KORE_NO_HTTP)
struct http_request; struct http_request;
struct spdy_stream; #endif
struct connection;
struct netbuf { struct netbuf {
u_int8_t *buf; u_int8_t *buf;
@ -107,7 +107,6 @@ struct netbuf {
u_int8_t flags; u_int8_t flags;
void *owner; void *owner;
struct spdy_stream *stream;
void *extra; void *extra;
int (*cb)(struct netbuf *); int (*cb)(struct netbuf *);
@ -124,9 +123,9 @@ TAILQ_HEAD(netbuf_head, netbuf);
struct listener { struct listener {
u_int8_t type; u_int8_t type;
int fd;
u_int8_t addrtype; u_int8_t addrtype;
int fd;
void (*connect)(struct connection *);
union { union {
struct sockaddr_in ipv4; struct sockaddr_in ipv4;
@ -144,10 +143,9 @@ LIST_HEAD(listener_head, listener);
#define CONN_STATE_DISCONNECTING 3 #define CONN_STATE_DISCONNECTING 3
#define CONN_PROTO_UNKNOWN 0 #define CONN_PROTO_UNKNOWN 0
#define CONN_PROTO_SPDY 1 #define CONN_PROTO_HTTP 1
#define CONN_PROTO_HTTP 2 #define CONN_PROTO_WEBSOCKET 2
#define CONN_PROTO_WEBSOCKET 3 #define CONN_PROTO_MSG 3
#define CONN_PROTO_MSG 4
#define CONN_READ_POSSIBLE 0x01 #define CONN_READ_POSSIBLE 0x01
#define CONN_WRITE_POSSIBLE 0x02 #define CONN_WRITE_POSSIBLE 0x02
@ -155,7 +153,6 @@ LIST_HEAD(listener_head, listener);
#define CONN_IDLE_TIMER_ACT 0x10 #define CONN_IDLE_TIMER_ACT 0x10
#define CONN_READ_BLOCK 0x20 #define CONN_READ_BLOCK 0x20
#define CONN_CLOSE_EMPTY 0x40 #define CONN_CLOSE_EMPTY 0x40
#define SPDY_CONN_GOAWAY 0x80
#define KORE_IDLE_TIMER_MAX 20000 #define KORE_IDLE_TIMER_MAX 20000
@ -202,22 +199,13 @@ struct connection {
u_int64_t start; u_int64_t start;
} idle_timer; } 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_head send_queue;
struct netbuf *snb; struct netbuf *snb;
struct netbuf *rnb; struct netbuf *rnb;
u_int32_t client_stream_id; #if !defined(KORE_NO_HTTP)
TAILQ_HEAD(, spdy_stream) spdy_streams;
TAILQ_HEAD(, http_request) http_requests; TAILQ_HEAD(, http_request) http_requests;
#endif
TAILQ_ENTRY(connection) list; TAILQ_ENTRY(connection) list;
TAILQ_ENTRY(connection) flush_list; TAILQ_ENTRY(connection) flush_list;
@ -227,6 +215,8 @@ TAILQ_HEAD(connection_list, connection);
extern struct connection_list connections; extern struct connection_list connections;
extern struct connection_list disconnected; extern struct connection_list disconnected;
#if !defined(KORE_NO_HTTP)
struct kore_handler_params { struct kore_handler_params {
char *name; char *name;
u_int8_t method; u_int8_t method;
@ -249,12 +239,14 @@ struct kore_auth {
TAILQ_ENTRY(kore_auth) list; TAILQ_ENTRY(kore_auth) list;
}; };
#define KORE_MODULE_LOAD 1
#define KORE_MODULE_UNLOAD 2
#define HANDLER_TYPE_STATIC 1 #define HANDLER_TYPE_STATIC 1
#define HANDLER_TYPE_DYNAMIC 2 #define HANDLER_TYPE_DYNAMIC 2
#endif
#define KORE_MODULE_LOAD 1
#define KORE_MODULE_UNLOAD 2
struct kore_module { struct kore_module {
void *handle; void *handle;
char *path; char *path;
@ -274,9 +266,10 @@ struct kore_module_handle {
int errors; int errors;
regex_t rctx; regex_t rctx;
struct kore_domain *dom; struct kore_domain *dom;
#if !defined(KORE_NO_HTTP)
struct kore_auth *auth; struct kore_auth *auth;
TAILQ_HEAD(, kore_handler_params) params; TAILQ_HEAD(, kore_handler_params) params;
#endif
TAILQ_ENTRY(kore_module_handle) list; TAILQ_ENTRY(kore_module_handle) list;
}; };
@ -304,6 +297,8 @@ struct kore_domain {
TAILQ_HEAD(kore_domain_h, kore_domain); TAILQ_HEAD(kore_domain_h, kore_domain);
#if !defined(KORE_NO_HTTP)
#define KORE_VALIDATOR_TYPE_REGEX 1 #define KORE_VALIDATOR_TYPE_REGEX 1
#define KORE_VALIDATOR_TYPE_FUNCTION 2 #define KORE_VALIDATOR_TYPE_FUNCTION 2
@ -316,6 +311,7 @@ struct kore_validator {
TAILQ_ENTRY(kore_validator) list; TAILQ_ENTRY(kore_validator) list;
}; };
#endif
#define KORE_BUF_INITIAL 128 #define KORE_BUF_INITIAL 128
#define KORE_BUF_INCREMENT KORE_BUF_INITIAL #define KORE_BUF_INCREMENT KORE_BUF_INITIAL
@ -394,7 +390,6 @@ extern int tls_version;
extern DH *tls_dhparam; extern DH *tls_dhparam;
extern u_int8_t nlisteners; extern u_int8_t nlisteners;
extern u_int64_t spdy_idle_time;
extern u_int16_t cpu_count; extern u_int16_t cpu_count;
extern u_int8_t worker_count; extern u_int8_t worker_count;
extern u_int8_t worker_set_affinity; extern u_int8_t worker_set_affinity;
@ -441,10 +436,12 @@ void kore_accesslog_init(void);
void kore_accesslog_worker_init(void); void kore_accesslog_worker_init(void);
int kore_accesslog_write(const void *, u_int32_t); int kore_accesslog_write(const void *, u_int32_t);
#if !defined(KORE_NO_HTTP)
int kore_auth_run(struct http_request *, struct kore_auth *); int kore_auth_run(struct http_request *, struct kore_auth *);
void kore_auth_init(void); void kore_auth_init(void);
int kore_auth_new(const char *); int kore_auth_new(const char *);
struct kore_auth *kore_auth_lookup(const char *); struct kore_auth *kore_auth_lookup(const char *);
#endif
void kore_timer_init(void); void kore_timer_init(void);
u_int64_t kore_timer_run(u_int64_t); 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); u_int64_t, void *, int);
int kore_tls_sni_cb(SSL *, int *, void *); int kore_tls_sni_cb(SSL *, int *, void *);
int kore_server_bind(const char *, const char *); int kore_server_bind(const char *, const char *, const char *);
int kore_tls_npn_cb(SSL *, const u_char **, unsigned int *, void *);
void kore_tls_info_callback(const SSL *, int, int); void kore_tls_info_callback(const SSL *, int, int);
void kore_connection_init(void); void kore_connection_init(void);
@ -482,10 +478,6 @@ void *kore_realloc(void *, size_t);
void kore_mem_free(void *); void kore_mem_free(void *);
void kore_mem_init(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_get(struct kore_pool *);
void kore_pool_put(struct kore_pool *, void *); void kore_pool_put(struct kore_pool *, void *);
void kore_pool_init(struct kore_pool *, const char *, 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 *); int kore_base64_decode(char *, u_int8_t **, u_int32_t *);
void *kore_mem_find(void *, size_t, void *, 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 *, void kore_websocket_handshake(struct http_request *,
struct kore_wscbs *); struct kore_wscbs *);
void kore_websocket_send(struct connection *, void kore_websocket_send(struct connection *,
u_int8_t, const void *, size_t); u_int8_t, const void *, size_t);
void kore_websocket_broadcast(struct connection *, void kore_websocket_broadcast(struct connection *,
u_int8_t, const void *, size_t, int); u_int8_t, const void *, size_t, int);
#endif
void kore_msg_init(void); void kore_msg_init(void);
void kore_msg_worker_init(void); void kore_msg_worker_init(void);
void kore_msg_parent_init(void); void kore_msg_parent_init(void);
void kore_msg_parent_add(struct kore_worker *); void kore_msg_parent_add(struct kore_worker *);
void kore_msg_parent_remove(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, int kore_msg_register(u_int8_t,
void (*cb)(struct kore_msg *, const void *)); 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 *, struct kore_module_handle *kore_module_handler_find(const char *,
const char *); const char *);
#if !defined(KORE_NO_HTTP)
void kore_validator_init(void); void kore_validator_init(void);
void kore_validator_reload(void); void kore_validator_reload(void);
int kore_validator_add(const char *, u_int8_t, const char *); 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 *, int kore_validator_check(struct http_request *,
struct kore_validator *, void *); struct kore_validator *, void *);
struct kore_validator *kore_validator_lookup(const char *); struct kore_validator *kore_validator_lookup(const char *);
#endif
void fatal(const char *, ...) __attribute__((noreturn)); void fatal(const char *, ...) __attribute__((noreturn));
void kore_debug_internal(char *, int, const char *, ...); 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 *)); int (*cb)(struct netbuf *));
void net_recv_expand(struct connection *c, u_int32_t, void net_recv_expand(struct connection *c, u_int32_t,
int (*cb)(struct netbuf *)); int (*cb)(struct netbuf *));
void net_send_queue(struct connection *, const void *, void net_send_queue(struct connection *, const void *, u_int32_t);
u_int32_t, struct spdy_stream *, int);
void net_send_stream(struct connection *, void *, void net_send_stream(struct connection *, void *,
u_int32_t, struct spdy_stream *, u_int32_t, int (*cb)(struct netbuf *), struct netbuf **);
int (*cb)(struct netbuf *), struct netbuf **);
void kore_buf_free(struct kore_buf *); void kore_buf_free(struct kore_buf *);
struct kore_buf *kore_buf_create(u_int32_t); 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_appendb(struct kore_buf *, struct kore_buf *);
void kore_buf_replace_string(struct kore_buf *, char *, void *, size_t); 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) #if defined(__cplusplus)
} }
#endif #endif

View File

@ -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 */

View File

@ -30,7 +30,9 @@
extern "C" { extern "C" {
#endif #endif
#if !defined(KORE_NO_HTTP)
struct http_request; struct http_request;
#endif
struct kore_task { struct kore_task {
u_int8_t type; u_int8_t type;
@ -38,7 +40,10 @@ struct kore_task {
int result; int result;
pthread_rwlock_t lock; pthread_rwlock_t lock;
#if !defined(KORE_NO_HTTP)
struct http_request *req; struct http_request *req;
#endif
int fds[2]; int fds[2];
int (*entry)(struct kore_task *); int (*entry)(struct kore_task *);
void (*cb)(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 *); int kore_task_finished(struct kore_task *);
void kore_task_handle(struct kore_task *, int); void kore_task_handle(struct kore_task *, int);
#if !defined(KORE_NO_HTTP)
void kore_task_bind_request(struct kore_task *, void kore_task_bind_request(struct kore_task *,
struct http_request *); struct http_request *);
#endif
void kore_task_bind_callback(struct kore_task *, void kore_task_bind_callback(struct kore_task *,
void (*cb)(struct kore_task *)); void (*cb)(struct kore_task *));
void kore_task_create(struct kore_task *, void kore_task_create(struct kore_task *,

View File

@ -37,23 +37,29 @@
static int configure_include(char **); static int configure_include(char **);
static int configure_bind(char **); static int configure_bind(char **);
static int configure_load(char **); static int configure_load(char **);
static int configure_handler(char **);
static int configure_domain(char **); static int configure_domain(char **);
static int configure_chroot(char **); static int configure_chroot(char **);
static int configure_runas(char **); static int configure_runas(char **);
static int configure_workers(char **); static int configure_workers(char **);
static int configure_pidfile(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_rlimit_nofiles(char **);
static int configure_max_connections(char **); static int configure_max_connections(char **);
static int configure_accept_threshold(char **); static int configure_accept_threshold(char **);
static int configure_set_affinity(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_version(char **);
static int configure_tls_cipher(char **); static int configure_tls_cipher(char **);
static int configure_tls_dhparam(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_header_max(char **);
static int configure_http_body_max(char **); static int configure_http_body_max(char **);
static int configure_http_hsts_enable(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_validator(char **);
static int configure_params(char **); static int configure_params(char **);
static int configure_validate(char **); static int configure_validate(char **);
static int configure_client_certificates(char **);
static int configure_authentication(char **); static int configure_authentication(char **);
static int configure_authentication_uri(char **); static int configure_authentication_uri(char **);
static int configure_authentication_type(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_authentication_validator(char **);
static int configure_websocket_maxframe(char **); static int configure_websocket_maxframe(char **);
static int configure_websocket_timeout(char **); static int configure_websocket_timeout(char **);
static int configure_socket_backlog(char **); #endif
#if defined(KORE_USE_PGSQL) #if defined(KORE_USE_PGSQL)
static int configure_pgsql_conn_max(char **); static int configure_pgsql_conn_max(char **);
@ -90,12 +95,6 @@ static struct {
{ "include", configure_include }, { "include", configure_include },
{ "bind", configure_bind }, { "bind", configure_bind },
{ "load", configure_load }, { "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 }, { "domain", configure_domain },
{ "chroot", configure_chroot }, { "chroot", configure_chroot },
{ "runas", configure_runas }, { "runas", configure_runas },
@ -105,10 +104,19 @@ static struct {
{ "worker_accept_threshold", configure_accept_threshold }, { "worker_accept_threshold", configure_accept_threshold },
{ "worker_set_affinity", configure_set_affinity }, { "worker_set_affinity", configure_set_affinity },
{ "pidfile", configure_pidfile }, { "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 }, { "certfile", configure_certfile },
{ "certkey", configure_certkey }, { "certkey", configure_certkey },
{ "client_certificates", configure_client_certificates }, { "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_header_max", configure_http_header_max },
{ "http_body_max", configure_http_body_max }, { "http_body_max", configure_http_body_max },
{ "http_hsts_enable", configure_http_hsts_enable }, { "http_hsts_enable", configure_http_hsts_enable },
@ -124,7 +132,7 @@ static struct {
{ "authentication_validator", configure_authentication_validator }, { "authentication_validator", configure_authentication_validator },
{ "websocket_maxframe", configure_websocket_maxframe }, { "websocket_maxframe", configure_websocket_maxframe },
{ "websocket_timeout", configure_websocket_timeout }, { "websocket_timeout", configure_websocket_timeout },
{ "socket_backlog", configure_socket_backlog }, #endif
#if defined(KORE_USE_PGSQL) #if defined(KORE_USE_PGSQL)
{ "pgsql_conn_max", configure_pgsql_conn_max }, { "pgsql_conn_max", configure_pgsql_conn_max },
#endif #endif
@ -135,10 +143,14 @@ static struct {
}; };
char *config_file = NULL; char *config_file = NULL;
#if !defined(KORE_NO_HTTP)
static u_int8_t current_method = 0; static u_int8_t current_method = 0;
static struct kore_auth *current_auth = NULL; static struct kore_auth *current_auth = NULL;
static struct kore_domain *current_domain = NULL;
static struct kore_module_handle *current_handler = NULL; static struct kore_module_handle *current_handler = NULL;
#endif
static struct kore_domain *current_domain = NULL;
void void
kore_parse_config(void) kore_parse_config(void)
@ -197,6 +209,7 @@ kore_parse_config_file(char *fpath)
*t = ' '; *t = ' ';
} }
#if !defined(KORE_NO_HTTP)
if (!strcmp(p, "}") && current_handler != NULL) { if (!strcmp(p, "}") && current_handler != NULL) {
lineno++; lineno++;
current_handler = NULL; current_handler = NULL;
@ -213,6 +226,7 @@ kore_parse_config_file(char *fpath)
current_auth = NULL; current_auth = NULL;
continue; continue;
} }
#endif
if (!strcmp(p, "}") && current_domain != NULL) if (!strcmp(p, "}") && current_domain != NULL)
domain_sslstart(); domain_sslstart();
@ -262,7 +276,7 @@ configure_bind(char **argv)
if (argv[1] == NULL || argv[2] == NULL) if (argv[1] == NULL || argv[2] == NULL)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
return (kore_server_bind(argv[1], argv[2])); return (kore_server_bind(argv[1], argv[2], argv[3]));
} }
static int static int
@ -275,6 +289,7 @@ configure_load(char **argv)
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
#if !defined(KORE_NO_TLS)
static int static int
configure_tls_version(char **argv) configure_tls_version(char **argv)
{ {
@ -313,7 +328,6 @@ configure_tls_cipher(char **argv)
static int static int
configure_tls_dhparam(char **argv) configure_tls_dhparam(char **argv)
{ {
#if !defined(KORE_NO_TLS)
BIO *bio; BIO *bio;
if (argv[1] == NULL) if (argv[1] == NULL)
@ -336,79 +350,6 @@ configure_tls_dhparam(char **argv)
printf("PEM_read_bio_DHparams(): %s\n", ssl_errno_s); printf("PEM_read_bio_DHparams(): %s\n", ssl_errno_s);
return (KORE_RESULT_ERROR); 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); return (KORE_RESULT_OK);
} }
@ -438,101 +379,6 @@ configure_client_certificates(char **argv)
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
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 static int
configure_certfile(char **argv) configure_certfile(char **argv)
{ {
@ -573,17 +419,57 @@ configure_certkey(char **argv)
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
static int #endif /* !KORE_NO_TLS */
configure_max_connections(char **argv)
{
int err;
if (argv[1] == NULL) static int
configure_domain(char **argv)
{
if (argv[2] == NULL)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
worker_max_connections = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err); if (current_domain != NULL) {
if (err != KORE_RESULT_OK) { printf("previous domain configuration not closed\n");
printf("bad value for worker_max_connections: %s\n", argv[1]); 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);
}
#if !defined(KORE_NO_HTTP)
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_ERROR);
} }
@ -591,50 +477,27 @@ configure_max_connections(char **argv)
} }
static int static int
configure_rlimit_nofiles(char **argv) configure_accesslog(char **argv)
{ {
int err;
if (argv[1] == NULL) if (argv[1] == NULL)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
worker_rlimit_nofiles = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err); if (current_domain == NULL) {
if (err != KORE_RESULT_OK) { kore_debug("missing domain for accesslog");
printf("bad value for worker_rlimit_nofiles: %s\n", argv[1]);
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
return (KORE_RESULT_OK); if (current_domain->accesslog != -1) {
} kore_debug("domain %s already has an open accesslog",
current_domain->domain);
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_ERROR);
} }
return (KORE_RESULT_OK); current_domain->accesslog = open(argv[1],
} O_CREAT | O_APPEND | O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
static int if (current_domain->accesslog == -1) {
configure_set_affinity(char **argv) kore_debug("open(%s): %s", argv[1], errno_s);
{
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_ERROR);
} }
@ -1017,6 +880,143 @@ configure_websocket_timeout(char **argv)
return (KORE_RESULT_OK); 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 static int
configure_socket_backlog(char **argv) configure_socket_backlog(char **argv)
{ {

View File

@ -55,37 +55,33 @@ kore_connection_new(void *owner)
c->tls_reneg = 0; c->tls_reneg = 0;
c->disconnect = NULL; c->disconnect = NULL;
c->hdlr_extra = NULL; c->hdlr_extra = NULL;
c->inflate_started = 0;
c->deflate_started = 0;
c->client_stream_id = 0;
c->proto = CONN_PROTO_UNKNOWN; c->proto = CONN_PROTO_UNKNOWN;
c->type = KORE_TYPE_CONNECTION; 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.start = 0;
c->idle_timer.length = KORE_IDLE_TIMER_MAX; c->idle_timer.length = KORE_IDLE_TIMER_MAX;
TAILQ_INIT(&(c->send_queue)); #if !defined(KORE_NO_HTTP)
TAILQ_INIT(&(c->spdy_streams));
TAILQ_INIT(&(c->http_requests)); TAILQ_INIT(&(c->http_requests));
#endif
TAILQ_INIT(&(c->send_queue));
return (c); return (c);
} }
int int
kore_connection_accept(struct listener *l, struct connection **out) kore_connection_accept(struct listener *listener, struct connection **out)
{ {
struct connection *c; struct connection *c;
struct sockaddr *sin; struct sockaddr *sin;
socklen_t len; socklen_t len;
kore_debug("kore_connection_accept(%p)", l); kore_debug("kore_connection_accept(%p)", listener);
*out = NULL; *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) { if (c->addrtype == AF_INET) {
len = sizeof(struct sockaddr_in); len = sizeof(struct sockaddr_in);
sin = (struct sockaddr *)&(c->addr.ipv4); 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); 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_pool_put(&connection_pool, c);
kore_debug("accept(): %s", errno_s); kore_debug("accept(): %s", errno_s);
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
@ -106,24 +102,30 @@ kore_connection_accept(struct listener *l, struct connection **out)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
TAILQ_INSERT_TAIL(&connections, c, list);
#if !defined(KORE_NO_TLS) #if !defined(KORE_NO_TLS)
c->state = CONN_STATE_SSL_SHAKE; c->state = CONN_STATE_SSL_SHAKE;
c->write = net_write_ssl; c->write = net_write_ssl;
c->read = net_read_ssl; c->read = net_read_ssl;
#else #else
c->state = CONN_STATE_ESTABLISHED; c->state = CONN_STATE_ESTABLISHED;
c->proto = CONN_PROTO_HTTP;
c->write = net_write; c->write = net_write;
c->read = net_read; c->read = net_read;
if (http_keepalive_time != 0) if (listener->connect != NULL) {
c->idle_timer.length = http_keepalive_time * 1000; listener->connect(c);
} else {
net_recv_queue(c, http_header_max, NETBUF_CALL_CB_ALWAYS, #if !defined(KORE_NO_HTTP)
http_header_recv); 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 #endif
TAILQ_INSERT_TAIL(&connections, c, list);
kore_connection_start_idletimer(c); kore_connection_start_idletimer(c);
*out = c; *out = c;
@ -140,11 +142,6 @@ kore_connection_check_timeout(void)
TAILQ_FOREACH(c, &connections, list) { TAILQ_FOREACH(c, &connections, list) {
if (c->proto == CONN_PROTO_MSG) if (c->proto == CONN_PROTO_MSG)
continue; 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)) if (!(c->flags & CONN_IDLE_TIMER_ACT))
continue; continue;
kore_connection_check_idletimer(now, c); kore_connection_check_idletimer(now, c);
@ -190,8 +187,7 @@ kore_connection_handle(struct connection *c)
{ {
#if !defined(KORE_NO_TLS) #if !defined(KORE_NO_TLS)
int r; int r;
u_int32_t len; struct listener *listener;
const u_char *data;
char cn[X509_CN_LENGTH]; char cn[X509_CN_LENGTH];
#endif #endif
@ -239,6 +235,8 @@ kore_connection_handle(struct connection *c)
"no CN found in client certificate"); "no CN found in client certificate");
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
} else {
c->cert = NULL;
} }
r = SSL_get_verify_result(c->ssl); r = SSL_get_verify_result(c->ssl);
@ -248,40 +246,26 @@ kore_connection_handle(struct connection *c)
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
SSL_get0_next_proto_negotiated(c->ssl, &data, &len); if (c->owner != NULL) {
if (data) { listener = (struct listener *)c->owner;
if (!memcmp(data, "spdy/3", MIN(6, len))) { if (listener->connect != NULL) {
c->proto = CONN_PROTO_SPDY; listener->connect(c);
c->idle_timer.length = spdy_idle_time; goto tls_established;
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;
}
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; c->state = CONN_STATE_ESTABLISHED;
/* FALLTHROUGH */ /* FALLTHROUGH */
#endif /* !KORE_NO_TLS */ #endif /* !KORE_NO_TLS */
@ -312,8 +296,9 @@ void
kore_connection_remove(struct connection *c) kore_connection_remove(struct connection *c)
{ {
struct netbuf *nb, *next; struct netbuf *nb, *next;
struct spdy_stream *s, *snext; #if !defined(KORE_NO_HTTP)
struct http_request *req, *rnext; struct http_request *req, *rnext;
#endif
kore_debug("kore_connection_remove(%p)", c); kore_debug("kore_connection_remove(%p)", c);
@ -332,17 +317,14 @@ kore_connection_remove(struct connection *c)
if (c->hdlr_extra != NULL) if (c->hdlr_extra != NULL)
kore_mem_free(c->hdlr_extra); kore_mem_free(c->hdlr_extra);
if (c->inflate_started) #if !defined(KORE_NO_HTTP)
inflateEnd(&(c->z_inflate));
if (c->deflate_started)
deflateEnd(&(c->z_deflate));
for (req = TAILQ_FIRST(&(c->http_requests)); req != NULL; req = rnext) { for (req = TAILQ_FIRST(&(c->http_requests)); req != NULL; req = rnext) {
rnext = TAILQ_NEXT(req, olist); rnext = TAILQ_NEXT(req, olist);
TAILQ_REMOVE(&(c->http_requests), req, olist); TAILQ_REMOVE(&(c->http_requests), req, olist);
req->flags |= HTTP_REQUEST_DELETE; req->flags |= HTTP_REQUEST_DELETE;
http_request_wakeup(req); http_request_wakeup(req);
} }
#endif
for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = next) { for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = next) {
next = TAILQ_NEXT(nb, list); next = TAILQ_NEXT(nb, list);
@ -360,19 +342,6 @@ kore_connection_remove(struct connection *c)
kore_pool_put(&nb_pool, c->rnb); 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); 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; d = now - c->idle_timer.start;
if (d >= c->idle_timer.length) { if (d >= c->idle_timer.length) {
kore_debug("%p idle for %d ms, expiring", c, d); kore_debug("%p idle for %d ms, expiring", c, d);
if (c->proto == CONN_PROTO_SPDY) kore_connection_disconnect(c);
spdy_session_teardown(c, SPDY_SESSION_ERROR_OK);
else
kore_connection_disconnect(c);
} }
} }

View File

@ -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_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_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->certfile);
kore_mem_free(dom->certkey); kore_mem_free(dom->certkey);

View File

@ -19,7 +19,6 @@
#include <ctype.h> #include <ctype.h>
#include <inttypes.h> #include <inttypes.h>
#include "spdy.h"
#include "kore.h" #include "kore.h"
#include "http.h" #include "http.h"
@ -32,22 +31,17 @@
#endif #endif
static int http_body_recv(struct netbuf *); static int http_body_recv(struct netbuf *);
static void http_error_response(struct connection *, static void http_error_response(struct connection *, int);
struct spdy_stream *, int);
static void http_argument_add(struct http_request *, const char *, static void http_argument_add(struct http_request *, const char *,
void *, u_int32_t, int); void *, u_int32_t, int);
static void http_file_add(struct http_request *, const char *, static void http_file_add(struct http_request *, const char *,
const char *, u_int8_t *, u_int32_t); const char *, u_int8_t *, u_int32_t);
static void http_response_normal(struct http_request *, static void http_response_normal(struct http_request *,
struct connection *, int, void *, u_int32_t); 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 struct kore_buf *header_buf;
static char http_version[32]; static char http_version[32];
static u_int16_t http_version_len; 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;
static TAILQ_HEAD(, http_request) http_requests_sleeping; static TAILQ_HEAD(, http_request) http_requests_sleeping;
static struct kore_pool http_request_pool; static struct kore_pool http_request_pool;
@ -72,12 +66,6 @@ http_init(void)
header_buf = kore_buf_create(1024); 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), l = snprintf(http_version, sizeof(http_version),
"server: kore (%d.%d.%d-%s)\r\n", KORE_VERSION_MAJOR, "server: kore (%d.%d.%d-%s)\r\n", KORE_VERSION_MAJOR,
KORE_VERSION_MINOR, KORE_VERSION_PATCH, KORE_VERSION_STATE); KORE_VERSION_MINOR, KORE_VERSION_PATCH, KORE_VERSION_STATE);
@ -99,7 +87,7 @@ http_init(void)
} }
int 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, const char *method, const char *path, const char *version,
struct http_request **out) struct http_request **out)
{ {
@ -108,21 +96,21 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
int m, flags; int m, flags;
size_t hostlen, pathlen; size_t hostlen, pathlen;
kore_debug("http_request_new(%p, %p, %s, %s, %s, %s)", c, s, kore_debug("http_request_new(%p, %s, %s, %s, %s)", c, host,
host, method, path, version); method, path, version);
if ((hostlen = strlen(host)) >= KORE_DOMAINNAME_LEN - 1) { if ((hostlen = strlen(host)) >= KORE_DOMAINNAME_LEN - 1) {
http_error_response(c, s, 500); http_error_response(c, 500);
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
if ((pathlen = strlen(path)) >= HTTP_URI_LEN - 1) { if ((pathlen = strlen(path)) >= HTTP_URI_LEN - 1) {
http_error_response(c, s, 414); http_error_response(c, 414);
return (KORE_RESULT_ERROR); return (KORE_RESULT_ERROR);
} }
if (strcasecmp(version, "http/1.1")) { if (strcasecmp(version, "http/1.1")) {
http_error_response(c, s, 505); http_error_response(c, 505);
return (KORE_RESULT_ERROR); 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; m = HTTP_METHOD_HEAD;
flags = HTTP_REQUEST_COMPLETE; flags = HTTP_REQUEST_COMPLETE;
} else { } else {
http_error_response(c, s, 400); http_error_response(c, 400);
return (KORE_RESULT_ERROR); 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->start = 0;
req->owner = c; req->owner = c;
req->status = 0; req->status = 0;
req->stream = s;
req->method = m; req->method = m;
req->hdlr = NULL; req->hdlr = NULL;
req->agent = 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->arguments));
TAILQ_INIT(&(req->files)); TAILQ_INIT(&(req->files));
if (s != NULL) { if (!http_request_header(req, "user-agent", &(req->agent)))
if (!http_request_header(req, "user-agent", &(req->agent))) req->agent = kore_strdup("unknown");
req->agent = kore_strdup("unknown");
}
#if defined(KORE_USE_TASKS) #if defined(KORE_USE_TASKS)
LIST_INIT(&(req->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; req->status = status;
switch (req->owner->proto) { 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_HTTP:
case CONN_PROTO_WEBSOCKET: case CONN_PROTO_WEBSOCKET:
http_response_normal(req, req->owner, status, d, l); 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; req->status = status;
switch (req->owner->proto) { switch (req->owner->proto) {
case CONN_PROTO_SPDY:
http_response_spdy(req, req->owner,
req->stream, status, NULL, len);
break;
case CONN_PROTO_HTTP: case CONN_PROTO_HTTP:
http_response_normal(req, req->owner, status, NULL, len); http_response_normal(req, req->owner, status, NULL, len);
break; break;
@ -497,7 +475,7 @@ http_response_stream(struct http_request *req, int status, void *base,
} }
if (req->method != HTTP_METHOD_HEAD) { 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; nb->extra = arg;
} }
} }
@ -508,22 +486,16 @@ http_request_header(struct http_request *req, const char *header, char **out)
int r; int r;
struct http_header *hdr; struct http_header *hdr;
if (req->owner->proto == CONN_PROTO_SPDY) { TAILQ_FOREACH(hdr, &(req->req_headers), list) {
r = spdy_stream_get_header(req->stream->hblock, header, out); if (!strcasecmp(hdr->header, header)) {
} else { r = strlen(hdr->value) + 1;
TAILQ_FOREACH(hdr, &(req->req_headers), list) { *out = kore_malloc(r);
if (!strcasecmp(hdr->header, header)) { kore_strlcpy(*out, hdr->value, r);
r = strlen(hdr->value) + 1; return (KORE_RESULT_OK);
*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 int
@ -561,13 +533,13 @@ http_header_recv(struct netbuf *nb)
h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX); h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
if (h < 2) { if (h < 2) {
http_error_response(c, NULL, 400); http_error_response(c, 400);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
v = kore_split_string(headers[0], " ", request, 4); v = kore_split_string(headers[0], " ", request, 4);
if (v != 3) { if (v != 3) {
http_error_response(c, NULL, 400); http_error_response(c, 400);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
@ -579,13 +551,13 @@ http_header_recv(struct netbuf *nb)
v = kore_split_string(headers[i], ":", host, 3); v = kore_split_string(headers[i], ":", host, 3);
if (v != 2) { if (v != 2) {
http_error_response(c, NULL, 400); http_error_response(c, 400);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
if ((host[1] - host[0]) != 5 || if ((host[1] - host[0]) != 5 ||
strncasecmp(host[0], "host", 4) || host[1] == '\0') { strncasecmp(host[0], "host", 4) || host[1] == '\0') {
http_error_response(c, NULL, 400); http_error_response(c, 400);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
@ -595,11 +567,11 @@ http_header_recv(struct netbuf *nb)
} }
if (host[0] == NULL) { if (host[0] == NULL) {
http_error_response(c, NULL, 400); http_error_response(c, 400);
return (KORE_RESULT_OK); 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)) request[0], request[1], request[2], &req))
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
@ -630,7 +602,7 @@ http_header_recv(struct netbuf *nb)
if (!http_request_header(req, "content-length", &p)) { if (!http_request_header(req, "content-length", &p)) {
kore_debug("expected body but no content-length"); kore_debug("expected body but no content-length");
req->flags |= HTTP_REQUEST_DELETE; req->flags |= HTTP_REQUEST_DELETE;
http_error_response(req->owner, NULL, 411); http_error_response(req->owner, 411);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
@ -639,7 +611,7 @@ http_header_recv(struct netbuf *nb)
kore_debug("content-length invalid: %s", p); kore_debug("content-length invalid: %s", p);
kore_mem_free(p); kore_mem_free(p);
req->flags |= HTTP_REQUEST_DELETE; req->flags |= HTTP_REQUEST_DELETE;
http_error_response(req->owner, NULL, 411); http_error_response(req->owner, 411);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
@ -655,7 +627,7 @@ http_header_recv(struct netbuf *nb)
kore_log(LOG_NOTICE, "body too large (%ld > %ld)", kore_log(LOG_NOTICE, "body too large (%ld > %ld)",
clen, http_body_max); clen, http_body_max);
req->flags |= HTTP_REQUEST_DELETE; req->flags |= HTTP_REQUEST_DELETE;
http_error_response(req->owner, NULL, 411); http_error_response(req->owner, 411);
return (KORE_RESULT_OK); return (KORE_RESULT_OK);
} }
@ -675,7 +647,7 @@ http_header_recv(struct netbuf *nb)
req->flags &= ~HTTP_REQUEST_EXPECT_BODY; req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
} else { } else {
kore_debug("bytes_left would become zero (%ld)", clen); 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 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) { switch (c->proto) {
case CONN_PROTO_SPDY:
http_response_spdy(NULL, c, s, status, NULL, 0);
break;
case CONN_PROTO_HTTP: case CONN_PROTO_HTTP:
if (s != NULL)
kore_log(LOG_NOTICE, "http_error_response: s != NULL");
http_response_normal(NULL, c, status, NULL, 0); http_response_normal(NULL, c, status, NULL, 0);
break; break;
default: default:
@ -1164,61 +1131,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 static void
http_response_normal(struct http_request *req, struct connection *c, http_response_normal(struct http_request *req, struct connection *c,
int status, void *d, u_int32_t len) 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); kore_buf_append(header_buf, "\r\n", 2);
net_send_queue(c, header_buf->data, header_buf->offset, net_send_queue(c, header_buf->data, header_buf->offset);
NULL, NETBUF_LAST_CHAIN);
if (d != NULL && req != NULL && req->method != HTTP_METHOD_HEAD) 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)) if (!(c->flags & CONN_CLOSE_EMPTY))
net_recv_reset(c, http_header_max, http_header_recv); net_recv_reset(c, http_header_max, http_header_recv);

View File

@ -68,11 +68,20 @@ version(void)
{ {
printf("kore %d.%d.%d-%s ", KORE_VERSION_MAJOR, KORE_VERSION_MINOR, printf("kore %d.%d.%d-%s ", KORE_VERSION_MAJOR, KORE_VERSION_MINOR,
KORE_VERSION_PATCH, KORE_VERSION_STATE); 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) #if defined(KORE_USE_PGSQL)
printf("pgsql "); printf("pgsql ");
#endif #endif
#if defined(KORE_USE_TASKS) #if defined(KORE_USE_TASKS)
printf("tasks "); printf("tasks ");
#endif
#if defined(KORE_DEBUG)
printf("debug ");
#endif #endif
printf("\n"); printf("\n");
@ -136,10 +145,12 @@ main(int argc, char *argv[])
LIST_INIT(&listeners); LIST_INIT(&listeners);
kore_log_init(); kore_log_init();
#if !defined(KORE_NO_HTTP)
kore_auth_init(); kore_auth_init();
kore_validator_init();
#endif
kore_domain_init(); kore_domain_init();
kore_module_init(); kore_module_init();
kore_validator_init();
kore_server_sslstart(); kore_server_sslstart();
if (config_file == NULL) if (config_file == NULL)
@ -147,7 +158,10 @@ main(int argc, char *argv[])
kore_parse_config(); kore_parse_config();
kore_platform_init(); kore_platform_init();
#if !defined(KORE_NO_HTTP)
kore_accesslog_init(); kore_accesslog_init();
#endif
sig_recv = 0; sig_recv = 0;
signal(SIGHUP, kore_signal); signal(SIGHUP, kore_signal);
@ -174,17 +188,6 @@ main(int argc, char *argv[])
} }
#if !defined(KORE_NO_TLS) #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 int
kore_tls_sni_cb(SSL *ssl, int *ad, void *arg) kore_tls_sni_cb(SSL *ssl, int *ad, void *arg)
{ {
@ -225,7 +228,7 @@ kore_tls_info_callback(const SSL *ssl, int flags, int ret)
#endif #endif
int 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; struct listener *l;
int on, r; int on, r;
@ -295,6 +298,18 @@ kore_server_bind(const char *ip, const char *port)
return (KORE_RESULT_ERROR); 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++; nlisteners++;
LIST_INSERT_HEAD(&listeners, l, list); LIST_INSERT_HEAD(&listeners, l, list);

View File

@ -49,7 +49,7 @@ kore_malloc(size_t len)
fatal("kore_malloc(): zero size"); fatal("kore_malloc(): zero size");
mlen = sizeof(u_int32_t) + len + sizeof(struct meminfo); 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); fatal("kore_malloc(%d): %d", len, errno);
plen = (u_int32_t *)ptr; plen = (u_int32_t *)ptr;
@ -59,10 +59,6 @@ kore_malloc(size_t len)
mem = KORE_MEMINFO(addr); mem = KORE_MEMINFO(addr);
mem->magic = KORE_MEM_MAGIC; mem->magic = KORE_MEM_MAGIC;
#if defined(KORE_PEDANTIC_MALLOC)
explicit_bzero(addr, len);
#endif
return (addr); return (addr);
} }
@ -114,10 +110,6 @@ kore_mem_free(void *ptr)
if (mem->magic != KORE_MEM_MAGIC) if (mem->magic != KORE_MEM_MAGIC)
fatal("kore_mem_free(): magic boundary not found"); 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); addr = (u_int8_t *)ptr - sizeof(u_int32_t);
free(addr); free(addr);
} }
@ -134,11 +126,3 @@ kore_strdup(const char *str)
return (nstr); return (nstr);
} }
#if defined(KORE_PEDANTIC_MALLOC)
void
explicit_bzero(void *addr, size_t len)
{
bzero(addr, len);
}
#endif

View File

@ -129,7 +129,9 @@ kore_module_reload(int cbs)
} }
} }
#if !defined(KORE_NO_HTTP)
kore_validator_reload(); kore_validator_reload();
#endif
} }
int int
@ -141,6 +143,7 @@ kore_module_loaded(void)
return (1); return (1);
} }
#if !defined(KORE_NO_HTTP)
int int
kore_module_handler_new(const char *path, const char *domain, kore_module_handler_new(const char *path, const char *domain,
const char *func, const char *auth, int type) const char *func, const char *auth, int type)
@ -216,6 +219,8 @@ kore_module_handler_find(const char *domain, const char *path)
return (NULL); return (NULL);
} }
#endif /* !KORE_NO_HTTP */
void * void *
kore_module_getsym(const char *symbol) kore_module_getsym(const char *symbol)
{ {

View File

@ -34,8 +34,11 @@ static int msg_recv_packet(struct netbuf *);
static int msg_recv_data(struct netbuf *); static int msg_recv_data(struct netbuf *);
static void msg_disconnected_parent(struct connection *); static void msg_disconnected_parent(struct connection *);
static void msg_disconnected_worker(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_accesslog(struct kore_msg *, const void *);
static void msg_type_websocket(struct kore_msg *, const void *); static void msg_type_websocket(struct kore_msg *, const void *);
#endif
void void
kore_msg_init(void) kore_msg_init(void)
@ -54,7 +57,9 @@ kore_msg_parent_init(void)
kore_msg_parent_add(kw); kore_msg_parent_add(kw);
} }
#if !defined(KORE_NO_HTTP)
kore_msg_register(KORE_MSG_ACCESSLOG, msg_type_accesslog); kore_msg_register(KORE_MSG_ACCESSLOG, msg_type_accesslog);
#endif
} }
void void
@ -86,7 +91,9 @@ kore_msg_parent_remove(struct kore_worker *kw)
void void
kore_msg_worker_init(void) kore_msg_worker_init(void)
{ {
#if !defined(KORE_NO_HTTP)
kore_msg_register(KORE_MSG_WEBSOCKET, msg_type_websocket); kore_msg_register(KORE_MSG_WEBSOCKET, msg_type_websocket);
#endif
worker->msg[1] = kore_connection_new(NULL); worker->msg[1] = kore_connection_new(NULL);
worker->msg[1]->fd = worker->pipe[1]; 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 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; 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.length = len;
m.src = worker->id; m.src = worker->id;
net_send_queue(worker->msg[1], &m, sizeof(m), NULL, NETBUF_LAST_CHAIN); net_send_queue(worker->msg[1], &m, sizeof(m));
net_send_queue(worker->msg[1], data, len, NULL, NETBUF_LAST_CHAIN); net_send_queue(worker->msg[1], data, len);
net_send_flush(worker->msg[1]); 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. */ /* This allows the worker to receive the correct id. */
msg->dst = *(u_int8_t *)c->hdlr_extra; msg->dst = *(u_int8_t *)c->hdlr_extra;
net_send_queue(c, nb->buf, nb->s_off, net_send_queue(c, nb->buf, nb->s_off);
NULL, NETBUF_LAST_CHAIN);
net_send_flush(c); net_send_flush(c);
} }
} }
@ -199,6 +205,7 @@ msg_disconnected_worker(struct connection *c)
c->hdlr_extra = NULL; c->hdlr_extra = NULL;
} }
#if !defined(KORE_NO_HTTP)
static void static void
msg_type_accesslog(struct kore_msg *msg, const void *data) 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) { TAILQ_FOREACH(c, &connections, list) {
if (c->proto == CONN_PROTO_WEBSOCKET) { if (c->proto == CONN_PROTO_WEBSOCKET) {
net_send_queue(c, data, msg->length, net_send_queue(c, data, msg->length);
NULL, NETBUF_LAST_CHAIN);
net_send_flush(c); net_send_flush(c);
} }
} }
} }
#endif
static struct msg_type * static struct msg_type *
msg_type_lookup(u_int8_t id) msg_type_lookup(u_int8_t id)

View File

@ -37,35 +37,31 @@ net_init(void)
} }
void void
net_send_queue(struct connection *c, const void *data, u_int32_t len, net_send_queue(struct connection *c, const void *data, u_int32_t len)
struct spdy_stream *s, int before)
{ {
const u_int8_t *d; const u_int8_t *d;
struct netbuf *nb; struct netbuf *nb;
u_int32_t avail; u_int32_t avail;
kore_debug("net_send_queue(%p, %p, %d, %p, %d)", kore_debug("net_send_queue(%p, %p, %d)", c, data, len);
c, data, len, s, before);
d = data; d = data;
if (before == NETBUF_LAST_CHAIN) { nb = TAILQ_LAST(&(c->send_queue), netbuf_head);
nb = TAILQ_LAST(&(c->send_queue), netbuf_head); if (nb != NULL && !(nb->flags & NETBUF_IS_STREAM) &&
if (nb != NULL && !(nb->flags & NETBUF_IS_STREAM) && nb->b_len < nb->m_len) {
nb->stream == s && nb->b_len < nb->m_len) { avail = nb->m_len - nb->b_len;
avail = nb->m_len - nb->b_len; if (len < avail) {
if (len < avail) { memcpy(nb->buf + nb->b_len, d, len);
memcpy(nb->buf + nb->b_len, d, len); nb->b_len += len;
nb->b_len += len; return;
return; } else if (len > avail) {
} else if (len > avail) { memcpy(nb->buf + nb->b_len, d, avail);
memcpy(nb->buf + nb->b_len, d, avail); nb->b_len += avail;
nb->b_len += avail;
len -= avail; len -= avail;
d += avail; d += avail;
if (len == 0) if (len == 0)
return; return;
}
} }
} }
@ -74,7 +70,6 @@ net_send_queue(struct connection *c, const void *data, u_int32_t len,
nb->cb = NULL; nb->cb = NULL;
nb->owner = c; nb->owner = c;
nb->s_off = 0; nb->s_off = 0;
nb->stream = s;
nb->b_len = len; nb->b_len = len;
nb->type = NETBUF_SEND; nb->type = NETBUF_SEND;
@ -87,27 +82,22 @@ net_send_queue(struct connection *c, const void *data, u_int32_t len,
if (len > 0) if (len > 0)
memcpy(nb->buf, d, nb->b_len); memcpy(nb->buf, d, nb->b_len);
if (before == NETBUF_BEFORE_CHAIN) { TAILQ_INSERT_TAIL(&(c->send_queue), nb, list);
TAILQ_INSERT_BEFORE(c->snb, nb, list);
} else {
TAILQ_INSERT_TAIL(&(c->send_queue), nb, list);
}
} }
void void
net_send_stream(struct connection *c, void *data, u_int32_t len, 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; 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 = kore_pool_get(&nb_pool);
nb->cb = cb; nb->cb = cb;
nb->owner = c; nb->owner = c;
nb->s_off = 0; nb->s_off = 0;
nb->buf = data; nb->buf = data;
nb->stream = s;
nb->b_len = len; nb->b_len = len;
nb->m_len = nb->b_len; nb->m_len = nb->b_len;
nb->type = NETBUF_SEND; 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->b_len = len;
c->rnb->m_len = len; c->rnb->m_len = len;
c->rnb->extra = NULL; c->rnb->extra = NULL;
c->rnb->stream = NULL;
c->rnb->flags = flags; c->rnb->flags = flags;
c->rnb->type = NETBUF_RECV; c->rnb->type = NETBUF_RECV;
c->rnb->buf = kore_malloc(c->rnb->b_len); 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)); c->snb = TAILQ_FIRST(&(c->send_queue));
if (c->snb->b_len != 0) { 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; 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); len = MIN(NETBUF_SEND_PAYLOAD_MAX, smin);
if (!c->write(c, len, &r)) if (!c->write(c, len, &r))
@ -211,8 +185,6 @@ net_send(struct connection *c)
c->snb->s_off += (size_t)r; c->snb->s_off += (size_t)r;
c->snb->flags &= ~NETBUF_MUST_RESEND; 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 || 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); kore_debug("net_recv_flush(%p)", c);
if (c->rnb == NULL) if (c->rnb == NULL)
fatal("net_recv_flush(): c->rnb == NULL"); return (KORE_RESULT_OK);
while (c->flags & CONN_READ_POSSIBLE) { while (c->flags & CONN_READ_POSSIBLE) {
if (!c->read(c, &r)) if (!c->read(c, &r))
@ -275,12 +247,11 @@ net_recv_flush(struct connection *c)
void void
net_remove_netbuf(struct netbuf_head *list, struct netbuf *nb) 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) if (nb->type == NETBUF_RECV)
fatal("net_remove_netbuf(): cannot remove recv netbuf"); fatal("net_remove_netbuf(): cannot remove recv netbuf");
nb->stream = NULL;
if (nb->flags & NETBUF_MUST_RESEND) { if (nb->flags & NETBUF_MUST_RESEND) {
kore_debug("retaining %p (MUST_RESEND)", nb); kore_debug("retaining %p (MUST_RESEND)", nb);
nb->flags |= NETBUF_FORCE_REMOVE; nb->flags |= NETBUF_FORCE_REMOVE;

View File

@ -64,10 +64,6 @@ kore_pool_get(struct kore_pool *pool)
pool->inuse++; pool->inuse++;
#if defined(KORE_PEDANTIC_MALLOC)
explicit_bzero(ptr, pool->elen);
#endif
return (ptr); return (ptr);
} }
@ -76,10 +72,6 @@ kore_pool_put(struct kore_pool *pool, void *ptr)
{ {
struct kore_pool_entry *entry; struct kore_pool_entry *entry;
#if defined(KORE_PEDANTIC_MALLOC)
explicit_bzero(ptr, pool->elen);
#endif
entry = (struct kore_pool_entry *) entry = (struct kore_pool_entry *)
((u_int8_t *)ptr - sizeof(struct kore_pool_entry)); ((u_int8_t *)ptr - sizeof(struct kore_pool_entry));

1025
src/spdy.c

File diff suppressed because it is too large Load Diff

View File

@ -56,7 +56,9 @@ void
kore_task_create(struct kore_task *t, int (*entry)(struct kore_task *)) kore_task_create(struct kore_task *t, int (*entry)(struct kore_task *))
{ {
t->cb = NULL; t->cb = NULL;
#if !defined(KORE_NO_HTTP)
t->req = NULL; t->req = NULL;
#endif
t->entry = entry; t->entry = entry;
t->type = KORE_TYPE_TASK; t->type = KORE_TYPE_TASK;
t->state = KORE_TASK_STATE_CREATED; t->state = KORE_TASK_STATE_CREATED;
@ -91,6 +93,7 @@ kore_task_run(struct kore_task *t)
pthread_cond_signal(&(tt->cond)); pthread_cond_signal(&(tt->cond));
} }
#if !defined(KORE_NO_HTTP)
void void
kore_task_bind_request(struct kore_task *t, struct http_request *req) 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); http_request_sleep(req);
} }
#endif
void void
kore_task_bind_callback(struct kore_task *t, void (*cb)(struct kore_task *)) kore_task_bind_callback(struct kore_task *t, void (*cb)(struct kore_task *))
{ {
#if !defined(KORE_NO_HTTP)
if (t->req != NULL) if (t->req != NULL)
fatal("cannot bind requests and cbs at the same time"); fatal("cannot bind requests and cbs at the same time");
#endif
t->cb = cb; t->cb = cb;
} }
@ -119,10 +124,12 @@ kore_task_destroy(struct kore_task *t)
{ {
kore_debug("kore_task_destroy: %p", t); kore_debug("kore_task_destroy: %p", t);
#if !defined(KORE_NO_HTTP)
if (t->req != NULL) { if (t->req != NULL) {
t->req = NULL; t->req = NULL;
LIST_REMOVE(t, rlist); LIST_REMOVE(t, rlist);
} }
#endif
pthread_rwlock_wrlock(&(t->lock)); 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); kore_debug("kore_task_handle: %p, %d", t, finished);
#if !defined(KORE_NO_HTTP)
if (t->req != NULL) if (t->req != NULL)
http_request_wakeup(t->req); http_request_wakeup(t->req);
#endif
if (finished) { if (finished) {
kore_platform_disable_read(t->fds[0]); kore_platform_disable_read(t->fds[0]);
kore_task_set_state(t, KORE_TASK_STATE_FINISHED); kore_task_set_state(t, KORE_TASK_STATE_FINISHED);
#if !defined(KORE_NO_HTTP)
if (t->req != NULL) { if (t->req != NULL) {
if (t->req->flags & HTTP_REQUEST_DELETE) if (t->req->flags & HTTP_REQUEST_DELETE)
kore_task_destroy(t); kore_task_destroy(t);
} }
#endif
} }
if (t->cb != NULL) if (t->cb != NULL)

View File

@ -121,7 +121,7 @@ kore_websocket_send(struct connection *c, u_int8_t op, const void *data,
frame = kore_buf_create(len); frame = kore_buf_create(len);
websocket_frame_build(frame, op, data, 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); 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) { TAILQ_FOREACH(c, &connections, list) {
if (c != src && c->proto == CONN_PROTO_WEBSOCKET) { if (c != src && c->proto == CONN_PROTO_WEBSOCKET) {
net_send_queue(c, frame->data, frame->offset, net_send_queue(c, frame->data, frame->offset);
NULL, NETBUF_LAST_CHAIN);
net_send_flush(c); net_send_flush(c);
} }
} }

View File

@ -27,7 +27,10 @@
#include <signal.h> #include <signal.h>
#include "kore.h" #include "kore.h"
#if !defined(KORE_NO_HTTP)
#include "http.h" #include "http.h"
#endif
#if defined(KORE_USE_PGSQL) #if defined(KORE_USE_PGSQL)
#include "pgsql.h" #include "pgsql.h"
@ -271,7 +274,10 @@ kore_worker_entry(struct kore_worker *kw)
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
net_init(); net_init();
#if !defined(KORE_NO_HTTP)
http_init(); http_init();
kore_accesslog_worker_init();
#endif
kore_timer_init(); kore_timer_init();
kore_connection_init(); kore_connection_init();
kore_domain_load_crl(); kore_domain_load_crl();
@ -281,7 +287,6 @@ kore_worker_entry(struct kore_worker *kw)
next_lock = 0; next_lock = 0;
idle_check = 0; idle_check = 0;
kore_platform_event_init(); kore_platform_event_init();
kore_accesslog_worker_init();
kore_msg_worker_init(); kore_msg_worker_init();
#if defined(KORE_USE_PGSQL) #if defined(KORE_USE_PGSQL)
@ -330,7 +335,9 @@ kore_worker_entry(struct kore_worker *kw)
next_lock = now + WORKER_LOCK_TIMEOUT; next_lock = now + WORKER_LOCK_TIMEOUT;
} }
#if !defined(KORE_NO_HTTP)
http_process(); http_process();
#endif
if ((now - idle_check) >= 10000) { if ((now - idle_check) >= 10000) {
idle_check = now; idle_check = now;
@ -339,8 +346,13 @@ kore_worker_entry(struct kore_worker *kw)
kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT); kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
#if !defined(KORE_NO_HTTP)
if (quit && http_request_count == 0) if (quit && http_request_count == 0)
break; break;
#else
if (quit)
break;
#endif
} }
kore_connection_prune(KORE_CONNECTION_PRUNE_ALL); kore_connection_prune(KORE_CONNECTION_PRUNE_ALL);