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
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)", "")

View File

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

View File

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

View File

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

View File

@ -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 *);
@ -132,13 +131,6 @@ serve_b64test(struct http_request *req)
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
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);
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);

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
http_keepalive_time 600
spdy_idle_time 600
domain 127.0.0.1 {
certfile cert/server.crt

View File

@ -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)
{

View File

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

View File

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

View File

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

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" {
#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 *,

View File

@ -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);
}
@ -438,101 +379,6 @@ configure_client_certificates(char **argv)
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
configure_certfile(char **argv)
{
@ -573,17 +419,57 @@ configure_certkey(char **argv)
return (KORE_RESULT_OK);
}
static int
configure_max_connections(char **argv)
{
int err;
#endif /* !KORE_NO_TLS */
if (argv[1] == NULL)
static int
configure_domain(char **argv)
{
if (argv[2] == 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]);
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);
}
#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);
}
@ -591,50 +477,27 @@ configure_max_connections(char **argv)
}
static int
configure_rlimit_nofiles(char **argv)
configure_accesslog(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]);
if (current_domain == NULL) {
kore_debug("missing domain for accesslog");
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]);
if (current_domain->accesslog != -1) {
kore_debug("domain %s already has an open accesslog",
current_domain->domain);
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]);
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)
{

View File

@ -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);
if (c->owner != NULL) {
listener = (struct listener *)c->owner;
if (listener->connect != NULL) {
listener->connect(c);
goto tls_established;
}
} 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;
/* 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);
}
}

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_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);

View File

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

View File

@ -68,11 +68,20 @@ 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");
@ -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);
@ -174,17 +188,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)
{
@ -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);

View File

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

View File

@ -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)
{

View File

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

View File

@ -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;
return;
} else if (len > avail) {
memcpy(nb->buf + nb->b_len, d, avail);
nb->b_len += avail;
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;
}
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;

View File

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

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 *))
{
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)

View File

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

View File

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