mirror of
https://github.com/jorisvink/kore
synced 2025-03-09 04:29:02 -04:00
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:
parent
a88e56ae25
commit
769c78a6e8
23
Makefile
23
Makefile
@ -6,30 +6,35 @@ KORE=kore
|
||||
INSTALL_DIR=$(PREFIX)/bin
|
||||
INCLUDE_DIR=$(PREFIX)/include/kore
|
||||
|
||||
S_SRC= src/kore.c src/accesslog.c src/auth.c src/buf.c src/cli.c \
|
||||
src/config.c src/connection.c src/domain.c src/http.c src/mem.c \
|
||||
src/msg.c src/module.c src/net.c src/pool.c src/spdy.c src/timer.c \
|
||||
src/validator.c src/utils.c src/websocket.c src/worker.c \
|
||||
src/zlib_dict.c
|
||||
S_SRC= src/kore.c src/buf.c src/cli.c src/config.c src/connection.c \
|
||||
src/domain.c src/mem.c src/msg.c src/module.c src/net.c \
|
||||
src/pool.c src/timer.c src/utils.c src/worker.c
|
||||
S_OBJS= $(S_SRC:.c=.o)
|
||||
|
||||
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes
|
||||
CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual
|
||||
CFLAGS+=-Wsign-compare -Iincludes -g
|
||||
CFLAGS+=-DPREFIX='"$(PREFIX)"'
|
||||
LDFLAGS+=-rdynamic -lssl -lcrypto -lz
|
||||
LDFLAGS=-rdynamic -lssl -lcrypto
|
||||
|
||||
ifneq ("$(DEBUG)", "")
|
||||
CFLAGS+=-DKORE_DEBUG
|
||||
endif
|
||||
|
||||
ifneq ("$(KORE_PEDANTIC_MALLOC)", "")
|
||||
CFLAGS+=-DKORE_PEDANTIC_MALLOC
|
||||
ifneq ("$(NOHTTP)", "")
|
||||
CFLAGS+=-DKORE_NO_HTTP
|
||||
else
|
||||
S_SRC+= src/auth.c src/accesslog.c src/http.c \
|
||||
src/validator.c src/websocket.c src/zlib_dict.c
|
||||
endif
|
||||
|
||||
ifneq ("$(NOTLS)", "")
|
||||
CFLAGS+=-DKORE_NO_TLS
|
||||
LDFLAGS=-rdynamic -lz -lcrypto
|
||||
ifneq ("$(NOHTTP)", "")
|
||||
LDFLAGS=-rdynamic
|
||||
else
|
||||
LDFLAGS=-rdynamic -lcrypto
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ("$(PGSQL)", "")
|
||||
|
@ -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
|
||||
-----------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
5
examples/nohttp/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*.o
|
||||
.objs
|
||||
nohttp.so
|
||||
assets.h
|
||||
cert
|
16
examples/nohttp/README.md
Normal file
16
examples/nohttp/README.md
Normal 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
|
||||
```
|
22
examples/nohttp/conf/nohttp.conf
Normal file
22
examples/nohttp/conf/nohttp.conf
Normal 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
|
||||
}
|
66
examples/nohttp/src/nohttp.c
Normal file
66
examples/nohttp/src/nohttp.c
Normal 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);
|
||||
}
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
132
includes/spdy.h
132
includes/spdy.h
@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __H_SPDY_H
|
||||
#define __H_SPDY_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* XXX */
|
||||
struct connection;
|
||||
struct http_request;
|
||||
|
||||
struct spdy_ctrl_frame {
|
||||
u_int16_t version;
|
||||
u_int16_t type;
|
||||
u_int8_t flags;
|
||||
u_int32_t length;
|
||||
};
|
||||
|
||||
struct spdy_data_frame {
|
||||
u_int32_t stream_id;
|
||||
u_int8_t flags;
|
||||
u_int32_t length;
|
||||
};
|
||||
|
||||
struct spdy_syn_stream {
|
||||
u_int32_t stream_id;
|
||||
u_int32_t assoc_stream_id;
|
||||
u_int8_t slot;
|
||||
u_int8_t reserved;
|
||||
u_int8_t prio;
|
||||
};
|
||||
|
||||
struct spdy_header_block {
|
||||
u_int8_t *header_block;
|
||||
u_int32_t header_block_len;
|
||||
u_int32_t header_offset;
|
||||
u_int32_t header_pairs;
|
||||
};
|
||||
|
||||
struct spdy_stream {
|
||||
u_int32_t stream_id;
|
||||
u_int8_t flags;
|
||||
u_int8_t prio;
|
||||
u_int64_t post_size;
|
||||
u_int64_t send_size;
|
||||
u_int32_t frame_size;
|
||||
u_int32_t recv_wsize;
|
||||
u_int32_t send_wsize;
|
||||
void (*onclose)(struct connection *, struct spdy_stream *);
|
||||
|
||||
struct http_request *httpreq;
|
||||
struct spdy_header_block *hblock;
|
||||
TAILQ_ENTRY(spdy_stream) list;
|
||||
};
|
||||
|
||||
extern const unsigned char SPDY_dictionary_txt[];
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define KORE_SSL_PROTO_STRING "\x08spdy/3.1\x08http/1.1"
|
||||
#define SPDY_CONTROL_FRAME(x) ((x & (1 << 31)))
|
||||
|
||||
#define SPDY_FRAME_SIZE 8
|
||||
#define SPDY_SYNFRAME_SIZE 10
|
||||
#define SPDY_ZLIB_DICT_SIZE 1423
|
||||
#define SPDY_ZLIB_CHUNK 16348
|
||||
#define SPDY_INIT_WSIZE 65536
|
||||
|
||||
/* control frames */
|
||||
#define SPDY_CTRL_FRAME_SYN_STREAM 1
|
||||
#define SPDY_CTRL_FRAME_SYN_REPLY 2
|
||||
#define SPDY_CTRL_FRAME_RST_STREAM 3
|
||||
#define SPDY_CTRL_FRAME_SETTINGS 4
|
||||
#define SPDY_CTRL_FRAME_PING 6
|
||||
#define SPDY_CTRL_FRAME_GOAWAY 7
|
||||
#define SPDY_CTRL_FRAME_WINDOW 9
|
||||
#define SPDY_DATA_FRAME 99
|
||||
|
||||
/* session error codes */
|
||||
#define SPDY_SESSION_ERROR_OK 0
|
||||
#define SPDY_SESSION_ERROR_PROTOCOL 1
|
||||
#define SPDY_SESSION_ERROR_INTERNAL 2
|
||||
|
||||
/* flags */
|
||||
#define FLAG_FIN 0x01
|
||||
#define FLAG_UNIDIRECTIONAL 0x02
|
||||
|
||||
/* settings */
|
||||
#define SETTINGS_UPLOAD_BANDWIDTH 1
|
||||
#define SETTINGS_DOWNLOAD_BANDWIDTH 2
|
||||
#define SETTINGS_ROUND_TRIP_TIME 3
|
||||
#define SETTINGS_MAX_CONCURRENT_STREAMS 4
|
||||
#define SETTINGS_CURRENT_CWND 5
|
||||
#define SETTINGS_DOWNLOAD_RETRANS_RATE 6
|
||||
#define SETTINGS_INITIAL_WINDOW_SIZE 7
|
||||
#define SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE 8
|
||||
|
||||
#define SPDY_HBLOCK_NORMAL 0
|
||||
#define SPDY_HBLOCK_DELAYED_ALLOC 1
|
||||
|
||||
#define SPDY_FLOW_WINDOW_MAX 2147483647
|
||||
|
||||
/* internal flags (make sure they don't clash with SPDY stream flags) */
|
||||
#define SPDY_KORE_FIN 0x10
|
||||
#define SPDY_DATAFRAME_PRELUDE 0x20
|
||||
#define SPDY_NO_CLOSE 0x40
|
||||
|
||||
#define SPDY_KEEP_NETBUFS 0
|
||||
#define SPDY_REMOVE_NETBUFS 1
|
||||
|
||||
#endif /* !__H_SPDY_H */
|
@ -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 *,
|
||||
|
456
src/config.c
456
src/config.c
@ -37,23 +37,29 @@
|
||||
static int configure_include(char **);
|
||||
static int configure_bind(char **);
|
||||
static int configure_load(char **);
|
||||
static int configure_handler(char **);
|
||||
static int configure_domain(char **);
|
||||
static int configure_chroot(char **);
|
||||
static int configure_runas(char **);
|
||||
static int configure_workers(char **);
|
||||
static int configure_pidfile(char **);
|
||||
static int configure_accesslog(char **);
|
||||
static int configure_certfile(char **);
|
||||
static int configure_certkey(char **);
|
||||
static int configure_rlimit_nofiles(char **);
|
||||
static int configure_max_connections(char **);
|
||||
static int configure_accept_threshold(char **);
|
||||
static int configure_set_affinity(char **);
|
||||
static int configure_socket_backlog(char **);
|
||||
|
||||
#if !defined(KORE_NO_TLS)
|
||||
static int configure_certfile(char **);
|
||||
static int configure_certkey(char **);
|
||||
static int configure_tls_version(char **);
|
||||
static int configure_tls_cipher(char **);
|
||||
static int configure_tls_dhparam(char **);
|
||||
static int configure_spdy_idle_time(char **);
|
||||
static int configure_client_certificates(char **);
|
||||
#endif
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
static int configure_handler(char **);
|
||||
static int configure_accesslog(char **);
|
||||
static int configure_http_header_max(char **);
|
||||
static int configure_http_body_max(char **);
|
||||
static int configure_http_hsts_enable(char **);
|
||||
@ -62,7 +68,6 @@ static int configure_http_request_limit(char **);
|
||||
static int configure_validator(char **);
|
||||
static int configure_params(char **);
|
||||
static int configure_validate(char **);
|
||||
static int configure_client_certificates(char **);
|
||||
static int configure_authentication(char **);
|
||||
static int configure_authentication_uri(char **);
|
||||
static int configure_authentication_type(char **);
|
||||
@ -70,7 +75,7 @@ static int configure_authentication_value(char **);
|
||||
static int configure_authentication_validator(char **);
|
||||
static int configure_websocket_maxframe(char **);
|
||||
static int configure_websocket_timeout(char **);
|
||||
static int configure_socket_backlog(char **);
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_PGSQL)
|
||||
static int configure_pgsql_conn_max(char **);
|
||||
@ -90,12 +95,6 @@ static struct {
|
||||
{ "include", configure_include },
|
||||
{ "bind", configure_bind },
|
||||
{ "load", configure_load },
|
||||
{ "static", configure_handler },
|
||||
{ "dynamic", configure_handler },
|
||||
{ "tls_version", configure_tls_version },
|
||||
{ "tls_cipher", configure_tls_cipher },
|
||||
{ "tls_dhparam", configure_tls_dhparam },
|
||||
{ "spdy_idle_time", configure_spdy_idle_time },
|
||||
{ "domain", configure_domain },
|
||||
{ "chroot", configure_chroot },
|
||||
{ "runas", configure_runas },
|
||||
@ -105,10 +104,19 @@ static struct {
|
||||
{ "worker_accept_threshold", configure_accept_threshold },
|
||||
{ "worker_set_affinity", configure_set_affinity },
|
||||
{ "pidfile", configure_pidfile },
|
||||
{ "accesslog", configure_accesslog },
|
||||
{ "socket_backlog", configure_socket_backlog },
|
||||
#if !defined(KORE_NO_TLS)
|
||||
{ "tls_version", configure_tls_version },
|
||||
{ "tls_cipher", configure_tls_cipher },
|
||||
{ "tls_dhparam", configure_tls_dhparam },
|
||||
{ "certfile", configure_certfile },
|
||||
{ "certkey", configure_certkey },
|
||||
{ "client_certificates", configure_client_certificates },
|
||||
#endif
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
{ "static", configure_handler },
|
||||
{ "dynamic", configure_handler },
|
||||
{ "accesslog", configure_accesslog },
|
||||
{ "http_header_max", configure_http_header_max },
|
||||
{ "http_body_max", configure_http_body_max },
|
||||
{ "http_hsts_enable", configure_http_hsts_enable },
|
||||
@ -124,7 +132,7 @@ static struct {
|
||||
{ "authentication_validator", configure_authentication_validator },
|
||||
{ "websocket_maxframe", configure_websocket_maxframe },
|
||||
{ "websocket_timeout", configure_websocket_timeout },
|
||||
{ "socket_backlog", configure_socket_backlog },
|
||||
#endif
|
||||
#if defined(KORE_USE_PGSQL)
|
||||
{ "pgsql_conn_max", configure_pgsql_conn_max },
|
||||
#endif
|
||||
@ -135,10 +143,14 @@ static struct {
|
||||
};
|
||||
|
||||
char *config_file = NULL;
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
static u_int8_t current_method = 0;
|
||||
static struct kore_auth *current_auth = NULL;
|
||||
static struct kore_domain *current_domain = NULL;
|
||||
static struct kore_module_handle *current_handler = NULL;
|
||||
#endif
|
||||
|
||||
static struct kore_domain *current_domain = NULL;
|
||||
|
||||
void
|
||||
kore_parse_config(void)
|
||||
@ -197,6 +209,7 @@ kore_parse_config_file(char *fpath)
|
||||
*t = ' ';
|
||||
}
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
if (!strcmp(p, "}") && current_handler != NULL) {
|
||||
lineno++;
|
||||
current_handler = NULL;
|
||||
@ -213,6 +226,7 @@ kore_parse_config_file(char *fpath)
|
||||
current_auth = NULL;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(p, "}") && current_domain != NULL)
|
||||
domain_sslstart();
|
||||
@ -262,7 +276,7 @@ configure_bind(char **argv)
|
||||
if (argv[1] == NULL || argv[2] == NULL)
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
return (kore_server_bind(argv[1], argv[2]));
|
||||
return (kore_server_bind(argv[1], argv[2], argv[3]));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -275,6 +289,7 @@ configure_load(char **argv)
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
#if !defined(KORE_NO_TLS)
|
||||
static int
|
||||
configure_tls_version(char **argv)
|
||||
{
|
||||
@ -313,7 +328,6 @@ configure_tls_cipher(char **argv)
|
||||
static int
|
||||
configure_tls_dhparam(char **argv)
|
||||
{
|
||||
#if !defined(KORE_NO_TLS)
|
||||
BIO *bio;
|
||||
|
||||
if (argv[1] == NULL)
|
||||
@ -336,79 +350,6 @@ configure_tls_dhparam(char **argv)
|
||||
printf("PEM_read_bio_DHparams(): %s\n", ssl_errno_s);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
#endif
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
configure_spdy_idle_time(char **argv)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (argv[1] == NULL)
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
spdy_idle_time = kore_strtonum(argv[1], 10, 0, 65535, &err);
|
||||
if (err != KORE_RESULT_OK) {
|
||||
printf("spdy_idle_time has invalid value: %s\n", argv[1]);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
spdy_idle_time = spdy_idle_time * 1000;
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
configure_domain(char **argv)
|
||||
{
|
||||
if (argv[2] == NULL)
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
if (current_domain != NULL) {
|
||||
printf("previous domain configuration not closed\n");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (strcmp(argv[2], "{")) {
|
||||
printf("missing { for domain directive\n");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (!kore_domain_new(argv[1])) {
|
||||
printf("could not create new domain %s\n", argv[1]);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
current_domain = kore_domain_lookup(argv[1]);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
configure_handler(char **argv)
|
||||
{
|
||||
int type;
|
||||
|
||||
if (current_domain == NULL) {
|
||||
printf("missing domain for page handler\n");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (argv[1] == NULL || argv[2] == NULL)
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
if (!strcmp(argv[0], "static"))
|
||||
type = HANDLER_TYPE_STATIC;
|
||||
else if (!strcmp(argv[0], "dynamic"))
|
||||
type = HANDLER_TYPE_DYNAMIC;
|
||||
else
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
if (!kore_module_handler_new(argv[1],
|
||||
current_domain->domain, argv[2], argv[3], type)) {
|
||||
kore_debug("cannot create handler for %s", argv[1]);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
128
src/connection.c
128
src/connection.c
@ -55,37 +55,33 @@ kore_connection_new(void *owner)
|
||||
c->tls_reneg = 0;
|
||||
c->disconnect = NULL;
|
||||
c->hdlr_extra = NULL;
|
||||
c->inflate_started = 0;
|
||||
c->deflate_started = 0;
|
||||
c->client_stream_id = 0;
|
||||
c->proto = CONN_PROTO_UNKNOWN;
|
||||
c->type = KORE_TYPE_CONNECTION;
|
||||
c->wsize_initial = SPDY_INIT_WSIZE;
|
||||
c->spdy_send_wsize = SPDY_INIT_WSIZE;
|
||||
c->spdy_recv_wsize = SPDY_INIT_WSIZE;
|
||||
c->idle_timer.start = 0;
|
||||
c->idle_timer.length = KORE_IDLE_TIMER_MAX;
|
||||
|
||||
TAILQ_INIT(&(c->send_queue));
|
||||
TAILQ_INIT(&(c->spdy_streams));
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
TAILQ_INIT(&(c->http_requests));
|
||||
#endif
|
||||
|
||||
TAILQ_INIT(&(c->send_queue));
|
||||
|
||||
return (c);
|
||||
}
|
||||
|
||||
int
|
||||
kore_connection_accept(struct listener *l, struct connection **out)
|
||||
kore_connection_accept(struct listener *listener, struct connection **out)
|
||||
{
|
||||
struct connection *c;
|
||||
struct sockaddr *sin;
|
||||
socklen_t len;
|
||||
|
||||
kore_debug("kore_connection_accept(%p)", l);
|
||||
kore_debug("kore_connection_accept(%p)", listener);
|
||||
|
||||
*out = NULL;
|
||||
c = kore_connection_new(l);
|
||||
c = kore_connection_new(listener);
|
||||
|
||||
c->addrtype = l->addrtype;
|
||||
c->addrtype = listener->addrtype;
|
||||
if (c->addrtype == AF_INET) {
|
||||
len = sizeof(struct sockaddr_in);
|
||||
sin = (struct sockaddr *)&(c->addr.ipv4);
|
||||
@ -94,7 +90,7 @@ kore_connection_accept(struct listener *l, struct connection **out)
|
||||
sin = (struct sockaddr *)&(c->addr.ipv6);
|
||||
}
|
||||
|
||||
if ((c->fd = accept(l->fd, sin, &len)) == -1) {
|
||||
if ((c->fd = accept(listener->fd, sin, &len)) == -1) {
|
||||
kore_pool_put(&connection_pool, c);
|
||||
kore_debug("accept(): %s", errno_s);
|
||||
return (KORE_RESULT_ERROR);
|
||||
@ -106,24 +102,30 @@ kore_connection_accept(struct listener *l, struct connection **out)
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&connections, c, list);
|
||||
|
||||
#if !defined(KORE_NO_TLS)
|
||||
c->state = CONN_STATE_SSL_SHAKE;
|
||||
c->write = net_write_ssl;
|
||||
c->read = net_read_ssl;
|
||||
#else
|
||||
c->state = CONN_STATE_ESTABLISHED;
|
||||
c->proto = CONN_PROTO_HTTP;
|
||||
c->write = net_write;
|
||||
c->read = net_read;
|
||||
|
||||
if (http_keepalive_time != 0)
|
||||
c->idle_timer.length = http_keepalive_time * 1000;
|
||||
|
||||
net_recv_queue(c, http_header_max, NETBUF_CALL_CB_ALWAYS,
|
||||
http_header_recv);
|
||||
if (listener->connect != NULL) {
|
||||
listener->connect(c);
|
||||
} else {
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
c->proto = CONN_PROTO_HTTP;
|
||||
if (http_keepalive_time != 0)
|
||||
c->idle_timer.length = http_keepalive_time * 1000;
|
||||
net_recv_queue(c, http_header_max,
|
||||
NETBUF_CALL_CB_ALWAYS, http_header_recv);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
TAILQ_INSERT_TAIL(&connections, c, list);
|
||||
kore_connection_start_idletimer(c);
|
||||
|
||||
*out = c;
|
||||
@ -140,11 +142,6 @@ kore_connection_check_timeout(void)
|
||||
TAILQ_FOREACH(c, &connections, list) {
|
||||
if (c->proto == CONN_PROTO_MSG)
|
||||
continue;
|
||||
if (c->proto == CONN_PROTO_SPDY &&
|
||||
c->idle_timer.length == 0 &&
|
||||
!(c->flags & CONN_WRITE_BLOCK) &&
|
||||
!(c->flags & CONN_READ_BLOCK))
|
||||
continue;
|
||||
if (!(c->flags & CONN_IDLE_TIMER_ACT))
|
||||
continue;
|
||||
kore_connection_check_idletimer(now, c);
|
||||
@ -190,8 +187,7 @@ kore_connection_handle(struct connection *c)
|
||||
{
|
||||
#if !defined(KORE_NO_TLS)
|
||||
int r;
|
||||
u_int32_t len;
|
||||
const u_char *data;
|
||||
struct listener *listener;
|
||||
char cn[X509_CN_LENGTH];
|
||||
#endif
|
||||
|
||||
@ -239,6 +235,8 @@ kore_connection_handle(struct connection *c)
|
||||
"no CN found in client certificate");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
} else {
|
||||
c->cert = NULL;
|
||||
}
|
||||
|
||||
r = SSL_get_verify_result(c->ssl);
|
||||
@ -248,40 +246,26 @@ kore_connection_handle(struct connection *c)
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
SSL_get0_next_proto_negotiated(c->ssl, &data, &len);
|
||||
if (data) {
|
||||
if (!memcmp(data, "spdy/3", MIN(6, len))) {
|
||||
c->proto = CONN_PROTO_SPDY;
|
||||
c->idle_timer.length = spdy_idle_time;
|
||||
net_recv_queue(c, SPDY_FRAME_SIZE, 0,
|
||||
spdy_frame_recv);
|
||||
} else if (!memcmp(data, "http/1.1", MIN(8, len))) {
|
||||
c->proto = CONN_PROTO_HTTP;
|
||||
if (http_keepalive_time != 0) {
|
||||
c->idle_timer.length =
|
||||
http_keepalive_time * 1000;
|
||||
}
|
||||
|
||||
net_recv_queue(c, http_header_max,
|
||||
NETBUF_CALL_CB_ALWAYS,
|
||||
http_header_recv);
|
||||
} else {
|
||||
kore_log(LOG_NOTICE,
|
||||
"npn: received unknown protocol");
|
||||
return (KORE_RESULT_ERROR);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
153
src/http.c
153
src/http.c
@ -19,7 +19,6 @@
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "spdy.h"
|
||||
#include "kore.h"
|
||||
#include "http.h"
|
||||
|
||||
@ -32,22 +31,17 @@
|
||||
#endif
|
||||
|
||||
static int http_body_recv(struct netbuf *);
|
||||
static void http_error_response(struct connection *,
|
||||
struct spdy_stream *, int);
|
||||
static void http_error_response(struct connection *, int);
|
||||
static void http_argument_add(struct http_request *, const char *,
|
||||
void *, u_int32_t, int);
|
||||
static void http_file_add(struct http_request *, const char *,
|
||||
const char *, u_int8_t *, u_int32_t);
|
||||
static void http_response_normal(struct http_request *,
|
||||
struct connection *, int, void *, u_int32_t);
|
||||
static void http_response_spdy(struct http_request *,
|
||||
struct connection *, struct spdy_stream *,
|
||||
int, void *, u_int32_t);
|
||||
|
||||
static struct kore_buf *header_buf;
|
||||
static char http_version[32];
|
||||
static u_int16_t http_version_len;
|
||||
static char http_version_spdy[32];
|
||||
static TAILQ_HEAD(, http_request) http_requests;
|
||||
static TAILQ_HEAD(, http_request) http_requests_sleeping;
|
||||
static struct kore_pool http_request_pool;
|
||||
@ -72,12 +66,6 @@ http_init(void)
|
||||
|
||||
header_buf = kore_buf_create(1024);
|
||||
|
||||
l = snprintf(http_version_spdy, sizeof(http_version_spdy),
|
||||
"kore (%d.%d.%d-%s)", KORE_VERSION_MAJOR, KORE_VERSION_MINOR,
|
||||
KORE_VERSION_PATCH, KORE_VERSION_STATE);
|
||||
if (l == -1 || (size_t)l >= sizeof(http_version_spdy))
|
||||
fatal("http_init(): http_version_spdy buffer too small");
|
||||
|
||||
l = snprintf(http_version, sizeof(http_version),
|
||||
"server: kore (%d.%d.%d-%s)\r\n", KORE_VERSION_MAJOR,
|
||||
KORE_VERSION_MINOR, KORE_VERSION_PATCH, KORE_VERSION_STATE);
|
||||
@ -99,7 +87,7 @@ http_init(void)
|
||||
}
|
||||
|
||||
int
|
||||
http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
|
||||
http_request_new(struct connection *c, const char *host,
|
||||
const char *method, const char *path, const char *version,
|
||||
struct http_request **out)
|
||||
{
|
||||
@ -108,21 +96,21 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
|
||||
int m, flags;
|
||||
size_t hostlen, pathlen;
|
||||
|
||||
kore_debug("http_request_new(%p, %p, %s, %s, %s, %s)", c, s,
|
||||
host, method, path, version);
|
||||
kore_debug("http_request_new(%p, %s, %s, %s, %s)", c, host,
|
||||
method, path, version);
|
||||
|
||||
if ((hostlen = strlen(host)) >= KORE_DOMAINNAME_LEN - 1) {
|
||||
http_error_response(c, s, 500);
|
||||
http_error_response(c, 500);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if ((pathlen = strlen(path)) >= HTTP_URI_LEN - 1) {
|
||||
http_error_response(c, s, 414);
|
||||
http_error_response(c, 414);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (strcasecmp(version, "http/1.1")) {
|
||||
http_error_response(c, s, 505);
|
||||
http_error_response(c, 505);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
@ -142,7 +130,7 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
|
||||
m = HTTP_METHOD_HEAD;
|
||||
flags = HTTP_REQUEST_COMPLETE;
|
||||
} else {
|
||||
http_error_response(c, s, 400);
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
@ -152,7 +140,6 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
|
||||
req->start = 0;
|
||||
req->owner = c;
|
||||
req->status = 0;
|
||||
req->stream = s;
|
||||
req->method = m;
|
||||
req->hdlr = NULL;
|
||||
req->agent = NULL;
|
||||
@ -182,10 +169,8 @@ http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
|
||||
TAILQ_INIT(&(req->arguments));
|
||||
TAILQ_INIT(&(req->files));
|
||||
|
||||
if (s != NULL) {
|
||||
if (!http_request_header(req, "user-agent", &(req->agent)))
|
||||
req->agent = kore_strdup("unknown");
|
||||
}
|
||||
if (!http_request_header(req, "user-agent", &(req->agent)))
|
||||
req->agent = kore_strdup("unknown");
|
||||
|
||||
#if defined(KORE_USE_TASKS)
|
||||
LIST_INIT(&(req->tasks));
|
||||
@ -462,9 +447,6 @@ http_response(struct http_request *req, int status, void *d, u_int32_t l)
|
||||
req->status = status;
|
||||
|
||||
switch (req->owner->proto) {
|
||||
case CONN_PROTO_SPDY:
|
||||
http_response_spdy(req, req->owner, req->stream, status, d, l);
|
||||
break;
|
||||
case CONN_PROTO_HTTP:
|
||||
case CONN_PROTO_WEBSOCKET:
|
||||
http_response_normal(req, req->owner, status, d, l);
|
||||
@ -484,10 +466,6 @@ http_response_stream(struct http_request *req, int status, void *base,
|
||||
req->status = status;
|
||||
|
||||
switch (req->owner->proto) {
|
||||
case CONN_PROTO_SPDY:
|
||||
http_response_spdy(req, req->owner,
|
||||
req->stream, status, NULL, len);
|
||||
break;
|
||||
case CONN_PROTO_HTTP:
|
||||
http_response_normal(req, req->owner, status, NULL, len);
|
||||
break;
|
||||
@ -497,7 +475,7 @@ http_response_stream(struct http_request *req, int status, void *base,
|
||||
}
|
||||
|
||||
if (req->method != HTTP_METHOD_HEAD) {
|
||||
net_send_stream(req->owner, base, len, req->stream, cb, &nb);
|
||||
net_send_stream(req->owner, base, len, cb, &nb);
|
||||
nb->extra = arg;
|
||||
}
|
||||
}
|
||||
@ -508,22 +486,16 @@ http_request_header(struct http_request *req, const char *header, char **out)
|
||||
int r;
|
||||
struct http_header *hdr;
|
||||
|
||||
if (req->owner->proto == CONN_PROTO_SPDY) {
|
||||
r = spdy_stream_get_header(req->stream->hblock, header, out);
|
||||
} else {
|
||||
TAILQ_FOREACH(hdr, &(req->req_headers), list) {
|
||||
if (!strcasecmp(hdr->header, header)) {
|
||||
r = strlen(hdr->value) + 1;
|
||||
*out = kore_malloc(r);
|
||||
kore_strlcpy(*out, hdr->value, r);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
TAILQ_FOREACH(hdr, &(req->req_headers), list) {
|
||||
if (!strcasecmp(hdr->header, header)) {
|
||||
r = strlen(hdr->value) + 1;
|
||||
*out = kore_malloc(r);
|
||||
kore_strlcpy(*out, hdr->value, r);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
r = KORE_RESULT_ERROR;
|
||||
}
|
||||
|
||||
return (r);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
int
|
||||
@ -561,13 +533,13 @@ http_header_recv(struct netbuf *nb)
|
||||
|
||||
h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
|
||||
if (h < 2) {
|
||||
http_error_response(c, NULL, 400);
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
v = kore_split_string(headers[0], " ", request, 4);
|
||||
if (v != 3) {
|
||||
http_error_response(c, NULL, 400);
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
@ -579,13 +551,13 @@ http_header_recv(struct netbuf *nb)
|
||||
|
||||
v = kore_split_string(headers[i], ":", host, 3);
|
||||
if (v != 2) {
|
||||
http_error_response(c, NULL, 400);
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
if ((host[1] - host[0]) != 5 ||
|
||||
strncasecmp(host[0], "host", 4) || host[1] == '\0') {
|
||||
http_error_response(c, NULL, 400);
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
@ -595,11 +567,11 @@ http_header_recv(struct netbuf *nb)
|
||||
}
|
||||
|
||||
if (host[0] == NULL) {
|
||||
http_error_response(c, NULL, 400);
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
if (!http_request_new(c, NULL, host[1],
|
||||
if (!http_request_new(c, host[1],
|
||||
request[0], request[1], request[2], &req))
|
||||
return (KORE_RESULT_OK);
|
||||
|
||||
@ -630,7 +602,7 @@ http_header_recv(struct netbuf *nb)
|
||||
if (!http_request_header(req, "content-length", &p)) {
|
||||
kore_debug("expected body but no content-length");
|
||||
req->flags |= HTTP_REQUEST_DELETE;
|
||||
http_error_response(req->owner, NULL, 411);
|
||||
http_error_response(req->owner, 411);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
@ -639,7 +611,7 @@ http_header_recv(struct netbuf *nb)
|
||||
kore_debug("content-length invalid: %s", p);
|
||||
kore_mem_free(p);
|
||||
req->flags |= HTTP_REQUEST_DELETE;
|
||||
http_error_response(req->owner, NULL, 411);
|
||||
http_error_response(req->owner, 411);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
@ -655,7 +627,7 @@ http_header_recv(struct netbuf *nb)
|
||||
kore_log(LOG_NOTICE, "body too large (%ld > %ld)",
|
||||
clen, http_body_max);
|
||||
req->flags |= HTTP_REQUEST_DELETE;
|
||||
http_error_response(req->owner, NULL, 411);
|
||||
http_error_response(req->owner, 411);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
@ -675,7 +647,7 @@ http_header_recv(struct netbuf *nb)
|
||||
req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
|
||||
} else {
|
||||
kore_debug("bytes_left would become zero (%ld)", clen);
|
||||
http_error_response(req->owner, NULL, 500);
|
||||
http_error_response(req->owner, 500);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1145,17 +1117,12 @@ http_body_recv(struct netbuf *nb)
|
||||
}
|
||||
|
||||
static void
|
||||
http_error_response(struct connection *c, struct spdy_stream *s, int status)
|
||||
http_error_response(struct connection *c, int status)
|
||||
{
|
||||
kore_debug("http_error_response(%p, %p, %d)", c, s, status);
|
||||
kore_debug("http_error_response(%p, %d)", c, status);
|
||||
|
||||
switch (c->proto) {
|
||||
case CONN_PROTO_SPDY:
|
||||
http_response_spdy(NULL, c, s, status, NULL, 0);
|
||||
break;
|
||||
case CONN_PROTO_HTTP:
|
||||
if (s != NULL)
|
||||
kore_log(LOG_NOTICE, "http_error_response: s != NULL");
|
||||
http_response_normal(NULL, c, status, NULL, 0);
|
||||
break;
|
||||
default:
|
||||
@ -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);
|
||||
|
41
src/kore.c
41
src/kore.c
@ -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);
|
||||
|
||||
|
18
src/mem.c
18
src/mem.c
@ -49,7 +49,7 @@ kore_malloc(size_t len)
|
||||
fatal("kore_malloc(): zero size");
|
||||
|
||||
mlen = sizeof(u_int32_t) + len + sizeof(struct meminfo);
|
||||
if ((ptr = malloc(mlen)) == NULL)
|
||||
if ((ptr = calloc(1, mlen)) == NULL)
|
||||
fatal("kore_malloc(%d): %d", len, errno);
|
||||
|
||||
plen = (u_int32_t *)ptr;
|
||||
@ -59,10 +59,6 @@ kore_malloc(size_t len)
|
||||
mem = KORE_MEMINFO(addr);
|
||||
mem->magic = KORE_MEM_MAGIC;
|
||||
|
||||
#if defined(KORE_PEDANTIC_MALLOC)
|
||||
explicit_bzero(addr, len);
|
||||
#endif
|
||||
|
||||
return (addr);
|
||||
}
|
||||
|
||||
@ -114,10 +110,6 @@ kore_mem_free(void *ptr)
|
||||
if (mem->magic != KORE_MEM_MAGIC)
|
||||
fatal("kore_mem_free(): magic boundary not found");
|
||||
|
||||
#if defined(KORE_PEDANTIC_MALLOC)
|
||||
explicit_bzero(ptr, KORE_MEMSIZE(ptr));
|
||||
#endif
|
||||
|
||||
addr = (u_int8_t *)ptr - sizeof(u_int32_t);
|
||||
free(addr);
|
||||
}
|
||||
@ -134,11 +126,3 @@ kore_strdup(const char *str)
|
||||
|
||||
return (nstr);
|
||||
}
|
||||
|
||||
#if defined(KORE_PEDANTIC_MALLOC)
|
||||
void
|
||||
explicit_bzero(void *addr, size_t len)
|
||||
{
|
||||
bzero(addr, len);
|
||||
}
|
||||
#endif
|
||||
|
@ -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)
|
||||
{
|
||||
|
21
src/msg.c
21
src/msg.c
@ -34,8 +34,11 @@ static int msg_recv_packet(struct netbuf *);
|
||||
static int msg_recv_data(struct netbuf *);
|
||||
static void msg_disconnected_parent(struct connection *);
|
||||
static void msg_disconnected_worker(struct connection *);
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
static void msg_type_accesslog(struct kore_msg *, const void *);
|
||||
static void msg_type_websocket(struct kore_msg *, const void *);
|
||||
#endif
|
||||
|
||||
void
|
||||
kore_msg_init(void)
|
||||
@ -54,7 +57,9 @@ kore_msg_parent_init(void)
|
||||
kore_msg_parent_add(kw);
|
||||
}
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
kore_msg_register(KORE_MSG_ACCESSLOG, msg_type_accesslog);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -86,7 +91,9 @@ kore_msg_parent_remove(struct kore_worker *kw)
|
||||
void
|
||||
kore_msg_worker_init(void)
|
||||
{
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
kore_msg_register(KORE_MSG_WEBSOCKET, msg_type_websocket);
|
||||
#endif
|
||||
|
||||
worker->msg[1] = kore_connection_new(NULL);
|
||||
worker->msg[1]->fd = worker->pipe[1];
|
||||
@ -120,7 +127,7 @@ kore_msg_register(u_int8_t id, void (*cb)(struct kore_msg *, const void *))
|
||||
}
|
||||
|
||||
void
|
||||
kore_msg_send(u_int16_t dst, u_int8_t id, void *data, u_int32_t len)
|
||||
kore_msg_send(u_int16_t dst, u_int8_t id, const void *data, u_int32_t len)
|
||||
{
|
||||
struct kore_msg m;
|
||||
|
||||
@ -129,8 +136,8 @@ kore_msg_send(u_int16_t dst, u_int8_t id, void *data, u_int32_t len)
|
||||
m.length = len;
|
||||
m.src = worker->id;
|
||||
|
||||
net_send_queue(worker->msg[1], &m, sizeof(m), NULL, NETBUF_LAST_CHAIN);
|
||||
net_send_queue(worker->msg[1], data, len, NULL, NETBUF_LAST_CHAIN);
|
||||
net_send_queue(worker->msg[1], &m, sizeof(m));
|
||||
net_send_queue(worker->msg[1], data, len);
|
||||
net_send_flush(worker->msg[1]);
|
||||
}
|
||||
|
||||
@ -175,8 +182,7 @@ msg_recv_data(struct netbuf *nb)
|
||||
/* This allows the worker to receive the correct id. */
|
||||
msg->dst = *(u_int8_t *)c->hdlr_extra;
|
||||
|
||||
net_send_queue(c, nb->buf, nb->s_off,
|
||||
NULL, NETBUF_LAST_CHAIN);
|
||||
net_send_queue(c, nb->buf, nb->s_off);
|
||||
net_send_flush(c);
|
||||
}
|
||||
}
|
||||
@ -199,6 +205,7 @@ msg_disconnected_worker(struct connection *c)
|
||||
c->hdlr_extra = NULL;
|
||||
}
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
static void
|
||||
msg_type_accesslog(struct kore_msg *msg, const void *data)
|
||||
{
|
||||
@ -213,12 +220,12 @@ msg_type_websocket(struct kore_msg *msg, const void *data)
|
||||
|
||||
TAILQ_FOREACH(c, &connections, list) {
|
||||
if (c->proto == CONN_PROTO_WEBSOCKET) {
|
||||
net_send_queue(c, data, msg->length,
|
||||
NULL, NETBUF_LAST_CHAIN);
|
||||
net_send_queue(c, data, msg->length);
|
||||
net_send_flush(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct msg_type *
|
||||
msg_type_lookup(u_int8_t id)
|
||||
|
73
src/net.c
73
src/net.c
@ -37,35 +37,31 @@ net_init(void)
|
||||
}
|
||||
|
||||
void
|
||||
net_send_queue(struct connection *c, const void *data, u_int32_t len,
|
||||
struct spdy_stream *s, int before)
|
||||
net_send_queue(struct connection *c, const void *data, u_int32_t len)
|
||||
{
|
||||
const u_int8_t *d;
|
||||
struct netbuf *nb;
|
||||
u_int32_t avail;
|
||||
|
||||
kore_debug("net_send_queue(%p, %p, %d, %p, %d)",
|
||||
c, data, len, s, before);
|
||||
kore_debug("net_send_queue(%p, %p, %d)", c, data, len);
|
||||
|
||||
d = data;
|
||||
if (before == NETBUF_LAST_CHAIN) {
|
||||
nb = TAILQ_LAST(&(c->send_queue), netbuf_head);
|
||||
if (nb != NULL && !(nb->flags & NETBUF_IS_STREAM) &&
|
||||
nb->stream == s && nb->b_len < nb->m_len) {
|
||||
avail = nb->m_len - nb->b_len;
|
||||
if (len < avail) {
|
||||
memcpy(nb->buf + nb->b_len, d, len);
|
||||
nb->b_len += len;
|
||||
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;
|
||||
|
@ -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
1025
src/spdy.c
File diff suppressed because it is too large
Load Diff
13
src/tasks.c
13
src/tasks.c
@ -56,7 +56,9 @@ void
|
||||
kore_task_create(struct kore_task *t, int (*entry)(struct kore_task *))
|
||||
{
|
||||
t->cb = NULL;
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
t->req = NULL;
|
||||
#endif
|
||||
t->entry = entry;
|
||||
t->type = KORE_TYPE_TASK;
|
||||
t->state = KORE_TASK_STATE_CREATED;
|
||||
@ -91,6 +93,7 @@ kore_task_run(struct kore_task *t)
|
||||
pthread_cond_signal(&(tt->cond));
|
||||
}
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
void
|
||||
kore_task_bind_request(struct kore_task *t, struct http_request *req)
|
||||
{
|
||||
@ -104,13 +107,15 @@ kore_task_bind_request(struct kore_task *t, struct http_request *req)
|
||||
|
||||
http_request_sleep(req);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
kore_task_bind_callback(struct kore_task *t, void (*cb)(struct kore_task *))
|
||||
{
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
if (t->req != NULL)
|
||||
fatal("cannot bind requests and cbs at the same time");
|
||||
|
||||
#endif
|
||||
t->cb = cb;
|
||||
}
|
||||
|
||||
@ -119,10 +124,12 @@ kore_task_destroy(struct kore_task *t)
|
||||
{
|
||||
kore_debug("kore_task_destroy: %p", t);
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
if (t->req != NULL) {
|
||||
t->req = NULL;
|
||||
LIST_REMOVE(t, rlist);
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_rwlock_wrlock(&(t->lock));
|
||||
|
||||
@ -198,16 +205,20 @@ kore_task_handle(struct kore_task *t, int finished)
|
||||
{
|
||||
kore_debug("kore_task_handle: %p, %d", t, finished);
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
if (t->req != NULL)
|
||||
http_request_wakeup(t->req);
|
||||
#endif
|
||||
|
||||
if (finished) {
|
||||
kore_platform_disable_read(t->fds[0]);
|
||||
kore_task_set_state(t, KORE_TASK_STATE_FINISHED);
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
if (t->req != NULL) {
|
||||
if (t->req->flags & HTTP_REQUEST_DELETE)
|
||||
kore_task_destroy(t);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (t->cb != NULL)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
14
src/worker.c
14
src/worker.c
@ -27,7 +27,10 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "kore.h"
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
#include "http.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_PGSQL)
|
||||
#include "pgsql.h"
|
||||
@ -271,7 +274,10 @@ kore_worker_entry(struct kore_worker *kw)
|
||||
signal(SIGINT, SIG_IGN);
|
||||
|
||||
net_init();
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
http_init();
|
||||
kore_accesslog_worker_init();
|
||||
#endif
|
||||
kore_timer_init();
|
||||
kore_connection_init();
|
||||
kore_domain_load_crl();
|
||||
@ -281,7 +287,6 @@ kore_worker_entry(struct kore_worker *kw)
|
||||
next_lock = 0;
|
||||
idle_check = 0;
|
||||
kore_platform_event_init();
|
||||
kore_accesslog_worker_init();
|
||||
kore_msg_worker_init();
|
||||
|
||||
#if defined(KORE_USE_PGSQL)
|
||||
@ -330,7 +335,9 @@ kore_worker_entry(struct kore_worker *kw)
|
||||
next_lock = now + WORKER_LOCK_TIMEOUT;
|
||||
}
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
http_process();
|
||||
#endif
|
||||
|
||||
if ((now - idle_check) >= 10000) {
|
||||
idle_check = now;
|
||||
@ -339,8 +346,13 @@ kore_worker_entry(struct kore_worker *kw)
|
||||
|
||||
kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
if (quit && http_request_count == 0)
|
||||
break;
|
||||
#else
|
||||
if (quit)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
kore_connection_prune(KORE_CONNECTION_PRUNE_ALL);
|
||||
|
Loading…
x
Reference in New Issue
Block a user