Codebase list kore / 8a6c0cf
Merge tag 'upstream/2.0.0' Upstream version 2.0.0 Shih-Yuan Lee (FourDollars) 7 years ago
109 changed file(s) with 7570 addition(s) and 4166 deletion(s). Raw diff Collapse all Expand all
00 kore
11 *.o
22 *.swp
3 *.swo
34 *.module
45 *.DSYM
56 cert
7 obj
8 .lvimrc
0 language: c
1 sudo: false
2 compiler:
3 - clang
4 - gcc
5 addons:
6 apt:
7 packages:
8 - libssl-dev
9 script:
10 - make
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
11
22 CC?=gcc
33 PREFIX?=/usr/local
4 OBJDIR?=obj
45 KORE=kore
56 INSTALL_DIR=$(PREFIX)/bin
67 INCLUDE_DIR=$(PREFIX)/include/kore
78
8 S_SRC= src/kore.c src/accesslog.c src/auth.c src/buf.c src/cli.c src/config.c \
9 src/connection.c src/domain.c src/http.c src/mem.c src/module.c \
10 src/net.c src/pool.c src/spdy.c src/timer.c src/validator.c \
11 src/utils.c src/websocket.c src/worker.c src/zlib_dict.c
12 S_OBJS= $(S_SRC:.c=.o)
9 S_SRC= src/kore.c src/buf.c src/cli.c src/config.c src/connection.c \
10 src/domain.c src/mem.c src/msg.c src/module.c src/net.c \
11 src/pool.c src/timer.c src/utils.c src/worker.c src/keymgr.c
1312
14 CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes
13 CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
1514 CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual
16 CFLAGS+=-Wsign-compare -Iincludes -g
15 CFLAGS+=-Wsign-compare -Iincludes -std=c99 -pedantic
1716 CFLAGS+=-DPREFIX='"$(PREFIX)"'
18 LDFLAGS+=-rdynamic -lssl -lcrypto -lz
17 LDFLAGS=-rdynamic -lssl -lcrypto
1918
2019 ifneq ("$(DEBUG)", "")
21 CFLAGS+=-DKORE_DEBUG
20 CFLAGS+=-DKORE_DEBUG -g
21 NOOPT=1
2222 endif
2323
24 ifneq ("$(KORE_PEDANTIC_MALLOC)", "")
25 CFLAGS+=-DKORE_PEDANTIC_MALLOC
24 ifneq ("$(NOOPT)", "")
25 CFLAGS+=-O0
26 else
27 CFLAGS+=-O2
2628 endif
2729
28 ifneq ("$(BENCHMARK)", "")
29 CFLAGS+=-DKORE_BENCHMARK
30 LDFLAGS=-rdynamic -lz -lcrypto
30 ifneq ("$(NOHTTP)", "")
31 CFLAGS+=-DKORE_NO_HTTP
32 else
33 S_SRC+= src/auth.c src/accesslog.c src/http.c \
34 src/validator.c src/websocket.c
35 endif
36
37 ifneq ("$(NOTLS)", "")
38 CFLAGS+=-DKORE_NO_TLS
39 ifneq ("$(NOHTTP)", "")
40 LDFLAGS=-rdynamic
41 else
42 LDFLAGS=-rdynamic -lcrypto
43 endif
3144 endif
3245
3346 ifneq ("$(PGSQL)", "")
4356 CFLAGS+=-DKORE_USE_TASKS
4457 endif
4558
59 ifneq ("$(JSONRPC)", "")
60 S_SRC+=src/jsonrpc.c
61 LDFLAGS+=-lyajl
62 CFLAGS+=-DKORE_USE_JSONRPC
63 endif
64
4665 OSNAME=$(shell uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z)
4766 ifeq ("$(OSNAME)", "darwin")
4867 CFLAGS+=-I/opt/local/include/ -I/usr/local/opt/openssl/include
5473 S_SRC+=src/linux.c
5574 else
5675 S_SRC+=src/bsd.c
76 ifneq ("$(JSONRPC)", "")
77 CFLAGS+=-I/usr/local/include
78 LDFLAGS+=-L/usr/local/lib
79 endif
5780 endif
5881
59 all: $(S_OBJS)
82 S_OBJS= $(S_SRC:src/%.c=$(OBJDIR)/%.o)
83
84 $(KORE): $(OBJDIR) $(S_OBJS)
6085 $(CC) $(S_OBJS) $(LDFLAGS) -o $(KORE)
86
87 objects: $(OBJDIR) $(S_OBJS)
88
89 all: $(KORE)
90
91 $(OBJDIR):
92 @mkdir -p $(OBJDIR)
6193
6294 install:
6395 mkdir -p $(INCLUDE_DIR)
69101 rm -f $(INSTALL_DIR)/$(KORE)
70102 rm -rf $(INCLUDE_DIR)
71103
72 .c.o:
104 $(OBJDIR)/%.o: src/%.c
73105 $(CC) $(CFLAGS) -c $< -o $@
74106
75107 clean:
76108 find . -type f -name \*.o -exec rm {} \;
77 rm -f $(KORE)
109 rm -rf $(KORE) $(OBJDIR)
78110
79 .PHONY: clean
111 .PHONY: all clean
1010 Features
1111 --------
1212 * Supports SNI
13 * Supports SPDY/3.1
1413 * Supports HTTP/1.1
1514 * Websocket support
15 * Privseps by default
1616 * Lightweight background tasks
1717 * Built-in parameter validation
1818 * Only HTTPS connections allowed
19 * Multiple modules can be loaded at once
2019 * Built-in asynchronous PostgreSQL support
20 * Private keys isolated in separate process (RSA and ECDSA)
2121 * Default sane TLS ciphersuites (PFS in all major browsers)
22 * Load your web application as a precompiled dynamic library
2322 * Modules can be reloaded on-the-fly, even while serving content
2423 * Event driven (epoll/kqueue) architecture with per CPU core workers
24 * Build your web application as a precompiled dynamic library or single binary
2525
2626 License
2727 -------
3636
3737 See https://kore.io/doc/#requirements for more information.
3838
39 Latest release
40 --------------
41 * [2015-05-21] version 1.2.3 - https://kore.io/release/kore-1.2.3-release.tgz
42
43 Old releases
44 ------------
45 * [2015-04-09] version 1.2.2 - https://kore.io/release/kore-1.2.2-release.tgz
46 * [2014-12-12] version 1.2.1 - https://kore.io/release/kore-1.2.1-release.tgz
47 * [2014-08-25] version 1.2 - https://kore.io/release/kore-1.2-stable.tgz
48 * [2014-03-01] version 1.1 - https://kore.io/release/kore-1.1-stable.tgz
49
5039 Building Kore
5140 -------------
5241
5342 Requirements
54 * libz
55 * openssl >= 1.0.1i
43 * openssl (latest)
44 (note: this requirement drops away when building with NOTLS=1 NOHTTP=1)
5645
5746 Requirements for background tasks (optional)
5847 * pthreads
6352 Normal compilation and installation:
6453
6554 ```
66 # git clone https://github.com/jorisvink/kore.git
6755 # cd kore
6856 # make
6957 # make install
7563 * TASKS=1 (compiles in task support)
7664 * PGSQL=1 (compiles in pgsql support)
7765 * DEBUG=1 (enables use of -d for debug)
78 * BENCHMARK=1 (compiles Kore without OpenSSL)
79 * KORE_PEDANTIC_MALLOC=1 (zero all allocated memory)
66 * NOTLS=1 (compiles Kore without TLS)
67 * NOHTTP=1 (compiles Kore without HTTP support)
68 * NOOPT=1 (disable compiler optimizations)
69 * JSONRPC=1 (compiles in JSONRPC support)
8070
81 Example libraries
71 Example applications
8272 -----------------
8373
84 You can find example libraries under **_examples/_**.
74 You can find example applications under **_examples/_**.
8575
8676 The examples contain a README file with instructions on how
8777 to build or use them.
88
89 I apologize for unclear examples or documentation, I am working on
90 improving those.
9178
9279 Bugs, contributions and more
9380 ----------------------------
9582 If you run into any bugs, have suggestions or patches please
9683 contact me at joris@coders.se.
9784
85 If you feel like hanging out or just chatting there is an [IRC chatroom (#kore-dev@irc.freenode.org)](https://webchat.freenode.net?channels=kore-dev).
86
9887 More information can be found on https://kore.io/
0 This is the official release for Kore 1.2.3.
0 This is the official release for Kore 2.0.0.
11
22 If you want the current version, use git to clone the following:
3 https://github.com/jorisvink/kore/
3 https://github.com/jorisvink/kore/
44
55 See the README file for more information.
1717 # Worker processes will run as the specified user.
1818 runas joris
1919
20 # Set workers to the amount of CPU's available in your system,
21 # kore will automatically distribute all workers on them.
20 # How many worker processes Kore will spawn. If the directive
21 # worker_set_affinity is set to 1 (the default) Kore will automatically
22 # pin these worker processes to different CPU cores in your system.
23 # NOTE: If you set this to the maximum number of cores you have
24 # in your system (or more) you might consider turning off affinity
25 # if you are running CPU heavy services on the same machine.
2226 workers 4
2327
2428 # The number of active connections each worker can handle.
2933 #worker_rlimit_nofiles 1024
3034
3135 # Limit the number of new connections a worker can accept
32 # in a single event loop.
33 # NOTE: This can have a *MASSIVE* impact as this controls
34 # how new connections are spread across worker processes.
36 # in a single event loop. By default Kore will accept as
37 # many new connections it can up to worker_max_connections.
38 #
39 # NOTE: If you are running benchmark tools that throw all
40 # connections at Kore at the same time (when they are less
41 # then worker_max_connections) or you have an actual reason
42 # to not spend too much time in the accept loop this setting
43 # will make a HUGE positive difference.
3544 #
3645 # This is disabled by default. If you wish to enable this
3746 # specify the number of connections a worker will accept
4958 # http_header_max Maximum size of HTTP headers (in bytes).
5059 #
5160 # http_body_max Maximum size of an HTTP body (in bytes).
61 # If set to 0 disallows requests with a body
62 # all together.
63 #
64 # http_body_disk_offload Number of bytes after which Kore will use
65 # a temporary file to hold the HTTP body
66 # instead of holding it in memory. If set to
67 # 0 no disk offloading will be done. This is
68 # turned off by default.
69 #
70 # http_body_disk_path Path where Kore will store any temporary
71 # HTTP body files.
5272 #
5373 # http_keepalive_time Maximum seconds an HTTP connection can be
5474 # kept alive by the browser.
6181 # http_request_limit Limit the number of requests Kore processes
6282 # in a single event loop.
6383 #http_header_max 4096
64 #http_body_max 10240000
84 #http_body_max 1024000
6585 #http_keepalive_time 0
6686 #http_hsts_enable 31536000
6787 #http_request_limit 1000
88 #http_body_disk_offload 0
89 #http_body_disk_path tmp_files
6890
6991 # Websocket specific settings.
7092 # websocket_maxframe Specifies the maximum frame size we can receive
7395 #websocket_maxframe 16384
7496 #websocket_timeout 120
7597
98 # Configure the number of available threads for background tasks.
99 #task_threads 2
100
76101 # Load modules (you can load multiple at the same time).
77102 # An additional parameter can be specified as the "onload" function
78103 # which Kore will call when the module is loaded/reloaded.
96121 # Specify the TLS ciphers that will be used.
97122 #tls_cipher ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!kRSA:!kDSA
98123
99 # If you wish to use EDH / ECDH specify a file containing
100 # a generated DH key (See OpenSSL dhparam).
124 # Required DH parameters for TLS.
101125 #tls_dhparam dh2048.pem
102
103 # Specify the amount of seconds a SPDY connection is kept open.
104 # You can keep it open indefinitely by setting this to 0.
105 #spdy_idle_time 120
106126
107127 # Authentication configuration
108128 #
183203 static / serve_index
184204 static /intro.jpg serve_intro
185205 static /b64test serve_b64test
186 static /spdy-reset serve_spdyreset
187206 static /upload serve_file_upload
188207 static /lock-test serve_lock_test
189208 static /validator serve_validator
+0
-14
docker/Makefile less more
0 all: build app
1
2 build:
3 docker build -t kore-build -f build/Dockerfile build/
4 docker tag kore-build kore/build
5
6 app:
7 docker build -t kore-app -f app/Dockerfile app/
8 docker tag kore-app kore/app
9
10 clean:
11 docker rmi -f kore-build kore-app
12
13 .PHONY: all build app clean
+0
-14
docker/app/Dockerfile less more
0 FROM kore/build
1 MAINTAINER Thordur I. Bjornsson <thorduri@secnorth.net>
2
3 ENV KORE_VERSION 1.2.3
4
5 WORKDIR /kore
6
7 ADD https://github.com/jorisvink/kore/archive/$KORE_VERSION-release.tar.gz /kore/
8 RUN tar -zxf $KORE_VERSION-release.tar.gz && cd kore-$KORE_VERSION-release/ && \
9 make clean && make && make install && \
10 rm -rf /kore/$KORE_VERSION-release.tar.gz /kore/kore-$KORE_VERSION-release
11
12 EXPOSE 443 8888
13 ENTRYPOINT ["kore", "run"]
+0
-5
docker/build/Dockerfile less more
0 FROM debian:jessie
1 MAINTAINER Thordur I. Bjornsson <thorduri@secnorth.net>
2
3 RUN apt-get update -qq && \
4 apt-get -qqy install build-essential clang git libpq-dev libssl-dev libz-dev
0 # cpp build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 cxxflags=-Wall -Wmissing-declarations -Wshadow
9 cxxflags=-Wpointer-arith -Wcast-qual -Wsign-compare
10
11 dev {
12 # These cflags are added to the shared ones when
13 # you build the "dev" flavor.
14 cflags=-g
15 cxxflags=-g
16 }
17
18 #prod {
19 # You can specify additional CFLAGS here which are only
20 # included if you build with the "prod" flavor.
21 #}
0 # generic build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
33 load ./generic.so example_load
44
55 tls_dhparam dh2048.pem
6
7 http_body_max 1024000000
8 http_body_disk_offload 1024000
69
710 validator v_example function v_example_func
811 validator v_regex regex ^/test/[a-z]*$
2528 static / serve_index
2629 static /intro.jpg serve_intro
2730 static /b64test serve_b64test
28 static /spdy-reset serve_spdyreset
2931 static /upload serve_file_upload
3032 static /validator serve_validator
3133 static /params-test serve_params_test
1616 #include <kore/kore.h>
1717 #include <kore/http.h>
1818
19 #include <openssl/sha.h>
20
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24
1925 #include "assets.h"
2026
2127 int example_load(int);
2430 int serve_index(struct http_request *);
2531 int serve_intro(struct http_request *);
2632 int serve_b64test(struct http_request *);
27 int serve_spdyreset(struct http_request *);
2833 int serve_file_upload(struct http_request *);
2934 int serve_validator(struct http_request *);
3035 int serve_params_test(struct http_request *);
7378 tstamp = 0;
7479 if (http_request_header(req, "if-modified-since", &date)) {
7580 tstamp = kore_date_to_time(date);
76 kore_mem_free(date);
77
7881 kore_debug("header was present with %ld", tstamp);
7982 }
8083
114117 serve_b64test(struct http_request *req)
115118 {
116119 int i;
117 u_int32_t len;
120 size_t len;
118121 struct kore_buf *res;
119122 u_int8_t *data;
120123
121 res = kore_buf_create(1024);
124 res = kore_buf_alloc(1024);
122125 for (i = 0; b64tests[i] != NULL; i++)
123126 test_base64((u_int8_t *)b64tests[i], strlen(b64tests[i]), res);
124127
126129
127130 http_response_header(req, "content-type", "text/plain");
128131 http_response(req, 200, data, len);
129 kore_mem_free(data);
130
131 return (KORE_RESULT_OK);
132 }
133
134 int
135 serve_spdyreset(struct http_request *req)
136 {
137 spdy_session_teardown(req->owner, SPDY_SESSION_ERROR_OK);
132 kore_free(data);
133
138134 return (KORE_RESULT_OK);
139135 }
140136
141137 int
142138 serve_file_upload(struct http_request *req)
143139 {
144 int r;
145140 u_int8_t *d;
146141 struct kore_buf *b;
147 u_int32_t len;
142 struct http_file *f;
143 size_t len;
148144 char *name, buf[BUFSIZ];
149145
150 b = kore_buf_create(asset_len_upload_html);
146 b = kore_buf_alloc(asset_len_upload_html);
151147 kore_buf_append(b, asset_upload_html, asset_len_upload_html);
152148
153149 if (req->method == HTTP_METHOD_POST) {
154 http_populate_multipart_form(req, &r);
155 if (http_argument_get_string("firstname", &name, &len)) {
156 kore_buf_replace_string(b, "$firstname$", name, len);
150 if (req->http_body_fd != -1)
151 kore_log(LOG_NOTICE, "file is on disk");
152
153 http_populate_multipart_form(req);
154 if (http_argument_get_string(req, "firstname", &name)) {
155 kore_buf_replace_string(b, "$firstname$",
156 name, strlen(name));
157157 } else {
158158 kore_buf_replace_string(b, "$firstname$", NULL, 0);
159159 }
160160
161 if (http_file_lookup(req, "file", &name, &d, &len)) {
161 if ((f = http_file_lookup(req, "file")) != NULL) {
162162 (void)snprintf(buf, sizeof(buf),
163 "%s is %d bytes", name, len);
163 "%s is %ld bytes", f->filename, f->length);
164164 kore_buf_replace_string(b,
165165 "$upload$", buf, strlen(buf));
166166 } else {
175175
176176 http_response_header(req, "content-type", "text/html");
177177 http_response(req, 200, d, len);
178 kore_mem_free(d);
178 kore_free(d);
179179
180180 return (KORE_RESULT_OK);
181181 }
184184 test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res)
185185 {
186186 char *in;
187 u_int32_t len;
187 size_t len;
188188 u_int8_t *out;
189189
190190 kore_buf_appendf(res, "test '%s'\n", src);
200200 kore_buf_appendf(res, "decoded: ");
201201 kore_buf_append(res, out, len);
202202 kore_buf_appendf(res, "\n");
203 kore_mem_free(out);
203 kore_free(out);
204204 }
205205
206 kore_mem_free(in);
206 kore_free(in);
207207 }
208208
209209 kore_buf_appendf(res, "\n");
237237 {
238238 struct kore_buf *b;
239239 u_int8_t *d;
240 u_int32_t len;
240 size_t len;
241241 int r, i;
242242 char *test, name[10];
243243
244 http_populate_arguments(req);
245
246 b = kore_buf_create(asset_len_params_html);
244 if (req->method == HTTP_METHOD_GET)
245 http_populate_get(req);
246 else if (req->method == HTTP_METHOD_POST)
247 http_populate_post(req);
248
249 b = kore_buf_alloc(asset_len_params_html);
247250 kore_buf_append(b, asset_params_html, asset_len_params_html);
248251
249252 /*
250253 * The GET parameters will be filtered out on POST.
251254 */
252 if (http_argument_get_string("arg1", &test, &len)) {
253 kore_buf_replace_string(b, "$arg1$", test, len);
255 if (http_argument_get_string(req, "arg1", &test)) {
256 kore_buf_replace_string(b, "$arg1$", test, strlen(test));
254257 } else {
255258 kore_buf_replace_string(b, "$arg1$", NULL, 0);
256259 }
257260
258 if (http_argument_get_string("arg2", &test, &len)) {
259 kore_buf_replace_string(b, "$arg2$", test, len);
261 if (http_argument_get_string(req, "arg2", &test)) {
262 kore_buf_replace_string(b, "$arg2$", test, strlen(test));
260263 } else {
261264 kore_buf_replace_string(b, "$arg2$", NULL, 0);
262265 }
266269 kore_buf_replace_string(b, "$test2$", NULL, 0);
267270 kore_buf_replace_string(b, "$test3$", NULL, 0);
268271
269 if (http_argument_get_uint16("id", &r))
272 if (http_argument_get_uint16(req, "id", &r))
270273 kore_log(LOG_NOTICE, "id: %d", r);
271274 else
272275 kore_log(LOG_NOTICE, "No id set");
274277 http_response_header(req, "content-type", "text/html");
275278 d = kore_buf_release(b, &len);
276279 http_response(req, 200, d, len);
277 kore_mem_free(d);
280 kore_free(d);
278281
279282 return (KORE_RESULT_OK);
280283 }
281284
282285 for (i = 1; i < 4; i++) {
283286 (void)snprintf(name, sizeof(name), "test%d", i);
284 if (http_argument_get_string(name, &test, &len)) {
287 if (http_argument_get_string(req, name, &test)) {
285288 (void)snprintf(name, sizeof(name), "$test%d$", i);
286 kore_buf_replace_string(b, name, test, len);
289 kore_buf_replace_string(b, name, test, strlen(test));
287290 } else {
288291 (void)snprintf(name, sizeof(name), "$test%d$", i);
289292 kore_buf_replace_string(b, name, NULL, 0);
293296 http_response_header(req, "content-type", "text/html");
294297 d = kore_buf_release(b, &len);
295298 http_response(req, 200, d, len);
296 kore_mem_free(d);
299 kore_free(d);
297300
298301 return (KORE_RESULT_OK);
299302 }
0 # headers build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
1111 * We'll lookup if the X-Custom-Header is given in the request.
1212 * If it is we'll set it as a response header as well.
1313 *
14 * The value returned by http_request_header() must be freed.
15 *
16 * NOTE: All custom headers you set must be in lower case due to
17 * the SPDYv3 specification requiring this.
14 * The value returned by http_request_header() should not be freed.
1815 */
19 if (http_request_header(req, "x-custom-header", &custom)) {
16 if (http_request_header(req, "x-custom-header", &custom))
2017 http_response_header(req, "x-custom-header", custom);
21 kore_mem_free(custom);
22 }
2318
2419 /* Return 200 with "ok\n" to the client. */
2520 http_response(req, 200, "ok\n", 3);
0 # integers build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
1010 int32_t s32;
1111 int64_t s64;
1212 u_int64_t u64;
13 u_int32_t u32;
14 size_t len;
1315 struct kore_buf *buf;
14 u_int32_t u32, len;
1516 u_int8_t c, *data;
1617
17 http_populate_arguments(req);
18 buf = kore_buf_create(128);
18 http_populate_get(req);
19 buf = kore_buf_alloc(128);
1920
20 if (http_argument_get_byte("id", &c))
21 if (http_argument_get_byte(req, "id", &c))
2122 kore_buf_appendf(buf, "byte\t%c\n", c);
2223
23 if (http_argument_get_int16("id", &s16))
24 if (http_argument_get_int16(req, "id", &s16))
2425 kore_buf_appendf(buf, "int16\t%d\n", s16);
2526
26 if (http_argument_get_uint16("id", &u16))
27 if (http_argument_get_uint16(req, "id", &u16))
2728 kore_buf_appendf(buf, "uint16\t%d\n", u16);
2829
29 if (http_argument_get_int32("id", &s32))
30 if (http_argument_get_int32(req, "id", &s32))
3031 kore_buf_appendf(buf, "int32\t%d\n", s32);
3132
32 if (http_argument_get_uint32("id", &u32))
33 if (http_argument_get_uint32(req, "id", &u32))
3334 kore_buf_appendf(buf, "uint32\t%d\n", u32);
3435
35 if (http_argument_get_int64("id", &s64))
36 if (http_argument_get_int64(req, "id", &s64))
3637 kore_buf_appendf(buf, "int64\t%ld\n", s64);
3738
38 if (http_argument_get_uint64("id", &u64))
39 if (http_argument_get_uint64(req, "id", &u64))
3940 kore_buf_appendf(buf, "uint64\t%lu\n", u64);
4041
4142 data = kore_buf_release(buf, &len);
4243 http_response(req, 200, data, len);
43 kore_mem_free(data);
44 kore_free(data);
4445
4546 return (KORE_RESULT_OK);
4647 }
22 In this case we link against yajl (Yet Another JSON library) in order to
33 parse a JSON string that was POSTed to the server.
44
5 Take a peek at conf/build.conf for different build flavors and how to
6 link to other libraries.
7
58 Run:
69 ```
7 env LDFLAGS="-lyajl" kore run
10 $ kore run
811 ```
912
1013 Test:
1114 ```
12 curl -i -k -d '{"foo":{"bar": "Hello world"}}' https://127.0.0.1:8888
15 $ curl -i -k -d '{"foo":{"bar": "Hello world"}}' https://127.0.0.1:8888
1316 ```
1417
1518 The result should echo back the foo.bar JSON path value: Hello world.
0 # json_yajl build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 ldflags=-lyajl
13 }
14
15 #prod {
16 # You can specify additional CFLAGS here which are only
17 # included if you build with the "prod" flavor.
18 #}
0 /*
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
016 #include <kore/kore.h>
117 #include <kore/http.h>
218
723 int
824 page(struct http_request *req)
925 {
26 ssize_t ret;
1027 struct kore_buf *buf;
1128 char *body;
1229 yajl_val node, v;
1330 char eb[1024];
31 u_int8_t data[BUFSIZ];
1432 const char *path[] = { "foo", "bar", NULL };
1533
1634 /* We only allow POST/PUT methods. */
2240 }
2341
2442 /*
25 * Grab the entire body we received as text (NUL-terminated).
26 * Note: this can return NULL and the result MUST be freed.
43 * Read the entire received body into a memory buffer.
2744 */
28 if ((body = http_body_text(req)) == NULL) {
29 http_response(req, 400, NULL, 0);
30 return (KORE_RESULT_OK);
45 buf = kore_buf_alloc(128);
46 for (;;) {
47 ret = http_body_read(req, data, sizeof(data));
48 if (ret == -1) {
49 kore_buf_free(buf);
50 kore_log(LOG_NOTICE, "error reading body");
51 http_response(req, 500, NULL, 0);
52 return (KORE_RESULT_OK);
53 }
54
55 if (ret == 0)
56 break;
57
58 kore_buf_append(buf, data, ret);
3159 }
60
61 /* Grab our body data as a NUL-terminated string. */
62 body = kore_buf_stringify(buf, NULL);
3263
3364 /* Parse the body via yajl now. */
3465 node = yajl_tree_parse(body, eb, sizeof(eb));
3970 kore_log(LOG_NOTICE, "parse error: unknown");
4071 }
4172
42 kore_mem_free(body);
73 kore_buf_free(buf);
4374 http_response(req, 400, NULL, 0);
4475 return (KORE_RESULT_OK);
4576 }
4677
47 buf = kore_buf_create(128);
78 /* Reuse old buffer, don't need it anymore for body. */
79 kore_buf_reset(buf);
4880
4981 /* Attempt to grab foo.bar from the JSON tree. */
5082 v = yajl_tree_get(node, path, yajl_t_string);
5688
5789 /* Release the JSON tree now. */
5890 yajl_tree_free(node);
59 kore_mem_free(body);
6091
6192 /* Respond to the client. */
6293 http_response(req, 200, buf->data, buf->offset);
0 *.o
1 .objs
2 jsonrpc.so
3 assets.h
4 cert
5 .*.swp
6 .*.swo
0 This example demonstrates how you can use the JSON-RPC module in your
1 application.
2
3 Note that the module depends upon the third-party library `yajl` (Yet Another
4 JSON library) to parse and produce messages.
5
6 As for the `yajl_json` example, conf/build.conf shows how to link to the
7 library.
8
9 This example needs kore having been compiled with `JSONRPC` (and so `HTTP`)
10 activated.
11
12 Run:
13 ```
14 $ kore run
15 ```
16
17 Test:
18 ```
19 $ curl -i -k \
20 -d '{"id":1,"jsonrpc":"2.0","method":"echo","params":["Hello world"]}' \
21 https://127.0.0.1:8888/v1
22 ```
23 The result should echo back the string at `params`: Hello world.
24
25 Alternatively, if you have bats installed:
26 ```
27 $ bats test/integ/jsonrpc.bats
28 ```
29 Will run a small test suite.
30
31
32 The yajl repo is available @ https://github.com/lloyd/yajl
33
34
35 JSONRPC Request Lifetime
36 ------------------------
37
38 Currently, one HTTP request will (in most cases) provoke one and only one
39 response. Batch mode is not supported yet, neither is websocket.
40
41 As such `jsonrpc\_error` and `jsonrpc\_result` do clean the request after call.
42
43 If however you want to abort the processed request, like by returning
44 `KORE\_RESULT\_ERROR`, after it having been read, you need to clean it by
45 calling `jsonrpc\_destroy\_request`. Other than that you shouldn't think about
46 this function.
47
48
49 Message Handling Log
50 --------------------
51
52 The `jsonrpc\_request` keeps a log of messages with levels similar to those of
53 syslog. Messages are added with jsonrpc_log().
54
55 By default messages of the log are added to the data member of the error
56 responses if at levels EMERG, ERROR, WARNING and NOTICE.
57
58 If you dont want log messages to be outputted zero the log_levels flag of the
59 jsonrpc_request.
60
61
62 Formatting responses
63 --------------------
64
65 By default responses are not prettyfied. To do that set the appropriate flag in
66 the jsonrpc_request structure.
0 # jsonrpc build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 ldflags=-lyajl
13 }
14
15 #prod {
16 # You can specify additional CFLAGS here which are only
17 # included if you build with the "prod" flavor.
18 #}
0 # Placeholder configuration
1
2 bind 127.0.0.1 8888
3 load ./jsonrpc.so
4
5 tls_dhparam dh2048.pem
6
7 domain 127.0.0.1 {
8 certfile cert/server.crt
9 certkey cert/server.key
10
11 static / homepage
12 static /v1 v1
13 }
0 #include <kore/kore.h>
1 #include <kore/http.h>
2
3 int homepage(struct http_request *);
4
5 int
6 homepage(struct http_request *req)
7 {
8 static const char response_body[] = "JSON-RPC API\n";
9
10 http_response_header(req, "content-type", "text/plain");
11 http_response(req, 200, response_body, sizeof(response_body) - 1);
12 return (KORE_RESULT_OK);
13 }
0 #include <time.h>
1 #include <xlocale.h>
2 #include <yajl/yajl_gen.h>
3 #include <yajl/yajl_tree.h>
4 #include <kore/kore.h>
5 #include <kore/http.h>
6 #include <kore/jsonrpc.h>
7
8 int v1(struct http_request *);
9
10 static int
11 write_string(struct jsonrpc_request *req, void *ctx)
12 {
13 const unsigned char *str = (unsigned char *)ctx;
14
15 return yajl_gen_string(req->gen, str, strlen((const char *)str));
16 }
17
18 static int
19 write_string_array_params(struct jsonrpc_request *req, void *ctx)
20 {
21 int status = 0;
22
23 if (!YAJL_GEN_KO(status = yajl_gen_array_open(req->gen))) {
24 for (size_t i = 0; i < req->params->u.array.len; i++) {
25 yajl_val yajl_str = req->params->u.array.values[i];
26 char *str = YAJL_GET_STRING(yajl_str);
27
28 if (YAJL_GEN_KO(status = yajl_gen_string(req->gen,
29 (unsigned char *)str, strlen(str))))
30 break;
31 }
32 if (status == 0)
33 status = yajl_gen_array_close(req->gen);
34 }
35
36 return status;
37 }
38
39 int
40 v1(struct http_request *http_req)
41 {
42 struct jsonrpc_request req;
43 int ret;
44
45 /* We only allow POST/PUT methods. */
46 if (http_req->method != HTTP_METHOD_POST &&
47 http_req->method != HTTP_METHOD_PUT) {
48 http_response_header(http_req, "allow", "POST, PUT");
49 http_response(http_req, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL, 0);
50 return (KORE_RESULT_OK);
51 }
52
53 /* Read JSON-RPC request. */
54 if ((ret = jsonrpc_read_request(http_req, &req)) != 0)
55 return jsonrpc_error(&req, ret, NULL);
56
57 /* Echo command takes and gives back params. */
58 if (strcmp(req.method, "echo") == 0) {
59 if (!YAJL_IS_ARRAY(req.params)) {
60 jsonrpc_log(&req, LOG_ERR,
61 "Echo only accepts positional params");
62 return jsonrpc_error(&req, JSONRPC_INVALID_PARAMS, NULL);
63 }
64 for (size_t i = 0; i < req.params->u.array.len; i++) {
65 yajl_val v = req.params->u.array.values[i];
66 if (!YAJL_IS_STRING(v)) {
67 jsonrpc_log(&req, -3,
68 "Echo only accepts strings");
69 return jsonrpc_error(&req,
70 JSONRPC_INVALID_PARAMS, NULL);
71 }
72 }
73 return jsonrpc_result(&req, write_string_array_params, NULL);
74 }
75
76 /* Date command displays date and time according to parameters. */
77 if (strcmp(req.method, "date") == 0) {
78 time_t time_value;
79 struct tm time_info;
80 char timestamp[33];
81 struct tm *(*gettm)(const time_t *, struct tm *) =
82 localtime_r;
83
84 if (YAJL_IS_OBJECT(req.params)) {
85 const char *path[] = {"local", NULL};
86 yajl_val bf;
87
88 bf = yajl_tree_get(req.params, path, yajl_t_false);
89 if (bf != NULL)
90 gettm = gmtime_r;
91 } else if (req.params != NULL) {
92 jsonrpc_log(&req, LOG_ERR,
93 "Date only accepts named params");
94 return jsonrpc_error(&req, JSONRPC_INVALID_PARAMS, NULL);
95 }
96
97 if ((time_value = time(NULL)) == -1)
98 return jsonrpc_error(&req, -2,
99 "Failed to get date time");
100
101 if (gettm(&time_value, &time_info) == NULL)
102 return jsonrpc_error(&req, -3,
103 "Failed to get date time info");
104
105 memset(timestamp, 0, sizeof(timestamp));
106 if (strftime_l(timestamp, sizeof(timestamp) - 1, "%c",
107 &time_info, LC_GLOBAL_LOCALE) == 0)
108 return jsonrpc_error(&req, -4,
109 "Failed to get printable date time");
110
111 return jsonrpc_result(&req, write_string, timestamp);
112 }
113
114 return jsonrpc_error(&req, JSONRPC_METHOD_NOT_FOUND, NULL);
115 }
0 #!/usr/bin/env bats
1
2 # Simple and non exhaustive test suite using bats:
3 # https://github.com/sstephenson/bats
4
5 PIDFILE=run/jsonrpc.pid
6 CONFFILE=conf/jsonrpc.conf
7
8 # Start and stop have to be tweaked before being used
9 stop_app() {
10 if [ -f "$PIDFILE" ]; then
11 kill -QUIT `cat "$PIDFILE"`
12 sleep 3
13 fi
14 if [ -f "$PIDFILE" ]; then
15 kill -KILL `cat "$PIDFILE"`
16 sleep 2
17 fi
18 }
19
20 start_app() {
21 stop_app
22 kore -nrc "$CONFFILE"
23 }
24
25 query_with_content_type() {
26 curl -q \
27 -H "Content-Type: $1" \
28 -X POST \
29 --raw \
30 -d "$2" \
31 -s -S \
32 --insecure \
33 "https://127.0.0.1:8888/v1"
34 }
35
36 query() {
37 query_with_content_type "application/json" "$1"
38 }
39
40 grepstr() {
41 declare result=$1
42 shift
43 printf "%s" "$result" | grep "$@" >/dev/null
44 }
45
46 printrep() {
47 declare query=$1
48 declare result=$2
49 printf "Sent:\n"
50 printf "%s\n" "$query"
51 printf "Received:\n"
52 printf "%s\n" "$result"
53 }
54
55 @test "requests with no protocol returns nothing" {
56 query='{"method":"foo","id":"foo"}'
57 result=`query "$query"`
58 printrep "$query" "$result"
59 [ "$result" = "" ]
60 }
61 @test "requests with invalid protocol (1) returns nothing" {
62 query='{"jsonrpc":"1.0","method":"foo","id":"foo"}'
63 result=`query "$query"`
64 printrep "$query" "$result"
65 [ "$result" = "" ]
66 }
67 @test "requests with invalid protocol (2) returns nothing" {
68 query='{"jsonrpc":2.0,"method":"foo","id":"foo"}'
69 result=`query "$query"`
70 printrep "$query" "$result"
71 [ "$result" = "" ]
72 }
73
74 @test "requests with no method raise errors" {
75 query='{"jsonrpc":"2.0","id":"foo"}'
76 result=`query "$query"`
77 printrep "$query" "$result"
78 grepstr "$result" '"error"[ \t\n]*:[ \t\n]*{[ \t\n]*"code"'
79 }
80 @test "requests with invalid method raise errors" {
81 query='{"jsonrpc":"2.0","method":1,"id":"foo"}'
82 result=`query "$query"`
83 printrep "$query" "$result"
84 grepstr "$result" '"error"[ \t\n]*:[ \t\n]*{[ \t\n]*"code"'
85 }
86 @test "requests with unknown method raise errors" {
87 query='{"jsonrpc":"2.0","method":"foobar","id":"foo"}'
88 result=`query "$query"`
89 printrep "$query" "$result"
90 grepstr "$result" '"error"[ \t\n]*:[ \t\n]*{[ \t\n]*"code"'
91 }
92
93 @test "error responses give back the string request id" {
94 query='{"jsonrpc":"2.0","id":"foo"}'
95 result=`query "$query"`
96 printrep "$query" "$result"
97 grepstr "$result" '"error"[ \t\n]*:[ \t\n]*{[ \t\n]*"code"'
98 grepstr "$result" '"id"[ \t\n]*:[ \t\n]*"foo"'
99 }
100 @test "error responses give back the integer request id" {
101 query='{"jsonrpc":"2.0","id":1}'
102 result=`query "$query"`
103 printrep "$query" "$result"
104 grepstr "$result" '"error"[ \t\n]*:[ \t\n]*{[ \t\n]*"code"'
105 grepstr "$result" '"id"[ \t\n]*:[ \t\n]*1'
106 }
107 @test "result responses give back the string request id" {
108 query='{"jsonrpc":"2.0","method":"echo","params":["foobar"],"id":"tau"}'
109 result=`query "$query"`
110 printrep "$query" "$result"
111 grepstr "$result" '"result"[ \t\n]*:[ \t\n]*[[ \t\n]*"foobar"[ \t\n]*]'
112 grepstr "$result" '"id"[ \t\n]*:[ \t\n]*"tau"'
113 }
114 @test "result responses give back the integer request id" {
115 query='{"jsonrpc":"2.0","method":"echo","params":["foobar"],"id":6}'
116 result=`query "$query"`
117 printrep "$query" "$result"
118 grepstr "$result" '"result"[ \t\n]*:[ \t\n]*[[ \t\n]*"foobar"[ \t\n]*]'
119 grepstr "$result" '"id"[ \t\n]*:[ \t\n]*6'
120 }
0 # ktunnel build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
4141 {
4242 char *host, *port;
4343
44 /* Don't want to deal with SPDY connections. */
44 /* Make sure its HTTP. */
4545 if (req->owner->proto != CONN_PROTO_HTTP) {
4646 http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
4747 return (KORE_RESULT_OK);
4848 }
4949
5050 /* Parse the query string and grab our arguments. */
51 http_populate_arguments(req);
52 if (!http_argument_get_string("host", &host, NULL) ||
53 !http_argument_get_string("port", &port, NULL)) {
51 http_populate_get(req);
52 if (!http_argument_get_string(req, "host", &host) ||
53 !http_argument_get_string(req, "port", &port)) {
5454 http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
5555 return (KORE_RESULT_OK);
5656 }
114114 return (KORE_RESULT_ERROR);
115115 }
116116
117 if (!kore_connection_nonblock(fd)) {
117 if (!kore_connection_nonblock(fd, 1)) {
118118 close(fd);
119119 return (KORE_RESULT_ERROR);
120120 }
121121
122122 cpipe = kore_connection_new(c);
123 TAILQ_INSERT_TAIL(&connections, cpipe, list);
124
123125 cpipe->fd = fd;
124126 cpipe->addr.ipv4 = sin;
125127 cpipe->read = net_read;
137139 c->disconnect = ktunnel_pipe_disconnect;
138140 cpipe->disconnect = ktunnel_pipe_disconnect;
139141
140 kore_worker_connection_add(cpipe);
141142 kore_connection_start_idletimer(cpipe);
142143 kore_platform_event_all(cpipe->fd, cpipe);
143144
159160 struct connection *src = nb->owner;
160161 struct connection *dst = src->hdlr_extra;
161162
162 printf("received %d bytes on pipe %p (-> %p)\n", nb->s_off, src, dst);
163 printf("received %zu bytes on pipe %p (-> %p)\n", nb->s_off, src, dst);
163164
164 net_send_queue(dst, nb->buf, nb->s_off, NULL, NETBUF_LAST_CHAIN);
165 net_send_queue(dst, nb->buf, nb->s_off);
165166 net_send_flush(dst);
166167 net_recv_reset(src, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data);
167168
179180 printf("ktunnel_pipe_disconnect(%p)->%p\n", c, cpipe);
180181
181182 if (cpipe != NULL) {
182 /* Prevent Kore from calling kore_mem_free() on hdlr_extra. */
183 /* Prevent Kore from calling kore_free() on hdlr_extra. */
183184 c->hdlr_extra = NULL;
184185 kore_connection_disconnect(cpipe);
185186 }
0 *.o
1 .objs
2 messaging.so
3 assets.h
4 cert
0 Kore message framework example
1
2 Run:
3 ```
4 # kore run
5 ```
6
7 Test:
8 ```
9 Perform a simple GET request against the root page.
10 This should trigger the example app to send a message
11 to the other workers which will display it.
12
13 # curl -k https://127.0.0.1:8888
14 ```
0 # messaging build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
0 # Placeholder configuration
1
2 bind 127.0.0.1 8888
3 load ./messaging.so init
4 tls_dhparam dh2048.pem
5 workers 4
6
7 domain 127.0.0.1 {
8 certfile cert/server.crt
9 certkey cert/server.key
10 static / page
11 }
0 /*
1 * Copyright (c) 2015 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #include <kore/kore.h>
17 #include <kore/http.h>
18
19 /*
20 * This example demonstrates how to use the messaging framework
21 * in Kore. This framework allows you to send messages between
22 * your workers with custom callbacks defined per message ID.
23 */
24
25 /* Your code shouldn't use IDs < 100. */
26 #define MY_MESSAGE_ID 100
27
28 int init(int);
29 int page(struct http_request *);
30 void received_message(struct kore_msg *, const void *);
31
32 /* Initialization callback. */
33 int
34 init(int state)
35 {
36 if (state == KORE_MODULE_UNLOAD)
37 return (KORE_RESULT_OK);
38
39 /*
40 * Register our message callback when the module is initialized.
41 * kore_msg_register() fails if the message ID already exists,
42 * but in our case that is OK.
43 */
44 (void)kore_msg_register(MY_MESSAGE_ID, received_message);
45
46 return (KORE_RESULT_OK);
47 }
48
49 /*
50 * Callback for receiving a message MY_MESSAGE_ID.
51 */
52 void
53 received_message(struct kore_msg *msg, const void *data)
54 {
55 kore_log(LOG_INFO, "got message from %u (%d bytes): %.*s", msg->src,
56 msg->length, msg->length, (const char *)data);
57 }
58
59 /*
60 * Page request which will send a message to all other workers
61 * with the ID set to MY_MESSAGE_ID and a payload of "hello".
62 */
63 int
64 page(struct http_request *req)
65 {
66 /* Send to all workers first. */
67 kore_msg_send(KORE_MSG_WORKER_ALL, MY_MESSAGE_ID, "hello", 5);
68
69 /* Now send something to worker number #2 only. */
70 kore_msg_send(2, MY_MESSAGE_ID, "hello number 2", 14);
71
72 http_response(req, 200, NULL, 0);
73 return (KORE_RESULT_OK);
74 }
0 *.o
1 .objs
2 nohttp.so
3 assets.h
4 cert
0 Kore NOHTTP example
1
2 Note that this example only works if Kore was built with NOHTTP=1.
3
4 Run:
5 ```
6 $ kore run
7 ```
8
9 Test:
10 ```
11 Connect to the server using openssl s_client, you will notice
12 that anything sent is submitted back to your client.
13
14 $ openssl s_client -connect 127.0.0.1:8888
15 ```
0 # nohttp build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
0 # Kore can be used as a network layer if it was
1 # built with NOHTTP=1.
2 #
3 # With this you can bind a callback for every new
4 # connection that has been established. For TLS connections
5 # the callback is called after the TLS handshake is completed.
6
7 # We must load the module first as we need the callback from it.
8 load ./nohttp.so
9
10 # Listen on port 8888 and call connection_setup for each new connection.
11 bind 127.0.0.1 8888 connection_setup
12
13 # TLS dh params.
14 tls_dhparam dh2048.pem
15
16 # We must still define a domain to use TLS. This might go away
17 # in the future for NOHTTP=1
18 domain 127.0.0.1 {
19 certfile cert/server.crt
20 certkey cert/server.key
21 }
0 /*
1 * Copyright (c) 2015 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 /*
17 * Example of using Kore as a network application server.
18 *
19 * We will get called for every new connection that has been established.
20 * For TLS connections we will get called after the TLS handshake completed.
21 *
22 * From the setup we can queue up our own read commands and do whatever we
23 * like with the newly connected client.
24 */
25
26 #include <kore/kore.h>
27
28 void connection_setup(struct connection *);
29 int connection_handle(struct connection *);
30 int connection_recv_data(struct netbuf *);
31
32 void
33 connection_setup(struct connection *c)
34 {
35 kore_log(LOG_NOTICE, "%p: new connection", c);
36
37 /*
38 * Setup a read command that will read up to 128 bytes and will
39 * always call the callback connection_recv_data even if not all
40 * 128 bytes were read.
41 */
42 net_recv_queue(c, 128, NETBUF_CALL_CB_ALWAYS, connection_recv_data);
43
44 /* We are responsible for setting the connection state. */
45 c->state = CONN_STATE_ESTABLISHED;
46
47 /* Override the handle function, called when new events occur. */
48 c->handle = connection_handle;
49 }
50
51 /*
52 * This function is called everytime a new event is triggered on the
53 * connection. In this demo we just use it as a stub for the normal
54 * callback kore_connection_handle().
55 *
56 * In this callback you would generally look at the state of the connection
57 * in c->state and perform the required actions like writing / reading using
58 * net_send_flush() or net_recv_flush() if CONN_SEND_POSSIBLE or
59 * CONN_READ_POSSIBLE are set respectively. Returning KORE_RESULT_ERROR from
60 * this callback will disconnect the connection alltogether.
61 */
62 int
63 connection_handle(struct connection *c)
64 {
65 kore_log(LOG_NOTICE, "connection_handle: %p", c);
66 return (kore_connection_handle(c));
67 }
68
69 /*
70 * This function is called everytime we get up to 128 bytes of data.
71 * The connection can be found under nb->owner.
72 * The data received can be found under nb->buf.
73 * The length of the received data can be found under s_off.
74 */
75 int
76 connection_recv_data(struct netbuf *nb)
77 {
78 struct connection *c = (struct connection *)nb->owner;
79
80 kore_log(LOG_NOTICE, "%p: received %u bytes", c, nb->s_off);
81
82 /* We will just dump these back to the client. */
83 net_send_queue(c, nb->buf, nb->s_off);
84 net_send_flush(c);
85
86 /* Now reset the receive command for the next one. */
87 net_recv_reset(c, 128, connection_recv_data);
88
89 return (KORE_RESULT_OK);
90 }
0 # parameters build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
2121 int
2222 page(struct http_request *req)
2323 {
24 int p;
2524 u_int16_t id;
26 u_int32_t len;
2725 char *sid;
2826 struct kore_buf *buf;
2927
3937 * See conf/parameters.conf on how that is done, this is an
4038 * important step as without the params block you will never
4139 * get any parameters returned from Kore.
42 *
43 * http_populate_arguments() returns the number of arguments
44 * that were successfully processed and are available.
4540 */
46 p = http_populate_arguments(req);
47
48 /* If we had no arguments available what so ever, return 400. */
49 if (p == 0) {
50 http_response(req, 400, NULL, 0);
51 return (KORE_RESULT_OK);
52 }
41 http_populate_get(req);
5342
5443 /*
5544 * Lets grab the "id" parameter if available. Kore can obtain
5746 *
5847 * In this scenario, lets grab it both as an actual string and
5948 * as an u_int16_t (unsigned short).
60 *
61 * If you grab it as a string, you can immediately ask for
62 * the correct length as well, excluding the NUL terminator.
6349 *
6450 * When trying to obtain a parameter as something else then
6551 * a string, Kore will automatically check if the value fits
6955 * and Kore will return an error when trying to read it as such.
7056 */
7157
72 buf = kore_buf_create(128);
58 buf = kore_buf_alloc(128);
7359
7460 /* Grab it as a string, we shouldn't free the result in sid. */
75 if (http_argument_get_string("id", &sid, &len))
76 kore_buf_appendf(buf, "id as a string: '%s' (%d)\n", sid, len);
61 if (http_argument_get_string(req, "id", &sid))
62 kore_buf_appendf(buf, "id as a string: '%s'\n", sid);
7763
7864 /* Grab it as an actual u_int16_t. */
79 if (http_argument_get_uint16("id", &id))
65 if (http_argument_get_uint16(req, "id", &id))
8066 kore_buf_appendf(buf, "id as an u_int16_t: %d\n", id);
8167
8268 /* Now return the result to the client with a 200 status code. */
0 # pgsql build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
1515
1616 /*
1717 * This example demonstrates on how to use state machines and
18 * asynchronous pgsql queries.
18 * asynchronous pgsql queries. For a synchronous query example
19 * see the pgsql-sync/ example under the examples/ directory.
1920 *
2021 * While this example might seem overly complex for a simple pgsql
2122 * query, there is a reason behind its complexity:
3536 #include <kore/http.h>
3637 #include <kore/pgsql.h>
3738
38 #define REQ_STATE_QUERY 0
39 #define REQ_STATE_DB_WAIT 1
40 #define REQ_STATE_DB_READ 2
41 #define REQ_STATE_ERROR 3
42 #define REQ_STATE_DONE 4
39 #define REQ_STATE_INIT 0
40 #define REQ_STATE_QUERY 1
41 #define REQ_STATE_DB_WAIT 2
42 #define REQ_STATE_DB_READ 3
43 #define REQ_STATE_ERROR 4
44 #define REQ_STATE_DONE 5
4345
4446 int init(int);
4547 int page(struct http_request *);
4648
49 static int request_perform_init(struct http_request *);
4750 static int request_perform_query(struct http_request *);
4851 static int request_db_wait(struct http_request *);
4952 static int request_db_read(struct http_request *);
5154 static int request_done(struct http_request *);
5255
5356 struct http_state mystates[] = {
57 { "REQ_STATE_INIT", request_perform_init },
5458 { "REQ_STATE_QUERY", request_perform_query },
5559 { "REQ_STATE_DB_WAIT", request_db_wait },
5660 { "REQ_STATE_DB_READ", request_db_read },
6165 #define mystates_size (sizeof(mystates) / sizeof(mystates[0]))
6266
6367 struct rstate {
68 int cnt;
6469 struct kore_pgsql sql;
6570 };
6671
6873 int
6974 init(int state)
7075 {
71 /* Set our connection string. */
72 pgsql_conn_string = "host=/var/run/postgresql/ dbname=test";
76 /* Register our database. */
77 kore_pgsql_register("db", "host=/tmp dbname=test");
7378
7479 return (KORE_RESULT_OK);
7580 }
8388 return (http_state_run(mystates, mystates_size, req));
8489 }
8590
86 /* The initial state, we setup our context and fire off the pgsql query. */
91 /* Initialize our PGSQL data structure and prepare for an async query. */
92 int
93 request_perform_init(struct http_request *req)
94 {
95 struct rstate *state;
96
97 /* Setup our state context (if not yet set). */
98 if (req->hdlr_extra == NULL) {
99 state = kore_malloc(sizeof(*state));
100 req->hdlr_extra = state;
101 } else {
102 state = req->hdlr_extra;
103 }
104
105 /* Initialize our kore_pgsql data structure. */
106 if (!kore_pgsql_query_init(&state->sql, req, "db", KORE_PGSQL_ASYNC)) {
107 /* If the state was still INIT, we'll try again later. */
108 if (state->sql.state == KORE_PGSQL_STATE_INIT) {
109 req->fsm_state = REQ_STATE_INIT;
110 return (HTTP_STATE_RETRY);
111 }
112
113 kore_pgsql_logerror(&state->sql);
114 req->fsm_state = REQ_STATE_ERROR;
115 } else {
116 req->fsm_state = REQ_STATE_QUERY;
117 }
118
119 return (HTTP_STATE_CONTINUE);
120 }
121
122 /* After setting everything up we will execute our async query. */
87123 int
88124 request_perform_query(struct http_request *req)
89125 {
90 struct rstate *state;
91
92 /* Setup our state context. */
93 state = kore_malloc(sizeof(*state));
94
95 /* Attach the state to our request. */
96 req->hdlr_extra = state;
126 struct rstate *state = req->hdlr_extra;
97127
98128 /* We want to move to read result after this. */
99129 req->fsm_state = REQ_STATE_DB_WAIT;
100130
101131 /* Fire off the query. */
102 if (!kore_pgsql_query(&state->sql, req, "SELECT * FROM coders")) {
103 /* If the state was still INIT, we'll try again later. */
104 if (state->sql.state == KORE_PGSQL_STATE_INIT) {
105 req->fsm_state = REQ_STATE_QUERY;
106 return (HTTP_STATE_RETRY);
107 }
108
132 if (!kore_pgsql_query(&state->sql, "SELECT * FROM coders")) {
109133 /*
110134 * Let the state machine continue immediately since we
111135 * have an error anyway.
194218 return (HTTP_STATE_COMPLETE);
195219 }
196220
197 /* Request was completed succesfully. */
221 /* Request was completed successfully. */
198222 int
199223 request_done(struct http_request *req)
200224 {
0 *.o
1 .objs
2 pgsql-sync.so
3 assets.h
4 cert
0 # pgsql-sync build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
0 # Placeholder configuration
1
2 bind 127.0.0.1 8888
3 load ./pgsql-sync.so init
4 tls_dhparam dh2048.pem
5
6 domain 127.0.0.1 {
7 certfile cert/server.crt
8 certkey cert/server.key
9 static / page
10 }
0 /*
1 * Copyright (c) 2015 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 /*
17 * This example demonstrates how to use synchronous PGSQL queries
18 * with Kore. For an asynchronous example see pgsql/ under examples/.
19 *
20 * This example does the same as the asynchronous one, select all entries
21 * from a table called "coders".
22 */
23
24 #include <kore/kore.h>
25 #include <kore/http.h>
26 #include <kore/pgsql.h>
27
28 int init(int);
29 int page(struct http_request *);
30
31 /* Called when our module is loaded (see config) */
32 int
33 init(int state)
34 {
35 /* Register our database. */
36 kore_pgsql_register("db", "host=/tmp dbname=test");
37
38 return (KORE_RESULT_OK);
39 }
40
41 /* Page handler entry point (see config) */
42 int
43 page(struct http_request *req)
44 {
45 struct kore_pgsql sql;
46 char *name;
47 int rows, i;
48
49 req->status = HTTP_STATUS_INTERNAL_ERROR;
50
51 /*
52 * Initialise our kore_pgsql data structure with the database name
53 * we want to connect to (note that we registered this earlier with
54 * kore_pgsql_register()). We also say we will perform a synchronous
55 * query (KORE_PGSQL_SYNC) and we do not need to pass our http_request
56 * so we pass NULL instead.
57 */
58 if (!kore_pgsql_query_init(&sql, NULL, "db", KORE_PGSQL_SYNC)) {
59 kore_pgsql_logerror(&sql);
60 goto out;
61 }
62
63 /*
64 * Now we can fire off the query, once it returns we either have
65 * a result on which we can operate or an error occured.
66 */
67 if (!kore_pgsql_query(&sql, "SELECT * FROM coders")) {
68 kore_pgsql_logerror(&sql);
69 goto out;
70 }
71
72 /*
73 * Iterate over the result and dump it to somewhere.
74 */
75 rows = kore_pgsql_ntuples(&sql);
76 for (i = 0; i < rows; i++) {
77 name = kore_pgsql_getvalue(&sql, i, 0);
78 kore_log(LOG_NOTICE, "name: '%s'", name);
79 }
80
81 /* All good. */
82 req->status = HTTP_STATUS_OK;
83
84 out:
85 http_response(req, req->status, NULL, 0);
86
87 /* Don't forget to cleanup the kore_pgsql data structure. */
88 kore_pgsql_cleanup(&sql);
89
90 return (KORE_RESULT_OK);
91 }
0 *.o
1 .objs
2 websocket.so
3 assets.h
4 cert
0 Kore example of tasks and websockets.
1
2 This example connects Kore via task to a named unix pipe and
3 spews out any output to all connected websocket clients.
4
5 Before you run this make the pipe:
6 $ mkfifo /tmp/pipe
7
8 Run:
9 ```
10 $ kore run
11 ```
12
13 Test:
14 ```
15 Open a browser that does websockets, surf to https://127.0.0.1:8888
16 or whatever configured IP you have in the config.
17
18 Hit the connect button to open a websocket session.
19
20 Now connect a writer endpoint to the named pipe (/tmp/pipe):
21 $ echo "hello" > /tmp/pipe
22
23 You should see the result in your browser.
24 ```
0 <!DOCTYPE>
1 <html>
2 <head>
3 <script>
4 var socket = null;
5 var sent = 0;
6 var recv = 0;
7 var length = 65536;
8
9 function open(evt) {
10 }
11
12 function message(msg) {
13 }
14
15 function onmessage(evt) {
16 var obj = document.getElementById("log");
17 obj.innerHTML = "<p>" + evt.data + "</p>" + obj.innerHTML;
18 }
19
20 function connect() {
21 socket = new WebSocket("wss://127.0.0.1:8888/connect");
22
23 socket.onopen = function(evt) { open(evt) };
24 socket.onclose = function(evt) { alert("closed"); };
25 socket.onmessage = function(evt) { onmessage(evt) };
26 socket.onerror = function(evt) { alert("onerror"); };
27 }
28 </script>
29 </head>
30
31 <body>
32
33 <form action="/" onsubmit="connect(); return false;">
34 <input type="submit" value="connect">
35 </form>
36
37 <div id="log">
38 </div>
39
40 </body>
41 </html>
0 # pipe_task build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
0 # Kore pipe_task example
1
2 bind 127.0.0.1 8888
3 load ./pipe_task.so init
4
5 tls_dhparam dh2048.pem
6
7 websocket_maxframe 65536
8 websocket_timeout 10000
9
10 domain 127.0.0.1 {
11 certfile cert/server.crt
12 certkey cert/server.key
13
14 static / page
15 static /connect page_ws_connect
16 }
0 /*
1 * Copyright (c) 2015 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 /*
17 * This example demos Kore its task and websocket capabilities.
18 *
19 * It will spawn a task which connects to a named pipe and writes
20 * responses to all connected websocket clients.
21 */
22
23 #include <sys/param.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26
27 #include <kore/kore.h>
28 #include <kore/http.h>
29 #include <kore/tasks.h>
30
31 #include <fcntl.h>
32 #include <unistd.h>
33
34 #include "assets.h"
35
36 int init(int);
37 int page(struct http_request *);
38 int page_ws_connect(struct http_request *);
39
40 void websocket_connect(struct connection *);
41 void websocket_disconnect(struct connection *);
42 void websocket_message(struct connection *,
43 u_int8_t, void *, size_t);
44
45 int pipe_reader(struct kore_task *);
46 void pipe_data_available(struct kore_task *);
47
48 /* Websocket callbacks. */
49 struct kore_wscbs wscbs = {
50 websocket_connect,
51 websocket_message,
52 websocket_disconnect
53 };
54
55 /* Our pipe reader. */
56 struct kore_task pipe_task;
57
58 /* Module init function (see config). */
59 int
60 init(int state)
61 {
62 /* Do not allow reload. */
63 if (state == KORE_MODULE_UNLOAD)
64 return (KORE_RESULT_ERROR);
65
66 /* Only do this on a dedicated worker. */
67 if (worker->id != 0)
68 return (KORE_RESULT_OK);
69
70 /* Create our task. */
71 kore_task_create(&pipe_task, pipe_reader);
72
73 /* Bind a callback whenever data is available from task. */
74 kore_task_bind_callback(&pipe_task, pipe_data_available);
75
76 /* Start the task. */
77 kore_task_run(&pipe_task);
78
79 return (KORE_RESULT_OK);
80 }
81
82 /* Called whenever we get a new websocket connection. */
83 void
84 websocket_connect(struct connection *c)
85 {
86 kore_log(LOG_NOTICE, "%p: connected", c);
87 }
88
89 /* Called whenever we receive a websocket message from a client. */
90 void
91 websocket_message(struct connection *c, u_int8_t op, void *data, size_t len)
92 {
93 /* Not doing anything with this. */
94 }
95
96 /* Called whenever a websocket goes away. */
97 void
98 websocket_disconnect(struct connection *c)
99 {
100 kore_log(LOG_NOTICE, "%p: disconnecting", c);
101 }
102
103 /* The / page. */
104 int
105 page(struct http_request *req)
106 {
107 http_response_header(req, "content-type", "text/html");
108 http_response(req, 200, asset_frontend_html, asset_len_frontend_html);
109
110 return (KORE_RESULT_OK);
111 }
112
113 /* The /connect page. */
114 int
115 page_ws_connect(struct http_request *req)
116 {
117 kore_websocket_handshake(req, &wscbs);
118 return (KORE_RESULT_OK);
119 }
120
121 /*
122 * The pipe reader task. This task simply waits for a writer end
123 * on a named pipe and reads from it. The bytes read are written
124 * on the task channel because the task does not own any connection
125 * data structures and shouldn't reference them directly.
126 */
127 int
128 pipe_reader(struct kore_task *t)
129 {
130 int fd;
131 ssize_t ret;
132 u_int8_t buf[BUFSIZ];
133
134 fd = -1;
135
136 /* Just run forever. */
137 for (;;) {
138 /* Attempt to open the pipe if needed. */
139 if (fd == -1) {
140 kore_log(LOG_NOTICE, "waiting for writer");
141
142 if ((fd = open("/tmp/pipe", O_RDONLY)) == -1) {
143 kore_log(LOG_NOTICE, "failed to open pipe");
144 sleep(10);
145 continue;
146 }
147
148 kore_log(LOG_NOTICE, "writer connected");
149 }
150
151 /* Got a writer on the other end so start reading. */
152 ret = read(fd, buf, sizeof(buf));
153 if (ret == -1) {
154 kore_log(LOG_ERR, "read error on pipe");
155 (void)close(fd);
156 fd = -1;
157 continue;
158 }
159
160 if (ret == 0) {
161 kore_log(LOG_NOTICE, "writer disconnected");
162 (void)close(fd);
163 fd = -1;
164 continue;
165 }
166
167 kore_log(LOG_NOTICE, "got %ld bytes from pipe", ret);
168
169 /*
170 * Write data on the task channel so our main event loop
171 * will call the registered callback.
172 */
173 kore_task_channel_write(t, buf, ret);
174 }
175
176 return (KORE_RESULT_OK);
177 }
178
179 /* Called on the main event loop whenever a task event fires. */
180 void
181 pipe_data_available(struct kore_task *t)
182 {
183 size_t len;
184 u_int8_t buf[BUFSIZ];
185
186 /* Deal with the task finishing, we could restart it from here. */
187 if (kore_task_finished(t)) {
188 kore_log(LOG_WARNING, "task finished");
189 return;
190 }
191
192 /* Read data from the task channel. */
193 len = kore_task_channel_read(t, buf, sizeof(buf));
194 if (len > sizeof(buf))
195 kore_log(LOG_WARNING, "truncated data from task");
196
197 /* Broadcast it to all connected websocket clients. */
198 kore_log(LOG_NOTICE, "got %d bytes from task", len);
199 kore_websocket_broadcast(NULL, WEBSOCKET_OP_TEXT,
200 buf, len, WEBSOCKET_BROADCAST_GLOBAL);
201 }
0 # sse build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
44 tls_dhparam dh2048.pem
55
66 http_keepalive_time 600
7 spdy_idle_time 600
87
98 domain 127.0.0.1 {
109 certfile cert/server.crt
1515
1616 /*
1717 * Simple example of how SSE (Server Side Events) could be used in Kore.
18 * We deal with SSE both over normal HTTP/1.1 and over SPDY connections.
1918 *
2019 * Upon new arrivals, a join event is broadcast to all clients.
2120 * If a client goes away a leave event is broadcasted.
2827
2928 #include "assets.h"
3029
30 void sse_ping(void *, u_int64_t);
3131 int page(struct http_request *);
3232 int subscribe(struct http_request *);
3333 void sse_disconnect(struct connection *);
34 void sse_ping(void *, u_int64_t, u_int64_t);
3534 void sse_send(struct connection *, void *, size_t);
3635 void sse_broadcast(struct connection *, void *, size_t);
37 void sse_spdy_stream_closed(struct connection *, struct spdy_stream *);
3836 int check_header(struct http_request *, const char *, const char *);
3937
4038 /*
4240 * to their hdlr_extra pointer member.
4341 */
4442 struct sse_state {
45 struct spdy_stream *stream;
4643 struct kore_timer *timer;
4744 };
4845
9390 /* Set a disconnection method so we know when this client goes away. */
9491 req->owner->disconnect = sse_disconnect;
9592
96 /* For non SPDY clients we do not expect any more data to arrive. */
97 if (req->owner->proto != CONN_PROTO_SPDY)
98 req->owner->flags |= CONN_READ_BLOCK;
93 /* We do not expect any more data to arrive. */
94 req->owner->flags |= CONN_READ_BLOCK;
9995
10096 /* Allocate a state to be carried by our connection. */
10197 state = kore_malloc(sizeof(*state));
102 state->stream = req->stream;
10398 req->owner->hdlr_extra = state;
104
105 /* SSE over SPDY will need this extra love. */
106 if (req->owner->proto == CONN_PROTO_SPDY) {
107 /* Unset the http request attached to our SPDY stream. */
108 req->stream->httpreq = NULL;
109
110 /*
111 * Do not let the stream close unless a RST occurs or
112 * until we close it ourselves.
113 */
114 req->stream->flags |= SPDY_NO_CLOSE;
115
116 /* Set a callback in case this stream gets a RST. */
117 req->stream->onclose = sse_spdy_stream_closed;
118 }
11999
120100 /* Now start a timer to send a ping back every 10 second. */
121101 state->timer = kore_timer_add(sse_ping, 10000, req->owner, 0);
134114 struct connection *c;
135115
136116 /* Broadcast the message to all other clients. */
137 TAILQ_FOREACH(c, &worker_clients, list) {
117 TAILQ_FOREACH(c, &connections, list) {
138118 if (c == src)
139119 continue;
140120 sse_send(c, data, len);
150130 if (state == NULL)
151131 return;
152132
153 /* SPDY connections need this extra bit of magic. */
154 if (c->proto == CONN_PROTO_SPDY) {
155 if (state->stream == NULL) {
156 kore_log(LOG_ERR, "no SPDY stream for sse_send()");
157 kore_connection_disconnect(c);
158 return;
159 }
160
161 /*
162 * Tell Kore to send a dataframe prelude + increase the
163 * length of our stream to be sent.
164 */
165 if (state->stream->send_size == 0)
166 state->stream->flags |= SPDY_DATAFRAME_PRELUDE;
167 state->stream->send_size += len;
168 }
169
170133 /* Queue outgoing data now. */
171 net_send_queue(c, data, len, state->stream, NETBUF_LAST_CHAIN);
134 net_send_queue(c, data, len);
172135 net_send_flush(c);
173136 }
174137
175138 void
176 sse_ping(void *arg, u_int64_t now, u_int64_t delta)
139 sse_ping(void *arg, u_int64_t now)
177140 {
178141 struct connection *c = arg;
179142 char *ping = "event:ping\ndata:\n\n";
193156 /* Tell others we are leaving. */
194157 sse_broadcast(c, leaving, strlen(leaving));
195158
196 /* Make sure we cleanup our hooked stream if any. */
197 if (c->proto == CONN_PROTO_SPDY && state->stream != NULL) {
198 state->stream->onclose = NULL;
199 spdy_stream_close(c, state->stream, SPDY_REMOVE_NETBUFS);
200 }
201
202159 /* Kill our timer and free/remove the state. */
203160 kore_timer_remove(state->timer);
204 kore_mem_free(state);
161 kore_free(state);
205162
206163 /* Prevent us to be called again. */
207164 c->hdlr_extra = NULL;
208165 c->disconnect = NULL;
209 }
210
211 void
212 sse_spdy_stream_closed(struct connection *c, struct spdy_stream *s)
213 {
214 struct sse_state *state = c->hdlr_extra;
215
216 /* Paranoia. */
217 if (state->stream != s) {
218 state->stream = NULL;
219 kore_connection_disconnect(c);
220 return;
221 }
222
223 /* Set our stream to NULL and call sse_disconnect. */
224 state->stream = NULL;
225 sse_disconnect(c);
226166 }
227167
228168 int
236176 }
237177
238178 if (strcmp(hdr, value)) {
239 kore_mem_free(hdr);
240179 http_response(req, 400, NULL, 0);
241180 return (KORE_RESULT_ERROR);
242181 }
243182
244 kore_mem_free(hdr);
245183 return (KORE_RESULT_OK);
246184 }
55
66 Build:
77 ```
8 # env LDFLAGS="-I/path/to/libcurl -lcurl" kore build
8 $ kore build
99 ```
1010
1111 Run:
1212 ```
13 # kore run
13 $ kore run
1414 ```
1515
1616 Test:
1717 ```
18 # curl -i -k https://127.0.0.1:8888/?user=astring
18 $ curl -i -k https://127.0.0.1:8888/?user=astring
1919 The returned data must match what you supplied in user ([a-z] string)
2020 ```
0 # tasks build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 ldflags=-lcurl
13 }
14
15 #prod {
16 # You can specify additional CFLAGS here which are only
17 # included if you build with the "prod" flavor.
18 #}
33 load ./tasks.so
44
55 tls_dhparam dh2048.pem
6
7 task_threads 4
8 worker_max_connections 1000
9 http_keepalive_time 0
610
711 validator v_user regex ^[a-z]*$
812
5757 */
5858 if (req->hdlr_extra == NULL) {
5959 /* Grab the user argument */
60 http_populate_arguments(req);
61 if (!http_argument_get_string("user", &user, &len)) {
60 http_populate_get(req);
61 if (!http_argument_get_string(req, "user", &user)) {
6262 http_response(req, 500, "ERROR\n", 6);
6363 return (KORE_RESULT_OK);
6464 }
8686 * GET request to its channel.
8787 */
8888 kore_task_run(&state->task);
89 kore_task_channel_write(&state->task, user, len);
89 kore_task_channel_write(&state->task, user, strlen(user));
9090
9191 /*
9292 * Tell Kore to retry us later.
141141 int
142142 post_back(struct http_request *req)
143143 {
144 u_int32_t len;
145144 char *user;
146145
147146 if (req->method != HTTP_METHOD_POST) {
149148 return (KORE_RESULT_OK);
150149 }
151150
152 http_populate_arguments(req);
153 if (!http_argument_get_string("user", &user, &len)) {
151 http_populate_post(req);
152 if (!http_argument_get_string(req, "user", &user)) {
154153 http_response(req, 500, NULL, 0);
155154 return (KORE_RESULT_OK);
156155 }
157156
158157 /* Simply echo the supplied user argument back. */
159 http_response(req, 200, user, len);
158 http_response(req, 200, user, strlen(user));
160159
161160 return (KORE_RESULT_OK);
162161 }
193192 if ((curl = curl_easy_init()) == NULL)
194193 return (KORE_RESULT_ERROR);
195194
196 b = kore_buf_create(128);
195 b = kore_buf_alloc(128);
197196
198197 /* Do CURL magic. */
199198 curl_easy_setopt(curl, CURLOPT_POST, 1);
218217 */
219218 data = kore_buf_release(b, &len);
220219 kore_task_channel_write(t, data, len);
221 kore_mem_free(data);
220 kore_free(data);
222221
223222 return (KORE_RESULT_OK);
224223 }
0 *.o
1 .objs
2 tls-proxy.so
3 assets.h
4 cert
0 Kore as a TLS-proxy.
1
2 Edit src/proxy.c and add your backends to the backends[] data structure.
3
4 If you want to reduce attack surface you can build Kore with NOHTTP=1 to
5 completely remove the HTTP component and only run the net code.
6
7 Run:
8 ```
9 $ kore run
10 ```
11
12 Test:
13 ```
14 Connect to the server and notice that it proxies data between you
15 and your destination.
16
17 $ openssl s_client -connect 127.0.0.1:8888
18 ```
0 # tls-proxy build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
0 # Kore as a TLS proxy configuration.
1
2 load ./tls-proxy.so
3 tls_dhparam dh2048.pem
4
5 #
6 # Bind the proxy to a given IP and port. For every
7 # connection we receive we will call client_setup
8 # so it can kick things in action.
9 #
10 bind 127.0.0.1 8888 client_setup
11
12 # Setup domain for TLS usage.
13 domain localhost {
14 certfile cert/server.crt
15 certkey cert/server.key
16 }
0 /*
1 * Copyright (c) 2015 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #include <sys/param.h>
17 #include <sys/socket.h>
18
19 #include <kore/kore.h>
20
21 /*
22 * In this example Kore acts as a TLS proxy shuffling data between
23 * an encrypted connection and a plain text backend.
24 *
25 * It will look at the TLS SNI extension to figure out what backend
26 * to use for the connection when it comes in.
27 *
28 * Add your backends to the data structure below.
29 */
30
31 /* Default timeouts, 5 seconds for connecting, 15 seconds otherwise. */
32 #define PROXY_TIMEOUT (15 * 1000)
33 #define PROXY_CONNECT_TIMEOUT (5 * 1000)
34
35 /* All domains and their backends. */
36 struct {
37 const char *name;
38 const char *ip;
39 const u_int16_t port;
40 } backends[] = {
41 { "localhost", "127.0.0.1", 8080 },
42 { NULL, NULL, 0 }
43 };
44
45 int client_handle(struct connection *);
46 void client_setup(struct connection *);
47
48 void disconnect(struct connection *);
49 int pipe_data(struct netbuf *);
50
51 int backend_handle_connect(struct connection *);
52 int backend_handle_default(struct connection *);
53
54 /*
55 * Called for every new connection on a certain ip/port. Which one is
56 * configured in the TLS proxy its configuration file.
57 */
58 void
59 client_setup(struct connection *c)
60 {
61 int i, fd;
62 struct connection *backend;
63
64 /* Paranoia. */
65 if (c->ssl->session == NULL ||
66 c->ssl->session->tlsext_hostname == NULL) {
67 kore_connection_disconnect(c);
68 return;
69 }
70
71 /* Figure out what backend to use. */
72 for (i = 0; backends[i].name != NULL; i++) {
73 if (!strcasecmp(backends[i].name,
74 c->ssl->session->tlsext_hostname))
75 break;
76 }
77
78 /* If we don't have any backends, we just disconnect the client. */
79 if (backends[i].name == NULL) {
80 kore_connection_disconnect(c);
81 return;
82 }
83
84 /* Create new socket for the backend connection. */
85 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
86 kore_log(LOG_ERR, "socket(): %s", errno_s);
87 kore_connection_disconnect(c);
88 return;
89 }
90
91 /* Set it to non blocking as well. */
92 if (!kore_connection_nonblock(fd, 1)) {
93 close(fd);
94 kore_connection_disconnect(c);
95 return;
96 }
97
98 /* Grab a new connection from Kore to hook backend into. */
99 backend = kore_connection_new(NULL);
100
101 /* Prepare our connection. */
102 backend->addrtype = AF_INET;
103 backend->addr.ipv4.sin_family = AF_INET;
104 backend->addr.ipv4.sin_port = htons(backends[i].port);
105 backend->addr.ipv4.sin_addr.s_addr = inet_addr(backends[i].ip);
106
107 /* Set the file descriptor for the backend. */
108 backend->fd = fd;
109
110 /* Default write/read callbacks for backend. */
111 backend->read = net_read;
112 backend->write = net_write;
113
114 /* Connection type (unknown to Kore). */
115 backend->proto = CONN_PROTO_UNKNOWN;
116 backend->state = CONN_STATE_ESTABLISHED;
117
118 /* The backend idle timer is set first to connection timeout. */
119 backend->idle_timer.length = PROXY_CONNECT_TIMEOUT;
120
121 /* The client idle timer is set to default idle time. */
122 c->idle_timer.length = PROXY_TIMEOUT;
123
124 /* Now link both the client and the backend connection together. */
125 c->hdlr_extra = backend;
126 backend->hdlr_extra = c;
127
128 /*
129 * The handle function pointer for the backend is set to the
130 * backend_handle_connect() while connecting.
131 */
132 c->handle = client_handle;
133 backend->handle = backend_handle_connect;
134
135 /* Set the disconnect method for both connections. */
136 c->disconnect = disconnect;
137 backend->disconnect = disconnect;
138
139 /* Queue write events for the backend connection for now. */
140 kore_platform_schedule_write(backend->fd, backend);
141
142 /* Start idle timer for the backend. */
143 kore_connection_start_idletimer(backend);
144
145 /* Set our client connection to established. */
146 c->state = CONN_STATE_ESTABLISHED;
147
148 /* Insert the backend into the list of Kore connections. */
149 TAILQ_INSERT_TAIL(&connections, backend, list);
150
151 /* Kick off connecting. */
152 backend->flags |= CONN_WRITE_POSSIBLE;
153 backend->handle(backend);
154 }
155
156 /*
157 * This function is called for backends while they are connecting.
158 * In here we check for write events and attempt to connect() to the
159 * backend.
160 *
161 * Once a connection is established we set the backend handle function
162 * pointer to the backend_handle_default() callback and setup the reads
163 * for both the backend and the client connection we received.
164 */
165 int
166 backend_handle_connect(struct connection *c)
167 {
168 int ret;
169 struct connection *src;
170
171 /* We will get a write notification when we can progress. */
172 if (!(c->flags & CONN_WRITE_POSSIBLE))
173 return (KORE_RESULT_OK);
174
175 kore_connection_stop_idletimer(c);
176
177 /* Attempt connecting. */
178 ret = connect(c->fd, (struct sockaddr *)&c->addr.ipv4,
179 sizeof(c->addr.ipv4));
180
181 /* If we failed check why, we are non blocking. */
182 if (ret == -1) {
183 /* If we got a real error, disconnect. */
184 if (errno != EALREADY && errno != EINPROGRESS &&
185 errno != EISCONN) {
186 kore_log(LOG_ERR, "connect(): %s", errno_s);
187 return (KORE_RESULT_ERROR);
188 }
189
190 /* Clean the write flag, we'll be called later. */
191 if (errno != EISCONN) {
192 c->flags &= ~CONN_WRITE_POSSIBLE;
193 kore_connection_start_idletimer(c);
194 return (KORE_RESULT_OK);
195 }
196 }
197
198 /* The connection to the backend succeeded. */
199 c->handle = backend_handle_default;
200
201 /* Setup read calls for both backend and its client. */
202 net_recv_queue(c, NETBUF_SEND_PAYLOAD_MAX,
203 NETBUF_CALL_CB_ALWAYS, pipe_data);
204 net_recv_queue(c->hdlr_extra, NETBUF_SEND_PAYLOAD_MAX,
205 NETBUF_CALL_CB_ALWAYS, pipe_data);
206
207 /* Allow for all events now. */
208 kore_connection_start_idletimer(c);
209 kore_platform_event_all(c->fd, c);
210
211 /* Allow events from source now. */
212 src = c->hdlr_extra;
213 kore_platform_event_all(src->fd, src);
214
215 /* Now lets start. */
216 return (c->handle(c));
217 }
218
219 /*
220 * Called for connection activity on a backend, just forwards
221 * to the default Kore connection handling for now.
222 */
223 int
224 backend_handle_default(struct connection *c)
225 {
226 return (kore_connection_handle(c));
227 }
228
229 /*
230 * Called for connection activity on a client, just forwards
231 * to the default Kore connection handling for now.
232 */
233 int
234 client_handle(struct connection *c)
235 {
236 return (kore_connection_handle(c));
237 }
238
239 /*
240 * Called whenever a client or its backend have disconnected.
241 * This will disconnect the matching paired connection as well.
242 */
243 void
244 disconnect(struct connection *c)
245 {
246 struct connection *pair = c->hdlr_extra;
247
248 c->hdlr_extra = NULL;
249
250 if (pair != NULL) {
251 pair->hdlr_extra = NULL;
252 kore_connection_disconnect(pair);
253 }
254 }
255
256 /*
257 * Called whenever data is available that must be piped through
258 * to the paired connection. (client<>backend or backend<>client).
259 */
260 int
261 pipe_data(struct netbuf *nb)
262 {
263 struct connection *src = nb->owner;
264 struct connection *dst = src->hdlr_extra;
265
266 /* Flush data out towards destination. */
267 net_send_queue(dst, nb->buf, nb->s_off);
268 net_send_flush(dst);
269
270 /* Reset read for source. */
271 net_recv_reset(src, NETBUF_SEND_PAYLOAD_MAX, pipe_data);
272
273 return (KORE_RESULT_OK);
274 }
0 *.o
1 .objs
2 upload.so
3 assets.h
4 cert
0 # upload build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
0 # Placeholder configuration
1
2 bind 127.0.0.1 8888
3 load ./upload.so
4
5 tls_dhparam dh2048.pem
6
7 http_body_max 1024000000
8 http_body_disk_offload 4096
9
10 domain 127.0.0.1 {
11 certfile cert/server.crt
12 certkey cert/server.key
13
14 static / page
15 }
0 /*
1 * Copyright (c) 2016 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 /*
17 * This example demonstrates how to properly deal with file uploads
18 * coming from a multipart form.
19 *
20 * The basics are quite trivial:
21 * 1) call http_populate_multipart_form()
22 * 2) find the file using http_file_lookup().
23 * 3) read the file data using http_file_read().
24 *
25 * In this example the contents is written to a newly created file
26 * on the server that matches the naming given by the uploader.
27 *
28 * Note that the above is probably not what you want to do in real life.
29 */
30
31 #include <kore/kore.h>
32 #include <kore/http.h>
33
34 #include <fcntl.h>
35 #include <unistd.h>
36
37 int page(struct http_request *);
38
39 int
40 page(struct http_request *req)
41 {
42 int fd;
43 struct http_file *file;
44 u_int8_t buf[BUFSIZ];
45 ssize_t ret, written;
46
47 /* Only deal with POSTs. */
48 if (req->method != HTTP_METHOD_POST) {
49 http_response(req, 405, NULL, 0);
50 return (KORE_RESULT_OK);
51 }
52
53 /* Parse the multipart data that was present. */
54 http_populate_multipart_form(req);
55
56 /* Find our file. */
57 if ((file = http_file_lookup(req, "file")) == NULL) {
58 http_response(req, 400, NULL, 0);
59 return (KORE_RESULT_OK);
60 }
61
62 /* Open dump file where we will write file contents. */
63 fd = open(file->filename, O_CREAT | O_TRUNC | O_WRONLY, 0700);
64 if (fd == -1) {
65 http_response(req, 500, NULL, 0);
66 return (KORE_RESULT_OK);
67 }
68
69 /* While we have data from http_file_read(), write it. */
70 /* Alternatively you could look at file->offset and file->length. */
71 ret = KORE_RESULT_ERROR;
72 for (;;) {
73 ret = http_file_read(file, buf, sizeof(buf));
74 if (ret == -1) {
75 kore_log(LOG_ERR, "failed to read from file");
76 http_response(req, 500, NULL, 0);
77 goto cleanup;
78 }
79
80 if (ret == 0)
81 break;
82
83 written = write(fd, buf, ret);
84 if (written == -1) {
85 kore_log(LOG_ERR,"write(%s): %s",
86 file->filename, errno_s);
87 http_response(req, 500, NULL, 0);
88 goto cleanup;
89 }
90
91 if (written != ret) {
92 kore_log(LOG_ERR, "partial write on %s",
93 file->filename);
94 http_response(req, 500, NULL, 0);
95 goto cleanup;
96 }
97 }
98
99 ret = KORE_RESULT_OK;
100 http_response(req, 200, NULL, 0);
101 kore_log(LOG_INFO, "file '%s' successfully received",
102 file->filename);
103
104 cleanup:
105 if (close(fd) == -1)
106 kore_log(LOG_WARNING, "close(%s): %s", file->filename, errno_s);
107
108 if (ret == KORE_RESULT_ERROR) {
109 if (unlink(file->filename) == -1) {
110 kore_log(LOG_WARNING, "unlink(%s): %s",
111 file->filename, errno_s);
112 }
113 ret = KORE_RESULT_OK;
114 }
115
116 return (KORE_RESULT_OK);
117 }
0 # video_stream build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
44
55 tls_dhparam dh2048.pem
66
7 spdy_idle_time 600
87 http_keepalive_time 600
98
109 domain 127.0.0.1 {
3636 TAILQ_ENTRY(video) list;
3737 };
3838
39 void init(int);
39 int init(int);
4040 int serve_page(struct http_request *);
4141 int video_stream(struct http_request *);
4242
4747
4848 TAILQ_HEAD(, video) videos;
4949
50 void
50 int
5151 init(int state)
5252 {
53 switch (state) {
54 case KORE_MODULE_LOAD:
55 TAILQ_INIT(&videos);
56 break;
57 case KORE_MODULE_UNLOAD:
58 fatal("cannot reload this module, i should fix this");
59 break;
60 }
53 if (state == KORE_MODULE_UNLOAD) {
54 kore_log(LOG_NOTICE, "not reloading module");
55 return (KORE_RESULT_ERROR);
56 }
57
58 TAILQ_INIT(&videos);
59 return (KORE_RESULT_OK);
6160 }
6261
6362 int
186185
187186 close(v->fd);
188187 TAILQ_REMOVE(&videos, v, list);
189 kore_mem_free(v->path);
190 kore_mem_free(v);
188 kore_free(v->path);
189 kore_free(v);
191190
192191 http_response(req, 500, NULL, 0);
193192 return (KORE_RESULT_ERROR);
201200 v->path = kore_strdup(fpath);
202201
203202 if ((v->fd = open(fpath, O_RDONLY)) == -1) {
204 kore_mem_free(v->path);
205 kore_mem_free(v);
203 kore_free(v->path);
204 kore_free(v);
206205
207206 if (errno == ENOENT)
208207 http_response(req, 404, NULL, 0);
214213
215214 if (fstat(v->fd, &st) == -1) {
216215 close(v->fd);
217 kore_mem_free(v->path);
218 kore_mem_free(v);
216 kore_free(v->path);
217 kore_free(v);
219218
220219 http_response(req, 500, NULL, 0);
221220 return (KORE_RESULT_ERROR);
224223 v->size = st.st_size;
225224 if (!video_mmap(req, v)) {
226225 close(v->fd);
227 kore_mem_free(v->path);
228 kore_mem_free(v);
226 kore_free(v->path);
227 kore_free(v);
229228
230229 http_response(req, 500, NULL, 0);
231230 return (KORE_RESULT_ERROR);
0 # websocket build config
1 # You can switch flavors using: kore flavor [newflavor]
2
3 # The cflags below are shared between flavors
4 cflags=-Wall -Wmissing-declarations -Wshadow
5 cflags=-Wstrict-prototypes -Wmissing-prototypes
6 cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
7
8 dev {
9 # These cflags are added to the shared ones when
10 # you build the "dev" flavor.
11 cflags=-g
12 }
13
14 #prod {
15 # You can specify additional CFLAGS here which are only
16 # included if you build with the "prod" flavor.
17 #}
33 load ./websocket.so
44
55 tls_dhparam dh2048.pem
6
7 # Increase workers so connections are spread
8 # across them to demonstrate WEBSOCKET_BROADCAST_GLOBAL.
9 workers 4
610
711 websocket_maxframe 65536
812 websocket_timeout 20
4343 void
4444 websocket_message(struct connection *c, u_int8_t op, void *data, size_t len)
4545 {
46 kore_websocket_broadcast(c, op, data, len, WEBSOCKET_BROADCAST_LOCAL);
46 kore_websocket_broadcast(c, op, data, len, WEBSOCKET_BROADCAST_GLOBAL);
4747 }
4848
4949 void
1313 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414 */
1515
16 #if !defined(KORE_NO_HTTP)
17
1618 #ifndef __H_HTTP_H
1719 #define __H_HTTP_H
1820
2325 #define HTTP_KEEPALIVE_TIME 20
2426 #define HTTP_HSTS_ENABLE 31536000
2527 #define HTTP_HEADER_MAX_LEN 4096
26 #define HTTP_BODY_MAX_LEN 10240000
28 #define HTTP_BODY_MAX_LEN 1024000
2729 #define HTTP_URI_LEN 2000
2830 #define HTTP_USERAGENT_LEN 256
2931 #define HTTP_REQ_HEADER_MAX 25
30 #define HTTP_MAX_QUERY_ARGS 10
32 #define HTTP_MAX_QUERY_ARGS 20
3133 #define HTTP_MAX_COOKIES 10
3234 #define HTTP_REQUEST_LIMIT 1000
35 #define HTTP_BODY_DISK_PATH "tmp_files"
36 #define HTTP_BODY_DISK_OFFLOAD 0
37 #define HTTP_BODY_PATH_MAX 256
38 #define HTTP_BOUNDARY_MAX 80
3339
3440 #define HTTP_ARG_TYPE_RAW 0
3541 #define HTTP_ARG_TYPE_BYTE 1
5561
5662 struct http_arg {
5763 char *name;
58 void *value;
59 u_int32_t len;
60
6164 char *s_value;
62 u_int32_t s_len;
6365
6466 TAILQ_ENTRY(http_arg) list;
6567 };
6668
67 #define COPY_ARG_TYPE(v, l, t) \
69 #define COPY_ARG_TYPE(v, t) \
6870 do { \
69 if (l != NULL) \
70 *l = sizeof(t); \
7171 *(t *)nout = v; \
72 } while (0);
72 } while (0)
7373
7474 #define COPY_ARG_INT64(type, sign) \
7575 do { \
7878 nval = (type)kore_strtonum64(q->s_value, sign, &err); \
7979 if (err != KORE_RESULT_OK) \
8080 return (KORE_RESULT_ERROR); \
81 COPY_ARG_TYPE(nval, len, type); \
82 } while (0);
81 COPY_ARG_TYPE(nval, type); \
82 } while (0)
8383
8484 #define COPY_ARG_INT(min, max, type) \
8585 do { \
8888 nval = kore_strtonum(q->s_value, 10, min, max, &err); \
8989 if (err != KORE_RESULT_OK) \
9090 return (KORE_RESULT_ERROR); \
91 COPY_ARG_TYPE(nval, len, type); \
92 } while (0);
93
94 #define CACHE_STRING() \
95 do { \
96 if (q->s_value == NULL) { \
97 q->s_len = q->len + 1; \
98 q->s_value = kore_malloc(q->s_len); \
99 kore_strlcpy(q->s_value, q->value, q->s_len); \
100 } \
101 } while (0);
91 COPY_ARG_TYPE(nval, type); \
92 } while (0)
10293
10394 #define COPY_AS_INTTYPE_64(type, sign) \
10495 do { \
10596 if (nout == NULL) \
10697 return (KORE_RESULT_ERROR); \
107 CACHE_STRING(); \
10898 COPY_ARG_INT64(type, sign); \
109 } while (0);
99 } while (0)
110100
111101 #define COPY_AS_INTTYPE(min, max, type) \
112102 do { \
113103 if (nout == NULL) \
114104 return (KORE_RESULT_ERROR); \
115 CACHE_STRING(); \
116105 COPY_ARG_INT(min, max, type); \
117 } while (0);
118
119 #define http_argument_type(r, n, so, no, l, t) \
120 http_argument_get(r, n, so, no, l, t)
121
122 #define http_argument_get_string(n, o, l) \
123 http_argument_type(req, n, (void **)o, NULL, l, HTTP_ARG_TYPE_STRING)
124
125 #define http_argument_get_byte(n, o) \
126 http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_BYTE)
127
128 #define http_argument_get_uint16(n, o) \
129 http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_UINT16)
130
131 #define http_argument_get_int16(n, o) \
132 http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_INT16)
133
134 #define http_argument_get_uint32(n, o) \
135 http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_UINT32)
136
137 #define http_argument_get_int32(n, o) \
138 http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_INT32)
139
140 #define http_argument_get_uint64(n, o) \
141 http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_UINT64)
142
143 #define http_argument_get_int64(n, o) \
144 http_argument_type(req, n, NULL, o, NULL, HTTP_ARG_TYPE_INT64)
106 } while (0)
107
108 #define http_argument_type(r, n, so, no, t) \
109 http_argument_get(r, n, so, no, t)
110
111 #define http_argument_get_string(r, n, o) \
112 http_argument_type(r, n, (void **)o, NULL, HTTP_ARG_TYPE_STRING)
113
114 #define http_argument_get_byte(r, n, o) \
115 http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_BYTE)
116
117 #define http_argument_get_uint16(r, n, o) \
118 http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT16)
119
120 #define http_argument_get_int16(r, n, o) \
121 http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT16)
122
123 #define http_argument_get_uint32(r, n, o) \
124 http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT32)
125
126 #define http_argument_get_int32(r, n, o) \
127 http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT32)
128
129 #define http_argument_get_uint64(r, n, o) \
130 http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT64)
131
132 #define http_argument_get_int64(r, n, o) \
133 http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT64)
145134
146135
147136 struct http_file {
148137 char *name;
149138 char *filename;
150
151 u_int8_t *data;
152 u_int32_t len;
153
139 size_t position;
140 size_t offset;
141 size_t length;
142 struct http_request *req;
154143 TAILQ_ENTRY(http_file) list;
155144 };
156145
160149 #define HTTP_METHOD_DELETE 3
161150 #define HTTP_METHOD_HEAD 4
162151
163 #define HTTP_REQUEST_COMPLETE 0x01
164 #define HTTP_REQUEST_DELETE 0x02
165 #define HTTP_REQUEST_SLEEPING 0x04
166 #define HTTP_REQUEST_PGSQL_QUEUE 0x10
167 #define HTTP_REQUEST_EXPECT_BODY 0x20
168 #define HTTP_REQUEST_RETAIN_EXTRA 0x40
169 #define HTTP_REQUEST_NO_CONTENT_LENGTH 0x80
152 #define HTTP_REQUEST_COMPLETE 0x0001
153 #define HTTP_REQUEST_DELETE 0x0002
154 #define HTTP_REQUEST_SLEEPING 0x0004
155 #define HTTP_REQUEST_PGSQL_QUEUE 0x0010
156 #define HTTP_REQUEST_EXPECT_BODY 0x0020
157 #define HTTP_REQUEST_RETAIN_EXTRA 0x0040
158 #define HTTP_REQUEST_NO_CONTENT_LENGTH 0x0080
159 #define HTTP_REQUEST_AUTHED 0x0100
170160
171161 struct kore_task;
172162
173163 struct http_request {
174164 u_int8_t method;
175 u_int8_t flags;
176165 u_int8_t fsm_state;
166 u_int16_t flags;
177167 u_int16_t status;
178168 u_int64_t start;
179169 u_int64_t end;
182172 char *path;
183173 char *agent;
184174 struct connection *owner;
185 struct spdy_stream *stream;
186175 struct kore_buf *http_body;
176 int http_body_fd;
177 char *http_body_path;
178 size_t http_body_length;
179 size_t http_body_offset;
180 size_t content_length;
187181 void *hdlr_extra;
188182 char *query_string;
189 u_int8_t *multipart_body;
190183 struct kore_module_handle *hdlr;
191184
192185 LIST_HEAD(, kore_task) tasks;
211204 extern u_int64_t http_hsts_enable;
212205 extern u_int16_t http_keepalive_time;
213206 extern u_int32_t http_request_limit;
207 extern u_int64_t http_body_disk_offload;
208 extern char *http_body_disk_path;
209
210 void kore_accesslog(struct http_request *);
214211
215212 void http_init(void);
213 void http_cleanup(void);
216214 void http_process(void);
217215 const char *http_status_text(int);
216 const char *http_method_text(int);
218217 time_t http_date_to_time(char *);
219218 void http_request_free(struct http_request *);
220219 void http_request_sleep(struct http_request *);
221220 void http_request_wakeup(struct http_request *);
222 char *http_body_text(struct http_request *);
223 void http_process_request(struct http_request *, int);
224 u_int8_t *http_body_bytes(struct http_request *, u_int32_t *);
225 void http_response(struct http_request *, int, void *, u_int32_t);
221 void http_process_request(struct http_request *);
222 ssize_t http_body_read(struct http_request *, void *, size_t);
223 void http_response(struct http_request *, int, const void *, size_t);
226224 void http_response_stream(struct http_request *, int, void *,
227 u_int64_t, int (*cb)(struct netbuf *), void *);
225 size_t, int (*cb)(struct netbuf *), void *);
228226 int http_request_header(struct http_request *,
229227 const char *, char **);
230228 void http_response_header(struct http_request *,
231229 const char *, const char *);
232 int http_request_new(struct connection *, struct spdy_stream *,
233 const char *, const char *, const char *, const char *,
230 int http_request_new(struct connection *, const char *,
231 const char *, const char *, const char *,
234232 struct http_request **);
235233 int http_state_run(struct http_state *, u_int8_t,
236234 struct http_request *);
237235
238236 int http_argument_urldecode(char *);
239237 int http_header_recv(struct netbuf *);
240 int http_generic_404(struct http_request *);
241 int http_populate_arguments(struct http_request *);
242 int http_populate_multipart_form(struct http_request *, int *);
238 void http_populate_get(struct http_request *);
239 void http_populate_post(struct http_request *);
240 void http_populate_multipart_form(struct http_request *);
243241 int http_argument_get(struct http_request *,
244 const char *, void **, void *, u_int32_t *, int);
245 int http_file_lookup(struct http_request *, const char *, char **,
246 u_int8_t **, u_int32_t *);
247
248 void kore_accesslog(struct http_request *);
242 const char *, void **, void *, int);
243
244 void http_file_rewind(struct http_file *);
245 ssize_t http_file_read(struct http_file *, void *, size_t);
246 struct http_file *http_file_lookup(struct http_request *, const char *);
249247
250248 enum http_status_code {
251249 HTTP_STATUS_CONTINUE = 100,
293291 }
294292 #endif
295293 #endif /* !__H_HTTP_H */
294
295 #endif /* ! KORE_NO_HTTP */
0 /*
1 * Copyright (c) 2016 Raphaël Monrouzeau <raphael.monrouzeau@gmail.com>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #if !defined(KORE_NO_HTTP)
17
18 #ifndef __H_JSONRPC_H
19 #define __H_JSONRPC_H
20
21 #if defined(__cplusplus)
22 extern "C" {
23 #endif
24
25 /* JSON RPC request handling log entry. */
26 struct jsonrpc_log
27 {
28 char *msg;
29 struct jsonrpc_log *next, *prev;
30 int lvl;
31 };
32
33 /* JSON RPC request. */
34 struct jsonrpc_request
35 {
36 struct jsonrpc_log log;
37 struct kore_buf buf;
38 struct http_request *http;
39 yajl_gen gen;
40 yajl_val json;
41 yajl_val id;
42 char *method;
43 yajl_val params;
44 unsigned int flags;
45 int log_levels;
46 };
47
48 #define YAJL_GEN_CONST_STRING(CTX, STR) \
49 yajl_gen_string((CTX), (unsigned char *)(STR), sizeof (STR) - 1)
50
51 #define YAJL_GEN_CONST_NUMBER(CTX, STR) \
52 yajl_gen_number((CTX), (unsigned char *)(STR), sizeof (STR) - 1)
53
54 #define YAJL_GEN_KO(OPERATION) \
55 ((OPERATION) != yajl_gen_status_ok)
56
57 enum jsonrpc_error_code
58 {
59 #define JSONRPC_PARSE_ERROR_MSG "Parse error"
60 JSONRPC_PARSE_ERROR = -32700,
61 #define JSONRPC_INVALID_REQUEST_MSG "Invalid Request"
62 JSONRPC_INVALID_REQUEST = -32600,
63 #define JSONRPC_METHOD_NOT_FOUND_MSG "Method not found"
64 JSONRPC_METHOD_NOT_FOUND = -32601,
65 #define JSONRPC_INVALID_PARAMS_MSG "Invalid params"
66 JSONRPC_INVALID_PARAMS = -32602,
67 #define JSONRPC_INTERNAL_ERROR_MSG "Internal error"
68 JSONRPC_INTERNAL_ERROR = -32603,
69 #define JSONRPC_SERVER_ERROR_MSG "Server error"
70 JSONRPC_SERVER_ERROR = -32000,
71 #define JSONRPC_LIMIT_REACHED_MSG "Limit reached"
72 JSONRPC_LIMIT_REACHED = -31997
73 };
74
75 void jsonrpc_log(struct jsonrpc_request *, int, const char *, ...);
76 int jsonrpc_read_request(struct http_request *, struct jsonrpc_request *);
77 void jsonrpc_destroy_request(struct jsonrpc_request *);
78 int jsonrpc_error(struct jsonrpc_request *, int, const char *);
79 int jsonrpc_result(struct jsonrpc_request *,
80 int (*)(struct jsonrpc_request *, void *), void *);
81 #if defined(__cplusplus)
82 }
83 #endif
84 #endif /* !__H_JSONRPC_H */
85
86 #endif /* ! KORE_NO_HTTP */
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
2121 #endif
2222
2323 #include <sys/types.h>
24 #include <sys/time.h>
2425 #include <sys/queue.h>
2526
2627 #include <netinet/in.h>
2728 #include <arpa/inet.h>
2829
30 #if !defined(KORE_NO_TLS)
2931 #include <openssl/err.h>
3032 #include <openssl/dh.h>
3133 #include <openssl/ssl.h>
34 #endif
3235
3336 #include <errno.h>
3437 #include <regex.h>
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
3542 #include <syslog.h>
3643 #include <unistd.h>
37 #include <zlib.h>
44 #include <stdarg.h>
3845
3946 #if defined(__cplusplus)
4047 extern "C" {
4552 extern int daemon(int, int);
4653 #endif
4754
48 #include "spdy.h"
49
5055 #define KORE_RESULT_ERROR 0
5156 #define KORE_RESULT_OK 1
5257 #define KORE_RESULT_RETRY 2
5358
54 #define KORE_VERSION_MAJOR 1
55 #define KORE_VERSION_MINOR 2
56 #define KORE_VERSION_PATCH 3
59 #define KORE_VERSION_MAJOR 2
60 #define KORE_VERSION_MINOR 0
61 #define KORE_VERSION_PATCH 0
5762 #define KORE_VERSION_STATE "release"
5863
5964 #define KORE_TLS_VERSION_1_2 0
6368 #define errno_s strerror(errno)
6469 #define ssl_errno_s ERR_error_string(ERR_get_error(), NULL)
6570
66 #define KORE_DOMAINNAME_LEN 254
71 #define KORE_DOMAINNAME_LEN 255
6772 #define KORE_PIDFILE_DEFAULT "kore.pid"
6873 #define KORE_DEFAULT_CIPHER_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!kRSA:!kDSA"
6974
7075 #if defined(KORE_DEBUG)
71 #define kore_debug(fmt, ...) \
76 #define kore_debug(...) \
7277 if (kore_debug) \
73 kore_debug_internal(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
78 kore_debug_internal(__FILE__, __LINE__, __VA_ARGS__)
7479 #else
75 #define kore_debug(fmt, ...)
80 #define kore_debug(...)
7681 #endif
7782
7883 #define NETBUF_RECV 0
9499 #define X509_CN_LENGTH (ub_common_name + 1)
95100
96101 /* XXX hackish. */
102 #if !defined(KORE_NO_HTTP)
97103 struct http_request;
98 struct spdy_stream;
104 #endif
99105
100106 struct netbuf {
101107 u_int8_t *buf;
102 u_int32_t s_off;
103 u_int32_t b_len;
104 u_int32_t m_len;
108 size_t s_off;
109 size_t b_len;
110 size_t m_len;
105111 u_int8_t type;
106112 u_int8_t flags;
107113
108114 void *owner;
109 struct spdy_stream *stream;
110115
111116 void *extra;
112117 int (*cb)(struct netbuf *);
121126 #define KORE_TYPE_PGSQL_CONN 3
122127 #define KORE_TYPE_TASK 4
123128
124 struct listener {
125 u_int8_t type;
126
127 int fd;
128 u_int8_t addrtype;
129
130 union {
131 struct sockaddr_in ipv4;
132 struct sockaddr_in6 ipv6;
133 } addr;
134
135 LIST_ENTRY(listener) list;
136 };
137
138 LIST_HEAD(listener_head, listener);
139
140129 #define CONN_STATE_UNKNOWN 0
141130 #define CONN_STATE_SSL_SHAKE 1
142131 #define CONN_STATE_ESTABLISHED 2
143132 #define CONN_STATE_DISCONNECTING 3
144133
145134 #define CONN_PROTO_UNKNOWN 0
146 #define CONN_PROTO_SPDY 1
147 #define CONN_PROTO_HTTP 2
148 #define CONN_PROTO_WEBSOCKET 3
135 #define CONN_PROTO_HTTP 1
136 #define CONN_PROTO_WEBSOCKET 2
137 #define CONN_PROTO_MSG 3
149138
150139 #define CONN_READ_POSSIBLE 0x01
151140 #define CONN_WRITE_POSSIBLE 0x02
153142 #define CONN_IDLE_TIMER_ACT 0x10
154143 #define CONN_READ_BLOCK 0x20
155144 #define CONN_CLOSE_EMPTY 0x40
156 #define SPDY_CONN_GOAWAY 0x80
157145
158146 #define KORE_IDLE_TIMER_MAX 20000
159147
169157
170158 #define KORE_TIMER_ONESHOT 0x01
171159
160 #define KORE_CONNECTION_PRUNE_DISCONNECT 0
161 #define KORE_CONNECTION_PRUNE_ALL 1
162
172163 struct connection {
173164 u_int8_t type;
174165 int fd;
175166 u_int8_t state;
176167 u_int8_t proto;
177168 void *owner;
169 #if !defined(KORE_NO_TLS)
170 X509 *cert;
178171 SSL *ssl;
172 int tls_reneg;
173 #endif
179174 u_int8_t flags;
180175 void *hdlr_extra;
181 X509 *cert;
182 void *wscbs;
183 int tls_reneg;
184
176
177 int (*handle)(struct connection *);
185178 void (*disconnect)(struct connection *);
186179 int (*read)(struct connection *, int *);
187180 int (*write)(struct connection *, int, int *);
197190 u_int64_t start;
198191 } idle_timer;
199192
200 u_int8_t inflate_started;
201 z_stream z_inflate;
202 u_int8_t deflate_started;
203 z_stream z_deflate;
204
205 u_int32_t wsize_initial;
206 u_int32_t spdy_send_wsize;
207 u_int32_t spdy_recv_wsize;
208
209193 struct netbuf_head send_queue;
210194 struct netbuf *snb;
211195 struct netbuf *rnb;
212196
213 u_int32_t client_stream_id;
214 TAILQ_HEAD(, spdy_stream) spdy_streams;
197 #if !defined(KORE_NO_HTTP)
198 void *wscbs;
215199 TAILQ_HEAD(, http_request) http_requests;
200 #endif
216201
217202 TAILQ_ENTRY(connection) list;
218 TAILQ_ENTRY(connection) flush_list;
219203 };
220204
221205 TAILQ_HEAD(connection_list, connection);
222 extern struct connection_list worker_clients;
206 extern struct connection_list connections;
207 extern struct connection_list disconnected;
208
209 struct listener {
210 u_int8_t type;
211 u_int8_t addrtype;
212 int fd;
213 void (*connect)(struct connection *);
214
215 union {
216 struct sockaddr_in ipv4;
217 struct sockaddr_in6 ipv6;
218 } addr;
219
220 LIST_ENTRY(listener) list;
221 };
222
223 LIST_HEAD(listener_head, listener);
224
225 #if !defined(KORE_NO_HTTP)
223226
224227 struct kore_handler_params {
225228 char *name;
243246 TAILQ_ENTRY(kore_auth) list;
244247 };
245248
249 #define HANDLER_TYPE_STATIC 1
250 #define HANDLER_TYPE_DYNAMIC 2
251
252 #endif
253
246254 #define KORE_MODULE_LOAD 1
247255 #define KORE_MODULE_UNLOAD 2
248
249 #define HANDLER_TYPE_STATIC 1
250 #define HANDLER_TYPE_DYNAMIC 2
251256
252257 struct kore_module {
253258 void *handle;
268273 int errors;
269274 regex_t rctx;
270275 struct kore_domain *dom;
276 #if !defined(KORE_NO_HTTP)
271277 struct kore_auth *auth;
272
273278 TAILQ_HEAD(, kore_handler_params) params;
279 #endif
274280 TAILQ_ENTRY(kore_module_handle) list;
275281 };
276282
278284 u_int8_t id;
279285 u_int8_t cpu;
280286 pid_t pid;
287 int pipe[2];
288 struct connection *msg[2];
281289 u_int8_t has_lock;
282290 struct kore_module_handle *active_hdlr;
283291 };
284292
285293 struct kore_domain {
286294 char *domain;
295 int accesslog;
296 #if !defined(KORE_NO_TLS)
297 char *cafile;
298 char *crlfile;
287299 char *certfile;
288300 char *certkey;
289 char *cafile;
290 char *crlfile;
291 int accesslog;
292301 SSL_CTX *ssl_ctx;
302 #endif
293303 TAILQ_HEAD(, kore_module_handle) handlers;
294304 TAILQ_ENTRY(kore_domain) list;
295305 };
296306
297307 TAILQ_HEAD(kore_domain_h, kore_domain);
308
309 #if !defined(KORE_NO_HTTP)
298310
299311 #define KORE_VALIDATOR_TYPE_REGEX 1
300312 #define KORE_VALIDATOR_TYPE_FUNCTION 2
308320
309321 TAILQ_ENTRY(kore_validator) list;
310322 };
311
312 #define KORE_BUF_INITIAL 128
313 #define KORE_BUF_INCREMENT KORE_BUF_INITIAL
323 #endif
324
325 #define KORE_BUF_OWNER_API 0x0001
314326
315327 struct kore_buf {
316328 u_int8_t *data;
317 u_int64_t length;
318 u_int64_t offset;
329 int flags;
330 size_t length;
331 size_t offset;
319332 };
320333
321334 struct kore_pool_region {
322 void *start;
335 void *start;
336 size_t length;
323337 LIST_ENTRY(kore_pool_region) list;
324338 };
325339
330344 };
331345
332346 struct kore_pool {
333 u_int32_t elen;
334 u_int32_t slen;
335 u_int32_t elms;
336 u_int32_t inuse;
347 size_t elen;
348 size_t slen;
349 size_t elms;
350 size_t inuse;
351 volatile int lock;
337352 char *name;
338353
339354 LIST_HEAD(, kore_pool_region) regions;
352367 u_int64_t interval;
353368 int flags;
354369 void *arg;
355 void (*cb)(void *, u_int64_t, u_int64_t);
370 void (*cb)(void *, u_int64_t);
356371
357372 TAILQ_ENTRY(kore_timer) list;
358373 };
374
375 #define KORE_WORKER_KEYMGR 0
376
377 /* Reserved message ids, registered on workers. */
378 #define KORE_MSG_ACCESSLOG 1
379 #define KORE_MSG_WEBSOCKET 2
380 #define KORE_MSG_KEYMGR_REQ 3
381 #define KORE_MSG_KEYMGR_RESP 4
382
383 /* Predefined message targets. */
384 #define KORE_MSG_PARENT 1000
385 #define KORE_MSG_WORKER_ALL 1001
386
387 struct kore_msg {
388 u_int8_t id;
389 u_int16_t src;
390 u_int16_t dst;
391 u_int32_t length;
392 };
393
394 #if !defined(KORE_NO_TLS)
395 struct kore_keyreq {
396 int padding;
397 char domain[KORE_DOMAINNAME_LEN];
398 u_int8_t domain_len;
399 u_int16_t data_len;
400 u_int8_t data[];
401 };
402 #endif
403
404 #if !defined(KORE_SINGLE_BINARY)
405 extern char *config_file;
406 #endif
359407
360408 extern pid_t kore_pid;
361409 extern int foreground;
365413 extern int skip_runas;
366414 extern char *runas_user;
367415 extern char *kore_pidfile;
368 extern char *config_file;
369416 extern char *kore_tls_cipher_list;
370417 extern int tls_version;
418
419 #if !defined(KORE_NO_TLS)
371420 extern DH *tls_dhparam;
421 #endif
372422
373423 extern u_int8_t nlisteners;
374 extern u_int64_t spdy_idle_time;
375424 extern u_int16_t cpu_count;
376425 extern u_int8_t worker_count;
377426 extern u_int8_t worker_set_affinity;
396445 void kore_worker_wait(int);
397446 void kore_worker_init(void);
398447 void kore_worker_shutdown(void);
448 void kore_worker_privdrop(void);
399449 void kore_worker_dispatch_signal(int);
400450 void kore_worker_spawn(u_int16_t, u_int16_t);
401451 void kore_worker_entry(struct kore_worker *);
402 void kore_worker_connection_add(struct connection *);
403 void kore_worker_connection_move(struct connection *);
404 void kore_worker_connection_remove(struct connection *);
405 void kore_worker_websocket_broadcast(struct connection *,
406 void (*cb)(struct connection *, void *), void *);
452
453 struct kore_worker *kore_worker_data(u_int8_t);
407454
408455 void kore_platform_init(void);
409456 void kore_platform_event_init(void);
457 void kore_platform_event_cleanup(void);
410458 void kore_platform_proctitle(char *);
411459 void kore_platform_disable_read(int);
412460 void kore_platform_enable_accept(void);
414462 int kore_platform_event_wait(u_int64_t);
415463 void kore_platform_event_all(int, void *);
416464 void kore_platform_schedule_read(int, void *);
465 void kore_platform_schedule_write(int, void *);
417466 void kore_platform_event_schedule(int, int, int, void *);
418467 void kore_platform_worker_setcpu(struct kore_worker *);
419468
420469 void kore_accesslog_init(void);
421 int kore_accesslog_wait(void);
422470 void kore_accesslog_worker_init(void);
423
471 int kore_accesslog_write(const void *, u_int32_t);
472
473 #if !defined(KORE_NO_HTTP)
424474 int kore_auth_run(struct http_request *, struct kore_auth *);
425475 void kore_auth_init(void);
426476 int kore_auth_new(const char *);
427477 struct kore_auth *kore_auth_lookup(const char *);
478 #endif
428479
429480 void kore_timer_init(void);
430481 u_int64_t kore_timer_run(u_int64_t);
431482 void kore_timer_remove(struct kore_timer *);
432 struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t,
433 u_int64_t), u_int64_t, void *, int);
434
483 struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t),
484 u_int64_t, void *, int);
485
486 void kore_listener_cleanup(void);
487 int kore_server_bind(const char *, const char *, const char *);
488 #if !defined(KORE_NO_TLS)
435489 int kore_tls_sni_cb(SSL *, int *, void *);
436 int kore_server_bind(const char *, const char *);
437 int kore_tls_npn_cb(SSL *, const u_char **, unsigned int *, void *);
438490 void kore_tls_info_callback(const SSL *, int, int);
491 #endif
439492
440493 void kore_connection_init(void);
494 void kore_connection_cleanup(void);
495 void kore_connection_prune(int);
441496 struct connection *kore_connection_new(void *);
442 int kore_connection_nonblock(int);
497 void kore_connection_check_timeout(void);
498 int kore_connection_nonblock(int, int);
443499 int kore_connection_handle(struct connection *);
444500 void kore_connection_remove(struct connection *);
445501 void kore_connection_disconnect(struct connection *);
457513 void kore_parse_config(void);
458514 void *kore_calloc(size_t, size_t);
459515 void *kore_realloc(void *, size_t);
460 void kore_mem_free(void *);
516 void kore_free(void *);
461517 void kore_mem_init(void);
462
463 #if defined(KORE_PEDANTIC_MALLOC)
464 void explicit_bzero(void *, size_t);
465 #endif
466518
467519 void *kore_pool_get(struct kore_pool *);
468520 void kore_pool_put(struct kore_pool *, void *);
469521 void kore_pool_init(struct kore_pool *, const char *,
470 u_int32_t, u_int32_t);
522 size_t, size_t);
523 void kore_pool_cleanup(struct kore_pool *);
471524
472525 time_t kore_date_to_time(char *);
473526 char *kore_time_to_date(time_t);
474527 char *kore_strdup(const char *);
475528 void kore_log(int, const char *, ...);
476529 u_int64_t kore_strtonum64(const char *, int, int *);
477 void kore_strlcpy(char *, const char *, size_t);
530 size_t kore_strlcpy(char *, const char *, const size_t);
478531 void kore_server_disconnect(struct connection *);
479532 int kore_split_string(char *, char *, char **, size_t);
480 void kore_strip_chars(char *, char, char **);
533 void kore_strip_chars(char *, const char, char **);
481534 int kore_snprintf(char *, size_t, int *, const char *, ...);
482535 long long kore_strtonum(const char *, int, long long, long long, int *);
483 int kore_base64_encode(u_int8_t *, u_int32_t, char **);
484 int kore_base64_decode(char *, u_int8_t **, u_int32_t *);
485 void *kore_mem_find(void *, size_t, void *, u_int32_t);
486
536 int kore_base64_encode(u_int8_t *, size_t, char **);
537 int kore_base64_decode(char *, u_int8_t **, size_t *);
538 void *kore_mem_find(void *, size_t, void *, size_t);
539 char *kore_text_trim(char *, size_t);
540 char *kore_read_line(FILE *, char *, size_t);
541
542 #if !defined(KORE_NO_HTTP)
487543 void kore_websocket_handshake(struct http_request *,
488544 struct kore_wscbs *);
489545 void kore_websocket_send(struct connection *,
490 u_int8_t, void *, size_t);
546 u_int8_t, const void *, size_t);
491547 void kore_websocket_broadcast(struct connection *,
492 u_int8_t, void *, size_t, int);
548 u_int8_t, const void *, size_t, int);
549 #endif
550
551 void kore_msg_init(void);
552 void kore_msg_worker_init(void);
553 void kore_msg_parent_init(void);
554 void kore_msg_parent_add(struct kore_worker *);
555 void kore_msg_parent_remove(struct kore_worker *);
556 void kore_msg_send(u_int16_t, u_int8_t, const void *, u_int32_t);
557 int kore_msg_register(u_int8_t,
558 void (*cb)(struct kore_msg *, const void *));
493559
494560 void kore_domain_init(void);
561 void kore_domain_cleanup(void);
495562 int kore_domain_new(char *);
563 void kore_domain_free(struct kore_domain *);
496564 void kore_module_init(void);
565 void kore_module_cleanup(void);
497566 void kore_module_reload(int);
498567 void kore_module_onload(void);
499568 int kore_module_loaded(void);
500569 void kore_domain_closelogs(void);
501570 void *kore_module_getsym(const char *);
502571 void kore_domain_load_crl(void);
572 void kore_domain_keymgr_init(void);
503573 void kore_module_load(const char *, const char *);
504574 void kore_domain_sslstart(struct kore_domain *);
575 void kore_domain_callback(void (*cb)(struct kore_domain *));
505576 int kore_module_handler_new(const char *, const char *,
506577 const char *, const char *, int);
578 void kore_module_handler_free(struct kore_module_handle *);
507579
508580 struct kore_domain *kore_domain_lookup(const char *);
509581 struct kore_module_handle *kore_module_handler_find(const char *,
510582 const char *);
511583
584 #if !defined(KORE_NO_HTTP)
512585 void kore_validator_init(void);
513586 void kore_validator_reload(void);
514587 int kore_validator_add(const char *, u_int8_t, const char *);
516589 int kore_validator_check(struct http_request *,
517590 struct kore_validator *, void *);
518591 struct kore_validator *kore_validator_lookup(const char *);
592 #endif
519593
520594 void fatal(const char *, ...) __attribute__((noreturn));
521595 void kore_debug_internal(char *, int, const char *, ...);
528602 void net_write64(u_int8_t *, u_int64_t);
529603
530604 void net_init(void);
605 void net_cleanup(void);
531606 int net_send(struct connection *);
532607 int net_send_flush(struct connection *);
533608 int net_recv_flush(struct connection *);
535610 int net_read_ssl(struct connection *, int *);
536611 int net_write(struct connection *, int, int *);
537612 int net_write_ssl(struct connection *, int, int *);
538 void net_recv_reset(struct connection *, u_int32_t,
613 void net_recv_reset(struct connection *, size_t,
539614 int (*cb)(struct netbuf *));
540615 void net_remove_netbuf(struct netbuf_head *, struct netbuf *);
541 void net_recv_queue(struct connection *, u_int32_t, int,
616 void net_recv_queue(struct connection *, size_t, int,
542617 int (*cb)(struct netbuf *));
543 void net_recv_expand(struct connection *c, u_int32_t,
618 void net_recv_expand(struct connection *c, size_t,
544619 int (*cb)(struct netbuf *));
545 void net_send_queue(struct connection *, void *,
546 u_int32_t, struct spdy_stream *, int);
620 void net_send_queue(struct connection *, const void *, size_t);
547621 void net_send_stream(struct connection *, void *,
548 u_int32_t, struct spdy_stream *,
549 int (*cb)(struct netbuf *), struct netbuf **);
622 size_t, int (*cb)(struct netbuf *), struct netbuf **);
550623
551624 void kore_buf_free(struct kore_buf *);
552 struct kore_buf *kore_buf_create(u_int32_t);
553 void kore_buf_append(struct kore_buf *, void *, u_int32_t);
554 u_int8_t *kore_buf_release(struct kore_buf *, u_int32_t *);
625 struct kore_buf *kore_buf_alloc(size_t);
626 void kore_buf_init(struct kore_buf *, size_t);
627 void kore_buf_append(struct kore_buf *, const void *, size_t);
628 u_int8_t *kore_buf_release(struct kore_buf *, size_t *);
629 void kore_buf_reset(struct kore_buf *);
630 void kore_buf_cleanup(struct kore_buf *);
631
632 char *kore_buf_stringify(struct kore_buf *, size_t *);
555633 void kore_buf_appendf(struct kore_buf *, const char *, ...);
556634 void kore_buf_appendv(struct kore_buf *, const char *, va_list);
557 void kore_buf_appendb(struct kore_buf *, struct kore_buf *);
558635 void kore_buf_replace_string(struct kore_buf *, char *, void *, size_t);
559636
560 struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t);
561 int spdy_stream_get_header(struct spdy_header_block *,
562 const char *, char **);
563 void spdy_update_wsize(struct connection *,
564 struct spdy_stream *, u_int32_t);
565
566 int spdy_frame_recv(struct netbuf *);
567 int spdy_dataframe_begin(struct connection *);
568 void spdy_session_teardown(struct connection *c, u_int8_t);
569 void spdy_frame_send(struct connection *, u_int16_t,
570 u_int8_t, u_int32_t, struct spdy_stream *, u_int32_t);
571 void spdy_header_block_add(struct spdy_header_block *,
572 char *, char *);
573 u_int8_t *spdy_header_block_release(struct connection *,
574 struct spdy_header_block *, u_int32_t *);
575 void spdy_stream_close(struct connection *,
576 struct spdy_stream *, int);
577
578 struct spdy_header_block *spdy_header_block_create(int);
637 void kore_keymgr_run(void);
638 void kore_keymgr_cleanup(void);
639
640 #if defined(KORE_SINGLE_BINARY)
641 void kore_onload(void);
642 #endif
579643
580644 #if defined(__cplusplus)
581645 }
2121 #define KORE_PGSQL_FORMAT_TEXT 0
2222 #define KORE_PGSQL_FORMAT_BINARY 1
2323
24 #define KORE_PGSQL_SYNC 0x0001
25 #define KORE_PGSQL_ASYNC 0x0002
26
2427 #if defined(__cplusplus)
2528 extern "C" {
2629 #endif
2831 struct pgsql_conn {
2932 u_int8_t type;
3033 u_int8_t flags;
34 char *name;
3135
3236 PGconn *db;
3337 struct pgsql_job *job;
3438 TAILQ_ENTRY(pgsql_conn) list;
3539 };
3640
41 struct pgsql_db {
42 char *name;
43 char *conn_string;
44
45 LIST_ENTRY(pgsql_db) rlist;
46 };
47
3748 struct kore_pgsql {
3849 u_int8_t state;
50 int flags;
3951 char *error;
4052 PGresult *result;
4153 struct pgsql_conn *conn;
4456 };
4557
4658 extern u_int16_t pgsql_conn_max;
47 extern char *pgsql_conn_string;
4859
4960 void kore_pgsql_init(void);
61 int kore_pgsql_query_init(struct kore_pgsql *, struct http_request *,
62 const char *, int);
5063 void kore_pgsql_handle(void *, int);
5164 void kore_pgsql_cleanup(struct kore_pgsql *);
5265 void kore_pgsql_continue(struct http_request *, struct kore_pgsql *);
53 int kore_pgsql_query(struct kore_pgsql *, struct http_request *,
54 const char *);
55 int kore_pgsql_query_params(struct kore_pgsql *, struct http_request *,
66 int kore_pgsql_query(struct kore_pgsql *, const char *);
67 int kore_pgsql_query_params(struct kore_pgsql *,
5668 const char *, int, u_int8_t, ...);
57
69 int kore_pgsql_v_query_params(struct kore_pgsql *,
70 const char *, int, u_int8_t, va_list);
71 int kore_pgsql_register(const char *, const char *);
5872 int kore_pgsql_ntuples(struct kore_pgsql *);
5973 void kore_pgsql_logerror(struct kore_pgsql *);
6074 void kore_pgsql_queue_remove(struct http_request *);
+0
-132
includes/spdy.h less more
0 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #ifndef __H_SPDY_H
17 #define __H_SPDY_H
18
19 #include <sys/types.h>
20 #include <sys/queue.h>
21
22 #if defined(__cplusplus)
23 extern "C" {
24 #endif
25
26 /* XXX */
27 struct connection;
28 struct http_request;
29
30 struct spdy_ctrl_frame {
31 u_int16_t version;
32 u_int16_t type;
33 u_int8_t flags;
34 u_int32_t length;
35 };
36
37 struct spdy_data_frame {
38 u_int32_t stream_id;
39 u_int8_t flags;
40 u_int32_t length;
41 };
42
43 struct spdy_syn_stream {
44 u_int32_t stream_id;
45 u_int32_t assoc_stream_id;
46 u_int8_t slot;
47 u_int8_t reserved;
48 u_int8_t prio;
49 };
50
51 struct spdy_header_block {
52 u_int8_t *header_block;
53 u_int32_t header_block_len;
54 u_int32_t header_offset;
55 u_int32_t header_pairs;
56 };
57
58 struct spdy_stream {
59 u_int32_t stream_id;
60 u_int8_t flags;
61 u_int8_t prio;
62 u_int64_t post_size;
63 u_int64_t send_size;
64 u_int32_t frame_size;
65 u_int32_t recv_wsize;
66 u_int32_t send_wsize;
67 void (*onclose)(struct connection *, struct spdy_stream *);
68
69 struct http_request *httpreq;
70 struct spdy_header_block *hblock;
71 TAILQ_ENTRY(spdy_stream) list;
72 };
73
74 extern const unsigned char SPDY_dictionary_txt[];
75
76 #if defined(__cplusplus)
77 }
78 #endif
79
80 #define KORE_SSL_PROTO_STRING "\x08spdy/3.1\x08http/1.1"
81 #define SPDY_CONTROL_FRAME(x) ((x & (1 << 31)))
82
83 #define SPDY_FRAME_SIZE 8
84 #define SPDY_SYNFRAME_SIZE 10
85 #define SPDY_ZLIB_DICT_SIZE 1423
86 #define SPDY_ZLIB_CHUNK 16348
87 #define SPDY_INIT_WSIZE 65536
88
89 /* control frames */
90 #define SPDY_CTRL_FRAME_SYN_STREAM 1
91 #define SPDY_CTRL_FRAME_SYN_REPLY 2
92 #define SPDY_CTRL_FRAME_RST_STREAM 3
93 #define SPDY_CTRL_FRAME_SETTINGS 4
94 #define SPDY_CTRL_FRAME_PING 6
95 #define SPDY_CTRL_FRAME_GOAWAY 7
96 #define SPDY_CTRL_FRAME_WINDOW 9
97 #define SPDY_DATA_FRAME 99
98
99 /* session error codes */
100 #define SPDY_SESSION_ERROR_OK 0
101 #define SPDY_SESSION_ERROR_PROTOCOL 1
102 #define SPDY_SESSION_ERROR_INTERNAL 2
103
104 /* flags */
105 #define FLAG_FIN 0x01
106 #define FLAG_UNIDIRECTIONAL 0x02
107
108 /* settings */
109 #define SETTINGS_UPLOAD_BANDWIDTH 1
110 #define SETTINGS_DOWNLOAD_BANDWIDTH 2
111 #define SETTINGS_ROUND_TRIP_TIME 3
112 #define SETTINGS_MAX_CONCURRENT_STREAMS 4
113 #define SETTINGS_CURRENT_CWND 5
114 #define SETTINGS_DOWNLOAD_RETRANS_RATE 6
115 #define SETTINGS_INITIAL_WINDOW_SIZE 7
116 #define SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE 8
117
118 #define SPDY_HBLOCK_NORMAL 0
119 #define SPDY_HBLOCK_DELAYED_ALLOC 1
120
121 #define SPDY_FLOW_WINDOW_MAX 2147483647
122
123 /* internal flags (make sure they don't clash with SPDY stream flags) */
124 #define SPDY_KORE_FIN 0x10
125 #define SPDY_DATAFRAME_PRELUDE 0x20
126 #define SPDY_NO_CLOSE 0x40
127
128 #define SPDY_KEEP_NETBUFS 0
129 #define SPDY_REMOVE_NETBUFS 1
130
131 #endif /* !__H_SPDY_H */
2323 #define KORE_TASK_STATE_FINISHED 3
2424 #define KORE_TASK_STATE_ABORT 4
2525
26 #define KORE_TASK_THREADS 2
27
2628 #if defined(__cplusplus)
2729 extern "C" {
2830 #endif
2931
32 #if !defined(KORE_NO_HTTP)
3033 struct http_request;
34 #endif
3135
3236 struct kore_task {
3337 u_int8_t type;
3539 int result;
3640 pthread_rwlock_t lock;
3741
42 #if !defined(KORE_NO_HTTP)
3843 struct http_request *req;
44 #endif
45
3946 int fds[2];
4047 int (*entry)(struct kore_task *);
48 void (*cb)(struct kore_task *);
4149
4250 struct kore_task_thread *thread;
4351
6270 int kore_task_finished(struct kore_task *);
6371 void kore_task_handle(struct kore_task *, int);
6472
73 #if !defined(KORE_NO_HTTP)
6574 void kore_task_bind_request(struct kore_task *,
6675 struct http_request *);
76 #endif
77 void kore_task_bind_callback(struct kore_task *,
78 void (*cb)(struct kore_task *));
6779 void kore_task_create(struct kore_task *,
6880 int (*entry)(struct kore_task *));
6981
7587
7688 int kore_task_state(struct kore_task *);
7789 int kore_task_result(struct kore_task *);
78
90
91 extern u_int16_t kore_task_threads;
92
7993 #if defined(__cplusplus)
8094 }
8195 #endif
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1616 #include <sys/socket.h>
1717
1818 #include <poll.h>
19 #include <time.h>
1920
2021 #include "kore.h"
2122 #include "http.h"
22
23 static int accesslog_fd[2];
2423
2524 struct kore_log_packet {
2625 u_int8_t method;
3332 char host[KORE_DOMAINNAME_LEN];
3433 char path[HTTP_URI_LEN];
3534 char agent[HTTP_USERAGENT_LEN];
35 #if !defined(KORE_NO_TLS)
3636 char cn[X509_CN_LENGTH];
37 #endif
3738 };
3839
3940 void
4041 kore_accesslog_init(void)
4142 {
42 if (socketpair(AF_UNIX, SOCK_STREAM, 0, accesslog_fd) == -1)
43 fatal("kore_accesslog_init(): socketpair() %s", errno_s);
4443 }
4544
4645 void
4746 kore_accesslog_worker_init(void)
4847 {
49 close(accesslog_fd[0]);
5048 kore_domain_closelogs();
5149 }
5250
5351 int
54 kore_accesslog_wait(void)
52 kore_accesslog_write(const void *data, u_int32_t len)
5553 {
56 ssize_t len;
54 int l;
5755 time_t now;
56 ssize_t sent;
5857 struct kore_domain *dom;
59 struct pollfd pfd[1];
60 int nfds, l;
6158 struct kore_log_packet logpacket;
6259 char addr[INET6_ADDRSTRLEN];
6360 char *method, *buf, *tbuf, *cn;
6461
65 pfd[0].fd = accesslog_fd[0];
66 pfd[0].events = POLLIN;
67 pfd[0].revents = 0;
62 if (len != sizeof(struct kore_log_packet))
63 return (KORE_RESULT_ERROR);
6864
69 nfds = poll(pfd, 1, 1000);
70 if (nfds == -1 || (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) {
71 if (nfds == -1 && errno == EINTR)
72 return (KORE_RESULT_OK);
73 kore_log(LOG_WARNING, "poll(): %s", errno_s);
74 return (KORE_RESULT_ERROR);
75 }
76
77 if (nfds == 0)
78 return (KORE_RESULT_OK);
79
80 len = recv(accesslog_fd[0], &logpacket, sizeof(logpacket), 0);
81 if (len == -1) {
82 kore_log(LOG_WARNING, "recv(): %s", errno_s);
83 return (KORE_RESULT_ERROR);
84 }
85
86 if (len != sizeof(logpacket))
87 return (KORE_RESULT_ERROR);
65 (void)memcpy(&logpacket, data, sizeof(logpacket));
8866
8967 if ((dom = kore_domain_lookup(logpacket.host)) == NULL) {
9068 kore_log(LOG_WARNING,
11492 break;
11593 }
11694
95 cn = "none";
96 #if !defined(KORE_NO_TLS)
11797 if (logpacket.cn[0] != '\0')
11898 cn = logpacket.cn;
119 else
120 cn = "none";
99 #endif
121100
122101 if (inet_ntop(logpacket.addrtype, &(logpacket.addr),
123102 addr, sizeof(addr)) == NULL)
124 kore_strlcpy(addr, "unknown", sizeof(addr));
103 (void)kore_strlcpy(addr, "unknown", sizeof(addr));
125104
126105 time(&now);
127106 tbuf = kore_time_to_date(now);
130109 logpacket.worker_id, logpacket.time_req, cn, logpacket.agent);
131110 if (l == -1) {
132111 kore_log(LOG_WARNING,
133 "kore_accesslog_wait(): asprintf() == -1");
112 "kore_accesslog_write(): asprintf() == -1");
134113 return (KORE_RESULT_ERROR);
135114 }
136115
137 len = write(dom->accesslog, buf, l);
138 if (len == -1) {
116 sent = write(dom->accesslog, buf, l);
117 if (sent == -1) {
139118 free(buf);
140119 kore_log(LOG_WARNING,
141 "kore_accesslog_wait(): write(): %s", errno_s);
120 "kore_accesslog_write(): write(): %s", errno_s);
142121 return (KORE_RESULT_ERROR);
143122 }
144123
145 if (len != l)
124 if (sent != l)
146125 kore_log(LOG_NOTICE, "accesslog: %s", buf);
147126
148127 free(buf);
152131 void
153132 kore_accesslog(struct http_request *req)
154133 {
155 ssize_t len;
156134 struct kore_log_packet logpacket;
157135
158136 logpacket.addrtype = req->owner->addrtype;
171149 logpacket.worker_id = worker->id;
172150 logpacket.worker_cpu = worker->cpu;
173151 logpacket.time_req = req->total;
174 kore_strlcpy(logpacket.host, req->host, sizeof(logpacket.host));
175 kore_strlcpy(logpacket.path, req->path, sizeof(logpacket.path));
152
153 if (kore_strlcpy(logpacket.host,
154 req->host, sizeof(logpacket.host)) >= sizeof(logpacket.host))
155 kore_log(LOG_NOTICE, "kore_accesslog: host truncated");
156
157 if (kore_strlcpy(logpacket.path,
158 req->path, sizeof(logpacket.path)) >= sizeof(logpacket.path))
159 kore_log(LOG_NOTICE, "kore_accesslog: path truncated");
176160
177161 if (req->agent != NULL) {
178 kore_strlcpy(logpacket.agent,
179 req->agent, sizeof(logpacket.agent));
162 if (kore_strlcpy(logpacket.agent, req->agent,
163 sizeof(logpacket.agent)) >= sizeof(logpacket.agent))
164 kore_log(LOG_NOTICE, "kore_accesslog: agent truncated");
180165 } else {
181 kore_strlcpy(logpacket.agent, "unknown",
166 (void)kore_strlcpy(logpacket.agent, "unknown",
182167 sizeof(logpacket.agent));
183168 }
184169
170 #if !defined(KORE_NO_TLS)
185171 memset(logpacket.cn, '\0', sizeof(logpacket.cn));
186 #if !defined(KORE_BENCHMARK)
187172 if (req->owner->cert != NULL) {
188173 if (X509_GET_CN(req->owner->cert,
189174 logpacket.cn, sizeof(logpacket.cn)) == -1) {
192177 }
193178 #endif
194179
195 len = send(accesslog_fd[1], &logpacket, sizeof(logpacket), 0);
196 if (len == -1) {
197 kore_log(LOG_WARNING, "kore_accesslog(): send(): %s", errno_s);
198 } else if (len != sizeof(logpacket)) {
199 kore_log(LOG_WARNING, "short accesslog packet sent");
200 }
180 kore_msg_send(KORE_MSG_PARENT,
181 KORE_MSG_ACCESSLOG, &logpacket, sizeof(logpacket));
201182 }
7676
7777 switch (r) {
7878 case KORE_RESULT_OK:
79 req->flags |= HTTP_REQUEST_AUTHED;
7980 kore_debug("kore_auth_run() for %s successful", req->path);
8081 /* FALLTHROUGH */
8182 case KORE_RESULT_RETRY:
108109 size_t len, slen;
109110 char *value, *c, *cookie, *cookies[HTTP_MAX_COOKIES];
110111
111 if (!http_request_header(req, "cookie", &cookie))
112 if (!http_request_header(req, "cookie", &c))
112113 return (KORE_RESULT_ERROR);
114
115 cookie = kore_strdup(c);
113116
114117 slen = strlen(auth->value);
115118 v = kore_split_string(cookie, ";", cookies, HTTP_MAX_COOKIES);
123126 }
124127
125128 if (i == v) {
126 kore_mem_free(cookie);
129 kore_free(cookie);
127130 return (KORE_RESULT_ERROR);
128131 }
129132
130133 c = cookies[i];
131134 if ((value = strchr(c, '=')) == NULL) {
132 kore_mem_free(cookie);
135 kore_free(cookie);
133136 return (KORE_RESULT_ERROR);
134137 }
135138
136139 i = kore_validator_check(req, auth->validator, ++value);
137 kore_mem_free(cookie);
140 kore_free(cookie);
138141
139142 return (i);
140143 }
142145 static int
143146 kore_auth_header(struct http_request *req, struct kore_auth *auth)
144147 {
145 int r;
146148 char *header;
147149
148150 if (!http_request_header(req, auth->value, &header))
149151 return (KORE_RESULT_ERROR);
150152
151 r = kore_validator_check(req, auth->validator, header);
152 kore_mem_free(header);
153
154 return (r);
153 return (kore_validator_check(req, auth->validator, header));
155154 }
156155
157156 static int
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
2121 #include <sys/cpuset.h>
2222 #endif
2323
24 #include <errno.h>
25 #include <string.h>
26
2427 #include "kore.h"
2528
2629 #if defined(KORE_USE_PGSQL)
8184 event_count = (worker_max_connections * 2) + nlisteners;
8285 events = kore_calloc(event_count, sizeof(struct kevent));
8386
84 LIST_FOREACH(l, &listeners, list) {
85 kore_platform_event_schedule(l->fd,
86 EVFILT_READ, EV_ADD | EV_DISABLE, l);
87 /* Hack to check if we're running under the parent or not. */
88 if (worker != NULL) {
89 LIST_FOREACH(l, &listeners, list) {
90 kore_platform_event_schedule(l->fd,
91 EVFILT_READ, EV_ADD | EV_DISABLE, l);
92 }
93 }
94 }
95
96 void
97 kore_platform_event_cleanup(void)
98 {
99 if (kfd != -1) {
100 close(kfd);
101 kfd = -1;
102 }
103
104 if (events != NULL) {
105 kore_free(events);
106 events = NULL;
87107 }
88108 }
89109
172192 !(c->flags & CONN_WRITE_BLOCK))
173193 c->flags |= CONN_WRITE_POSSIBLE;
174194
175 if (!kore_connection_handle(c)) {
195 if (c->handle != NULL && !c->handle(c))
176196 kore_connection_disconnect(c);
177 } else {
178 if (!TAILQ_EMPTY(&(c->send_queue))) {
179 kore_platform_event_schedule(c->fd,
180 EVFILT_WRITE, EV_ADD | EV_ONESHOT,
181 c);
182 }
183 }
184197 break;
185198 #if defined(KORE_USE_PGSQL)
186199 case KORE_TYPE_PGSQL_CONN:
203216 void
204217 kore_platform_event_all(int fd, void *c)
205218 {
206 kore_platform_event_schedule(fd, EVFILT_READ, EV_ADD, c);
207 kore_platform_event_schedule(fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, c);
219 kore_platform_event_schedule(fd, EVFILT_READ, EV_ADD | EV_CLEAR, c);
220 kore_platform_event_schedule(fd, EVFILT_WRITE, EV_ADD | EV_CLEAR, c);
208221 }
209222
210223 void
242255 }
243256
244257 void
258 kore_platform_schedule_write(int fd, void *data)
259 {
260 kore_platform_event_schedule(fd, EVFILT_WRITE, EV_ADD, data);
261 }
262
263 void
245264 kore_platform_disable_read(int fd)
246265 {
247266 kore_platform_event_schedule(fd, EVFILT_READ, EV_DELETE, NULL);
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1313 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414 */
1515
16 #include <string.h>
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include <stdlib.h>
20
1621 #include "kore.h"
1722
1823 struct kore_buf *
19 kore_buf_create(u_int32_t initial)
24 kore_buf_alloc(size_t initial)
2025 {
2126 struct kore_buf *buf;
2227
2328 buf = kore_malloc(sizeof(*buf));
24 buf->data = kore_malloc(initial);
25 buf->length = initial;
26 buf->offset = 0;
29 kore_buf_init(buf, initial);
30 buf->flags = KORE_BUF_OWNER_API;
2731
2832 return (buf);
2933 }
3034
3135 void
32 kore_buf_append(struct kore_buf *buf, void *d, u_int32_t len)
36 kore_buf_init(struct kore_buf *buf, size_t initial)
3337 {
34 if ((buf->offset + len) >= buf->length) {
35 buf->length += len + KORE_BUF_INCREMENT;
38 if (initial > 0)
39 buf->data = kore_malloc(initial);
40 else
41 buf->data = NULL;
42
43 buf->length = initial;
44 buf->offset = 0;
45 buf->flags = 0;
46 }
47
48 void
49 kore_buf_cleanup(struct kore_buf *buf)
50 {
51 kore_free(buf->data);
52 buf->data = NULL;
53 buf->offset = 0;
54 buf->length = 0;
55 }
56
57 void
58 kore_buf_free(struct kore_buf *buf)
59 {
60 kore_buf_cleanup(buf);
61 if (buf->flags & KORE_BUF_OWNER_API)
62 kore_free(buf);
63 }
64
65 void
66 kore_buf_append(struct kore_buf *buf, const void *d, size_t len)
67 {
68 if ((buf->offset + len) < len)
69 fatal("overflow in kore_buf_append");
70
71 if ((buf->offset + len) > buf->length) {
72 buf->length += len;
3673 buf->data = kore_realloc(buf->data, buf->length);
3774 }
3875
3976 memcpy((buf->data + buf->offset), d, len);
4077 buf->offset += len;
41 }
42
43 void
44 kore_buf_appendb(struct kore_buf *buf, struct kore_buf *src)
45 {
46 u_int8_t *d;
47 u_int32_t len;
48
49 d = kore_buf_release(src, &len);
50 kore_buf_append(buf, d, len);
51 kore_mem_free(d);
5278 }
5379
5480 void
6995 b = sb;
7096 }
7197
72 kore_buf_append(buf, (u_int8_t *)b, l);
98 kore_buf_append(buf, b, l);
7399 if (b != sb)
74100 free(b);
75101 }
84110 va_end(args);
85111 }
86112
113 char *
114 kore_buf_stringify(struct kore_buf *buf, size_t *len)
115 {
116 char c;
117
118 if (len != NULL)
119 *len = buf->offset;
120
121 c = '\0';
122 kore_buf_append(buf, &c, sizeof(c));
123
124 return ((char *)buf->data);
125 }
126
87127 u_int8_t *
88 kore_buf_release(struct kore_buf *buf, u_int32_t *len)
128 kore_buf_release(struct kore_buf *buf, size_t *len)
89129 {
90130 u_int8_t *p;
91131
92132 p = buf->data;
93133 *len = buf->offset;
94 kore_mem_free(buf);
134
135 buf->data = NULL;
136 kore_buf_free(buf);
95137
96138 return (p);
97139 }
98140
99141 void
100 kore_buf_free(struct kore_buf *buf)
101 {
102 kore_mem_free(buf->data);
103 kore_mem_free(buf);
104 }
105
106 void
107142 kore_buf_replace_string(struct kore_buf *b, char *src, void *dst, size_t len)
108143 {
109 u_int32_t blen, off, off2;
110 size_t nlen, klen;
111144 char *key, *end, *tmp, *p;
145 size_t blen, off, off2, nlen, klen;
112146
113147 off = 0;
114148 klen = strlen(src);
131165 memcpy((tmp + off), dst, len);
132166 memcpy((tmp + off + len), end, off2);
133167
134 kore_mem_free(b->data);
168 kore_free(b->data);
135169 b->data = (u_int8_t *)tmp;
136170 b->offset = off + len + off2;
137171 b->length = nlen;
139173 off = off + len;
140174 }
141175 }
176
177 void
178 kore_buf_reset(struct kore_buf *buf)
179 {
180 buf->offset = 0;
181 }
1919 #include <sys/queue.h>
2020 #include <sys/wait.h>
2121 #include <sys/mman.h>
22 #include <sys/time.h>
2223
2324 #include <openssl/pem.h>
2425 #include <openssl/x509v3.h>
3940
4041 #include "kore.h"
4142
42 #if defined(OpenBSD) || defined(__FreeBSD_version)
43 #if defined(OpenBSD) || defined(__FreeBSD_version) || \
44 defined(NetBSD) || defined(__DragonFly_version)
4345 #define PRI_TIME_T "d"
4446 #endif
4547
46 #if defined(linux)
48 #if defined(__linux__)
4749 #if defined(__x86_64__)
4850 #define PRI_TIME_T PRIu64
4951 #else
5557 #define PRI_TIME_T "ld"
5658 #endif
5759
58 #define LD_FLAGS_MAX 10
60 #define LD_FLAGS_MAX 30
61 #define CFLAGS_MAX 30
62 #define CXXFLAGS_MAX CFLAGS_MAX
63
64 #define BUILD_NOBUILD 0
65 #define BUILD_C 1
66 #define BUILD_CXX 2
67
68 struct buildopt {
69 char *name;
70 char *kore_source;
71 char *kore_flavor;
72 int single_binary;
73 struct kore_buf *cflags;
74 struct kore_buf *cxxflags;
75 struct kore_buf *ldflags;
76 TAILQ_ENTRY(buildopt) list;
77 };
78
79 TAILQ_HEAD(buildopt_list, buildopt);
5980
6081 struct cmd {
6182 const char *name;
7091 struct cfile {
7192 struct stat st;
7293 int build;
73 int cpp;
7494 char *name;
7595 char *fpath;
7696 char *opath;
80100 TAILQ_HEAD(cfile_list, cfile);
81101
82102 static void cli_fatal(const char *, ...) __attribute__((noreturn));
83
84103 static void cli_file_close(int);
85 static void cli_run_kore(void *);
104 static void cli_run_kore(void);
86105 static void cli_generate_certs(void);
87106 static void cli_link_library(void *);
88 static void cli_compile_cfile(void *);
107 static void cli_compile_kore(void *);
108 static void cli_compile_source_file(void *);
89109 static void cli_mkdir(const char *, int);
90110 static int cli_dir_exists(const char *);
91111 static int cli_file_exists(const char *);
92112 static void cli_cleanup_files(const char *);
113 static void cli_build_cflags(struct buildopt *);
114 static void cli_build_cxxflags(struct buildopt *);
115 static void cli_build_ldflags(struct buildopt *);
93116 static void cli_file_writef(int, const char *, ...);
94117 static void cli_file_open(const char *, int, int *);
95118 static void cli_file_remove(char *, struct dirent *);
98121 static int cli_vasprintf(char **, const char *, ...);
99122 static void cli_spawn_proc(void (*cb)(void *), void *);
100123 static void cli_write_asset(const char *, const char *);
101 static void cli_register_cfile(char *, struct dirent *);
124 static void cli_register_kore_file(char *, struct dirent *);
125 static void cli_register_source_file(char *, struct dirent *);
102126 static void cli_file_create(const char *, const char *, size_t);
103127 static int cli_file_requires_build(struct stat *, const char *);
104128 static void cli_find_files(const char *,
105129 void (*cb)(char *, struct dirent *));
106 static void cli_add_cfile(char *, char *, char *,
107 struct stat *, int, int);
130 static void cli_add_source_file(char *, char *, char *,
131 struct stat *, int);
132
133 static struct buildopt *cli_buildopt_default(void);
134 static struct buildopt *cli_buildopt_new(const char *);
135 static struct buildopt *cli_buildopt_find(const char *);
136 static void cli_buildopt_cleanup(void);
137 static void cli_buildopt_parse(const char *);
138 static void cli_buildopt_cflags(struct buildopt *, const char *);
139 static void cli_buildopt_cxxflags(struct buildopt *, const char *);
140 static void cli_buildopt_ldflags(struct buildopt *, const char *);
141 static void cli_buildopt_single_binary(struct buildopt *,
142 const char *);
143 static void cli_buildopt_kore_source(struct buildopt *,
144 const char *);
145 static void cli_buildopt_kore_flavor(struct buildopt *,
146 const char *);
147
148 static void cli_flavor_load(void);
149 static void cli_flavor_change(const char *);
108150
109151 static void cli_run(int, char **);
110152 static void cli_help(int, char **);
111153 static void cli_build(int, char **);
112154 static void cli_clean(int, char **);
113155 static void cli_create(int, char **);
156 static void cli_flavor(int, char **);
114157
115158 static void file_create_src(void);
116159 static void file_create_config(void);
122165 { "build", "build an application", cli_build },
123166 { "clean", "cleanup the build files", cli_clean },
124167 { "create", "create a new application skeleton", cli_create },
168 { "flavor", "switch build flavor", cli_flavor },
125169 { NULL, NULL, NULL }
126170 };
127171
134178
135179 static const char *gen_dirs[] = {
136180 "src",
137 #if !defined(KORE_BENCHMARK)
181 #if !defined(KORE_NO_TLS)
138182 "cert",
139183 #endif
140184 "conf",
156200 "}\n";
157201
158202 static const char *config_data =
159 "# Placeholder configuration\n"
203 "# %s configuration\n"
160204 "\n"
161205 "bind\t\t127.0.0.1 8888\n"
162206 "load\t\t./%s.so\n"
163 #if !defined(KORE_BENCHMARK)
207 #if !defined(KORE_NO_TLS)
164208 "tls_dhparam\tdh2048.pem\n"
165209 #endif
166210 "\n"
167 "domain 127.0.0.1 {\n"
168 #if !defined(KORE_BENCHMARK)
211 "domain * {\n"
212 #if !defined(KORE_NO_TLS)
169213 "\tcertfile\tcert/server.crt\n"
170214 "\tcertkey\t\tcert/server.key\n"
171215 #endif
172216 "\tstatic\t/\tpage\n"
173217 "}\n";
174218
175 #if !defined(KORE_BENCHMARK)
219 static const char *build_data =
220 "# %s build config\n"
221 "# You can switch flavors using: kore flavor [newflavor]\n"
222 "\n"
223 "# Set to yes if you wish to produce a single binary instead\n"
224 "# of a dynamic library. If you set this to yes you must also\n"
225 "# set kore_source together with kore_flavor and update ldflags\n"
226 "# to include the appropriate libraries you will be linking with.\n"
227 "#single_binary=no\n"
228 "#kore_source=/home/joris/src/kore\n"
229 "#kore_flavor=\n"
230 "\n"
231 "# The flags below are shared between flavors\n"
232 "cflags=-Wall -Wmissing-declarations -Wshadow\n"
233 "cflags=-Wstrict-prototypes -Wmissing-prototypes\n"
234 "cflags=-Wpointer-arith -Wcast-qual -Wsign-compare\n"
235 "\n"
236 "cxxflags=-Wall -Wmissing-declarations -Wshadow\n"
237 "cxxflags=-Wpointer-arith -Wcast-qual -Wsign-compare\n"
238 "\n"
239 "dev {\n"
240 " # These flags are added to the shared ones when\n"
241 " # you build the \"dev\" flavor.\n"
242 " cflags=-g\n"
243 " cxxflags=-g\n"
244 "}\n"
245 "\n"
246 "#prod {\n"
247 "# You can specify additional flags here which are only\n"
248 "# included if you build with the \"prod\" flavor.\n"
249 "#}\n";
250
251 #if !defined(KORE_NO_TLS)
176252 static const char *dh2048_data =
177253 "-----BEGIN DH PARAMETERS-----\n"
178254 "MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv\n"
184260 "-----END DH PARAMETERS-----";
185261 #endif
186262
187 static const char *gitignore_data = "*.o\n.objs\n%s.so\nassets.h\ncert\n";
263 static const char *gitignore = "*.o\n.flavor\n.objs\n%s.so\nassets.h\ncert\n";
188264
189265 static int s_fd = -1;
190266 static char *appl = NULL;
267 static int run_after = 0;
191268 static char *rootdir = NULL;
192 static char *compiler = "gcc";
269 static char *compiler_c = "gcc";
270 static char *compiler_cpp = "g++";
271 static char *compiler_ld = "gcc";
193272 static struct cfile_list source_files;
194 static int cfiles_count;
273 static struct buildopt_list build_options;
274 static int source_files_count;
275 static int cxx_files_count;
195276 static struct cmd *command = NULL;
277 static int cflags_count = 0;
278 static int cxxflags_count = 0;
279 static int ldflags_count = 0;
280 static char *flavor = NULL;
281 static char *cflags[CFLAGS_MAX];
282 static char *cxxflags[CXXFLAGS_MAX];
283 static char *ldflags[LD_FLAGS_MAX];
196284
197285 void
198286 kore_cli_usage(int local)
225313 kore_cli_usage(1);
226314
227315 (void)umask(S_IWGRP|S_IWOTH);
316
317 if ((flavor = strchr(argv[0], ':')) != NULL)
318 *(flavor)++ = '\0';
228319
229320 for (i = 0; cmds[i].name != NULL; i++) {
230321 if (!strcmp(argv[0], cmds[i].name)) {
274365
275366 cli_generate_certs();
276367
277 printf("%s created succesfully!\n", appl);
278
279 #if !defined(KORE_BENCHMARK)
368 printf("%s created successfully!\n", appl);
369
370 #if !defined(KORE_NO_TLS)
280371 printf("note: do NOT use the created DH parameters/certificates in production\n");
281372 #endif
282373 }
283374
284375 static void
376 cli_flavor(int argc, char **argv)
377 {
378 struct buildopt *bopt;
379 char pwd[MAXPATHLEN], *conf;
380
381 if (getcwd(pwd, sizeof(pwd)) == NULL)
382 cli_fatal("could not get cwd: %s", errno_s);
383
384 appl = basename(pwd);
385 (void)cli_vasprintf(&conf, "conf/%s.conf", appl);
386 if (!cli_dir_exists("conf") || !cli_file_exists(conf))
387 cli_fatal("%s doesn't appear to be a kore app", appl);
388 free(conf);
389
390 TAILQ_INIT(&build_options);
391 (void)cli_buildopt_new("_default");
392 cli_buildopt_parse("conf/build.conf");
393
394 if (argc == 0) {
395 cli_flavor_load();
396 TAILQ_FOREACH(bopt, &build_options, list) {
397 if (!strcmp(bopt->name, "_default"))
398 continue;
399 if (!strcmp(bopt->name, flavor)) {
400 printf("* %s\n", bopt->name);
401 } else {
402 printf(" %s\n", bopt->name);
403 }
404 }
405 } else {
406 cli_flavor_change(argv[0]);
407 printf("changed build flavor to: %s\n", argv[0]);
408 }
409
410 cli_buildopt_cleanup();
411 }
412
413 static void
285414 cli_build(int argc, char **argv)
286415 {
287 struct cfile *cf;
288 struct timeval times[2];
289 int requires_relink;
290 char pwd[PATH_MAX], *src_path, *assets_header;
291 char *assets_path, *p, *obj_path, *cpath, *config;
292
293 if (argc == 0) {
294 if (getcwd(pwd, sizeof(pwd)) == NULL)
295 cli_fatal("could not get cwd: %s", errno_s);
296
297 rootdir = ".";
298 appl = basename(pwd);
299 } else {
300 appl = argv[0];
301 rootdir = appl;
302 }
416 struct dirent dp;
417 struct cfile *cf;
418 struct buildopt *bopt;
419 struct timeval times[2];
420 char *build_path;
421 int requires_relink, l;
422 char *sofile, *config, *data;
423 char *assets_path, *p, *obj_path, *cpath;
424 char pwd[PATH_MAX], *src_path, *assets_header;
425
426 if (getcwd(pwd, sizeof(pwd)) == NULL)
427 cli_fatal("could not get cwd: %s", errno_s);
428
429 rootdir = ".";
430 appl = basename(pwd);
303431
304432 if ((p = getenv("CC")) != NULL)
305 compiler = p;
306
307 cfiles_count = 0;
433 compiler_c = p;
434
435 if ((p = getenv("CXX")) != NULL)
436 compiler_cpp = p;
437
438 source_files_count = 0;
439 cxx_files_count = 0;
308440 TAILQ_INIT(&source_files);
441 TAILQ_INIT(&build_options);
309442
310443 (void)cli_vasprintf(&src_path, "%s/src", rootdir);
311444 (void)cli_vasprintf(&assets_path, "%s/assets", rootdir);
312445 (void)cli_vasprintf(&config, "%s/conf/%s.conf", rootdir, appl);
313446 (void)cli_vasprintf(&assets_header, "%s/src/assets.h", rootdir);
447 (void)cli_vasprintf(&build_path, "%s/conf/build.conf", rootdir);
448
314449 if (!cli_dir_exists(src_path) || !cli_file_exists(config))
315450 cli_fatal("%s doesn't appear to be a kore app", appl);
316451
317 free(config);
452 cli_flavor_load();
453 bopt = cli_buildopt_new("_default");
454 if (!cli_file_exists(build_path)) {
455 l = cli_vasprintf(&data, build_data, appl);
456 cli_file_create("conf/build.conf", data, l);
457 free(data);
458 }
459
460 cli_find_files(src_path, cli_register_source_file);
461 free(src_path);
462
463 cli_buildopt_parse(build_path);
464 free(build_path);
318465
319466 (void)cli_vasprintf(&obj_path, "%s/.objs", rootdir);
320467 if (!cli_dir_exists(obj_path))
321468 cli_mkdir(obj_path, 0755);
322469 free(obj_path);
323470
471 if (bopt->single_binary) {
472 if (bopt->kore_source == NULL)
473 cli_fatal("single_binary set but not kore_source");
474
475 printf("building kore (%s)\n", bopt->kore_source);
476 cli_spawn_proc(cli_compile_kore, bopt);
477
478 (void)cli_vasprintf(&src_path, "%s/src", bopt->kore_source);
479 cli_find_files(src_path, cli_register_kore_file);
480 free(src_path);
481 }
482
483 printf("building %s (%s)\n", appl, flavor);
484
485 cli_build_cflags(bopt);
486 cli_build_cxxflags(bopt);
487 cli_build_ldflags(bopt);
488
324489 (void)unlink(assets_header);
325490
326491 /* Generate the assets. */
327 if (cli_dir_exists(assets_path)) {
328 cli_file_open(assets_header,
329 O_CREAT | O_TRUNC | O_WRONLY, &s_fd);
330
331 cli_file_writef(s_fd, "#ifndef __H_KORE_ASSETS_H\n");
332 cli_file_writef(s_fd, "#define __H_KORE_ASSETS_H\n");
492 cli_file_open(assets_header, O_CREAT | O_TRUNC | O_WRONLY, &s_fd);
493 cli_file_writef(s_fd, "#ifndef __H_KORE_ASSETS_H\n");
494 cli_file_writef(s_fd, "#define __H_KORE_ASSETS_H\n");
495
496 if (cli_dir_exists(assets_path))
333497 cli_find_files(assets_path, cli_build_asset);
334 cli_file_writef(s_fd, "\n#endif\n");
335 cli_file_close(s_fd);
336 }
498
499 if (bopt->single_binary) {
500 memset(&dp, 0, sizeof(dp));
501 dp.d_type = DT_REG;
502 printf("adding config %s\n", config);
503 (void)snprintf(dp.d_name,
504 sizeof(dp.d_name), "builtin_kore.conf");
505 cli_build_asset(config, &dp);
506 }
507
508 cli_file_writef(s_fd, "\n#endif\n");
509 cli_file_close(s_fd);
337510
338511 free(assets_path);
339
340 /* Build all source files. */
341 cli_find_files(src_path, cli_register_cfile);
342
343 free(src_path);
512 free(config);
513
514 if (cxx_files_count > 0)
515 compiler_ld = compiler_cpp;
516
344517 requires_relink = 0;
345
346518 TAILQ_FOREACH(cf, &source_files, list) {
347 if (cf->build == 0)
519 if (cf->build == BUILD_NOBUILD)
348520 continue;
349521
350522 printf("compiling %s\n", cf->name);
351 cli_spawn_proc(cli_compile_cfile, cf);
523 cli_spawn_proc(cli_compile_source_file, cf);
352524
353525 times[0].tv_usec = 0;
354526 times[0].tv_sec = cf->st.st_mtime;
370542 }
371543 free(cpath);
372544
545 if (bopt->single_binary) {
546 requires_relink++;
547 (void)cli_vasprintf(&sofile, "%s", appl);
548 } else {
549 (void)cli_vasprintf(&sofile, "%s.so", appl);
550 }
551
552 if (!cli_file_exists(sofile))
553 requires_relink++;
554 free(sofile);
555
373556 if (requires_relink) {
374 cli_spawn_proc(cli_link_library, NULL);
375 printf("%s built succesfully!\n", appl);
557 cli_spawn_proc(cli_link_library, bopt);
558 printf("%s built successfully!\n", appl);
376559 } else {
377 printf("nothing to be done\n");
378 }
560 printf("nothing to be done!\n");
561 }
562
563 if (run_after == 0)
564 cli_buildopt_cleanup();
379565 }
380566
381567 static void
400586 static void
401587 cli_run(int argc, char **argv)
402588 {
589 run_after = 1;
403590 cli_build(argc, argv);
404591
405592 if (chdir(rootdir) == -1)
409596 * We are exec()'ing kore again, while we could technically set
410597 * the right cli options manually and just continue running.
411598 */
412 cli_run_kore(NULL);
599 cli_run_kore();
413600 }
414601
415602 static void
429616 char *name, *data;
430617
431618 (void)cli_vasprintf(&name, "conf/%s.conf", appl);
432 l = cli_vasprintf(&data, config_data, appl);
619 l = cli_vasprintf(&data, config_data, appl, appl);
433620 cli_file_create(name, data, l);
434
435621 free(name);
436622 free(data);
623
624 l = cli_vasprintf(&data, build_data, appl);
625 cli_file_create("conf/build.conf", data, l);
626 free(data);
437627 }
438628
439629 static void
442632 int l;
443633 char *data;
444634
445 l = cli_vasprintf(&data, gitignore_data, appl);
635 l = cli_vasprintf(&data, gitignore, appl);
446636 cli_file_create(".gitignore", data, l);
447637 free(data);
448638 }
599789 if (stat(fpath, &st) == -1)
600790 cli_fatal("stat: %s %s", fpath, errno_s);
601791
792 /* If this file was empty, skip it. */
793 if (st.st_size == 0) {
794 printf("skipping empty asset %s\n", name);
795 return;
796 }
797
602798 (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, name);
603799 (void)cli_vasprintf(&cpath, "%s/.objs/%s.c", rootdir, name);
604800
607803 *(ext)++ = '\0';
608804 cli_write_asset(name, ext);
609805 *ext = '_';
610
611 cli_add_cfile(name, cpath, opath, &st, 0, 0);
612 kore_mem_free(name);
806
807 cli_add_source_file(name, cpath, opath, &st, BUILD_NOBUILD);
808 kore_free(name);
613809 return;
614810 }
615811
630826
631827 /* Start generating the file. */
632828 cli_file_writef(out, "/* Auto generated */\n");
633 cli_file_writef(out, "#include <sys/param.h>\n\n");
829 cli_file_writef(out, "#include <sys/types.h>\n\n");
634830
635831 /* Write the file data as a byte array. */
636832 cli_file_writef(out, "u_int8_t asset_%s_%s[] = {\n", name, ext);
667863 *--ext = '.';
668864
669865 /* Register the .c file now (cpath is free'd later). */
670 cli_add_cfile(name, cpath, opath, &st, 1, 0);
671 kore_mem_free(name);
672 }
673
674 static void
675 cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st,
676 int build, int cpp)
866 cli_add_source_file(name, cpath, opath, &st, BUILD_C);
867 kore_free(name);
868 }
869
870 static void
871 cli_add_source_file(char *name, char *fpath, char *opath, struct stat *st,
872 int build)
677873 {
678874 struct cfile *cf;
679875
680 cfiles_count++;
876 source_files_count++;
681877 cf = kore_malloc(sizeof(*cf));
682878
683879 cf->st = *st;
684880 cf->build = build;
685 cf->cpp = cpp;
686881 cf->fpath = fpath;
687882 cf->opath = opath;
688883 cf->name = kore_strdup(name);
691886 }
692887
693888 static void
694 cli_register_cfile(char *fpath, struct dirent *dp)
889 cli_register_source_file(char *fpath, struct dirent *dp)
695890 {
696891 struct stat st;
697892 char *ext, *opath;
698 int cpp;
893 int build;
699894
700895 if ((ext = strrchr(fpath, '.')) == NULL ||
701896 (strcmp(ext, ".c") && strcmp(ext, ".cpp")))
702897 return;
703898
704 if (!strcmp(ext, ".cpp"))
705 cpp = 1;
706 else
707 cpp = 0;
708
709899 if (stat(fpath, &st) == -1)
710900 cli_fatal("stat(%s): %s", fpath, errno_s);
711901
902 if (!strcmp(ext, ".cpp"))
903 cxx_files_count++;
904
712905 (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, dp->d_name);
713906 if (!cli_file_requires_build(&st, opath)) {
714 cli_add_cfile(dp->d_name, fpath, opath, &st, 0, cpp);
907 build = BUILD_NOBUILD;
908 } else if (!strcmp(ext, ".cpp")) {
909 build = BUILD_CXX;
910 } else {
911 build = BUILD_C;
912 }
913
914 cli_add_source_file(dp->d_name, fpath, opath, &st, build);
915 }
916
917 static void
918 cli_register_kore_file(char *fpath, struct dirent *dp)
919 {
920 struct stat st, ost;
921 char *opath, *ext, *fname;
922
923 if ((ext = strrchr(fpath, '.')) == NULL || strcmp(ext, ".c"))
715924 return;
716 }
717
718 cli_add_cfile(dp->d_name, fpath, opath, &st, 1, cpp);
925
926 if (stat(fpath, &st) == -1)
927 cli_fatal("stat(%s): %s", fpath, errno_s);
928
929 *ext = '\0';
930 if ((fname = basename(fpath)) == NULL)
931 cli_fatal("basename failed");
932
933 (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, fname);
934
935 /* Silently ignore non existing object files for kore source files. */
936 if (stat(opath, &ost) == -1) {
937 free(opath);
938 return;
939 }
940
941 cli_add_source_file(dp->d_name, fpath, opath, &st, BUILD_NOBUILD);
719942 }
720943
721944 static void
765988 static void
766989 cli_generate_certs(void)
767990 {
768 #if !defined(KORE_BENCHMARK)
991 #if !defined(KORE_NO_TLS)
769992 BIGNUM *e;
770993 FILE *fp;
771994 time_t now;
8651088 }
8661089
8671090 static void
868 cli_compile_cfile(void *arg)
869 {
870 int idx;
1091 cli_compile_source_file(void *arg)
1092 {
1093 int idx, i;
8711094 struct cfile *cf = arg;
872 char *args[24], *ipath[2], *p, *cppstandard;
873 #if defined(KORE_USE_PGSQL)
874 char *ppath;
875 #endif
876
877 (void)cli_vasprintf(&ipath[0], "-I%s/src", rootdir);
878 (void)cli_vasprintf(&ipath[1], "-I%s/src/includes", rootdir);
879
880 /*
881 * These compiler options should be settable
882 * somehow by the user if they so choose.
883 */
1095 char *args[32 + CFLAGS_MAX];
1096 char *compiler;
1097 char **flags;
1098 int flags_count;
1099
1100 switch (cf->build) {
1101 case BUILD_C:
1102 compiler = compiler_c;
1103 flags = cflags;
1104 flags_count = cflags_count;
1105 break;
1106 case BUILD_CXX:
1107 compiler = compiler_cpp;
1108 flags = cxxflags;
1109 flags_count = cxxflags_count;
1110 break;
1111 default:
1112 cli_fatal("cli_compile_file: unexpected file type: %d",
1113 cf->build);
1114 break;
1115 }
1116
8841117 idx = 0;
8851118 args[idx++] = compiler;
886 args[idx++] = ipath[0];
887 args[idx++] = ipath[1];
888 #if defined(PREFIX)
889 (void)cli_vasprintf(&args[idx++], "-I%s/include", PREFIX);
890 #else
891 args[idx++] = "-I/usr/local/include";
892 #endif
893
894 #if defined(KORE_USE_PGSQL)
895 (void)cli_vasprintf(&ppath, "-I%s", PGSQL_INCLUDE_PATH);
896 args[idx++] = ppath;
897 #endif
898
899 args[idx++] = "-Wall";
900 args[idx++] = "-Wmissing-declarations";
901 args[idx++] = "-Wshadow";
902 args[idx++] = "-Wpointer-arith";
903 args[idx++] = "-Wcast-qual";
904 args[idx++] = "-Wsign-compare";
905 args[idx++] = "-fPIC";
906 args[idx++] = "-g";
907
908 if (cf->cpp) {
909 args[idx++] = "-Woverloaded-virtual";
910 args[idx++] = "-Wold-style-cast";
911 args[idx++] = "-Wnon-virtual-dtor";
912
913 if ((p = getenv("CXXSTD")) != NULL) {
914 (void)cli_vasprintf(&cppstandard, "-std=%s", p);
915 args[idx++] = cppstandard;
916 }
917 } else {
918 args[idx++] = "-Wstrict-prototypes";
919 args[idx++] = "-Wmissing-prototypes";
920 }
1119
1120 for (i = 0; i < flags_count; i++)
1121 args[idx++] = flags[i];
9211122
9221123 args[idx++] = "-c";
9231124 args[idx++] = cf->fpath;
9261127 args[idx] = NULL;
9271128
9281129 execvp(compiler, args);
1130 cli_fatal("failed to start '%s': %s", compiler, errno_s);
9291131 }
9301132
9311133 static void
9321134 cli_link_library(void *arg)
9331135 {
9341136 struct cfile *cf;
935 int idx, f, i, has_cpp;
936 char *args[cfiles_count + 11 + LD_FLAGS_MAX];
937 char *p, *libname, *flags[LD_FLAGS_MAX], *cpplib;
938
939 if ((p = getenv("LDFLAGS")) != NULL)
940 f = kore_split_string(p, " ", flags, LD_FLAGS_MAX);
1137 struct buildopt *bopt;
1138 int idx, i;
1139 char *output;
1140 char *args[source_files_count + 11 + LD_FLAGS_MAX];
1141
1142 bopt = arg;
1143
1144 if (bopt->single_binary)
1145 (void)cli_vasprintf(&output, "%s/%s", rootdir, appl);
9411146 else
942 f = 0;
943
944 (void)cli_vasprintf(&libname, "%s/%s.so", rootdir, appl);
1147 (void)cli_vasprintf(&output, "%s/%s.so", rootdir, appl);
9451148
9461149 idx = 0;
947 args[idx++] = compiler;
948
1150 args[idx++] = compiler_ld;
1151
1152 TAILQ_FOREACH(cf, &source_files, list)
1153 args[idx++] = cf->opath;
1154
1155 for (i = 0; i < ldflags_count; i++)
1156 args[idx++] = ldflags[i];
1157
1158 if (bopt->single_binary) {
1159 args[idx++] = "-rdynamic";
1160 #if defined(__linux__)
1161 args[idx++] = "-ldl";
1162 #endif
1163 }
1164
1165 args[idx++] = "-o";
1166 args[idx++] = output;
1167 args[idx] = NULL;
1168
1169 execvp(compiler_ld, args);
1170 cli_fatal("failed to start '%s': %s", compiler_ld, errno_s);
1171 }
1172
1173 static void
1174 cli_compile_kore(void *arg)
1175 {
1176 struct buildopt *bopt = arg;
1177 int idx, i, fcnt;
1178 char *obj, *args[16], pwd[MAXPATHLEN], *flavors[7];
1179
1180 if (getcwd(pwd, sizeof(pwd)) == NULL)
1181 cli_fatal("could not get cwd: %s", errno_s);
1182
1183 (void)cli_vasprintf(&obj, "OBJDIR=%s/.objs", pwd);
1184
1185 if (putenv(obj) != 0)
1186 cli_fatal("cannot set OBJDIR for building kore");
1187
1188 if (putenv("CFLAGS=-DKORE_SINGLE_BINARY") != 0)
1189 cli_fatal("cannot set CFLAGS for building kore");
1190
1191 fcnt = kore_split_string(bopt->kore_flavor, " ", flavors, 7);
1192
1193 #if defined(OpenBSD) || defined(__FreeBSD_version) || \
1194 defined(NetBSD) || defined(__DragonFly_version)
1195 args[0] = "gmake";
1196 #else
1197 args[0] = "make";
1198 #endif
1199
1200 args[1] = "-s";
1201 args[2] = "-C";
1202 args[3] = bopt->kore_source;
1203 args[4] = "objects";
1204
1205 idx = 5;
1206 for (i = 0; i < fcnt; i++) {
1207 printf("using flavor %s\n", flavors[i]);
1208 args[idx++] = flavors[i];
1209 }
1210
1211 args[idx] = NULL;
1212
1213 execvp(args[0], args);
1214 cli_fatal("failed to start '%s': %s", args[0], errno_s);
1215 }
1216
1217 static void
1218 cli_run_kore(void)
1219 {
1220 struct buildopt *bopt;
1221 char *args[4], *cpath, *cmd, *flags;
1222
1223 bopt = cli_buildopt_default();
1224
1225 if (bopt->single_binary) {
1226 cpath = NULL;
1227 flags = "-fnr";
1228 (void)cli_vasprintf(&cmd, "./%s", appl);
1229 } else {
1230 cmd = "kore";
1231 flags = "-fnrc";
1232 (void)cli_vasprintf(&cpath, "conf/%s.conf", appl);
1233 }
1234
1235 args[0] = cmd;
1236 args[1] = flags;
1237
1238 if (cpath != NULL) {
1239 args[2] = cpath;
1240 args[3] = NULL;
1241 } else {
1242 args[2] = NULL;
1243 }
1244
1245 execvp(args[0], args);
1246 cli_fatal("failed to start '%s': %s", args[0], errno_s);
1247 }
1248
1249 static void
1250 cli_buildopt_parse(const char *path)
1251 {
1252 FILE *fp;
1253 struct buildopt *bopt;
1254 char buf[BUFSIZ], *p, *t;
1255
1256 if ((fp = fopen(path, "r")) == NULL)
1257 cli_fatal("cli_buildopt_parse: fopen(%s): %s", path, errno_s);
1258
1259 bopt = NULL;
1260
1261 while ((p = kore_read_line(fp, buf, sizeof(buf))) != NULL) {
1262 if (strlen(p) == 0)
1263 continue;
1264
1265 if (bopt != NULL && !strcmp(p, "}")) {
1266 bopt = NULL;
1267 continue;
1268 }
1269
1270 if (bopt == NULL) {
1271 if ((t = strchr(p, '=')) != NULL)
1272 goto parse_option;
1273 if ((t = strchr(p, ' ')) == NULL)
1274 cli_fatal("unexpected '%s'", p);
1275 *(t)++ = '\0';
1276 if (strcmp(t, "{"))
1277 cli_fatal("expected '{', got '%s'", t);
1278 bopt = cli_buildopt_new(p);
1279 continue;
1280 }
1281
1282 if ((t = strchr(p, '=')) == NULL) {
1283 printf("bad buildopt line: '%s'\n", p);
1284 continue;
1285 }
1286
1287 parse_option:
1288 *(t)++ = '\0';
1289
1290 p = kore_text_trim(p, strlen(p));
1291 t = kore_text_trim(t, strlen(t));
1292
1293 if (!strcasecmp(p, "cflags")) {
1294 cli_buildopt_cflags(bopt, t);
1295 } else if (!strcasecmp(p, "cxxflags")) {
1296 cli_buildopt_cxxflags(bopt, t);
1297 } else if (!strcasecmp(p, "ldflags")) {
1298 cli_buildopt_ldflags(bopt, t);
1299 } else if (!strcasecmp(p, "single_binary")) {
1300 cli_buildopt_single_binary(bopt, t);
1301 } else if (!strcasecmp(p, "kore_source")) {
1302 cli_buildopt_kore_source(bopt, t);
1303 } else if (!strcasecmp(p, "kore_flavor")) {
1304 cli_buildopt_kore_flavor(bopt, t);
1305 } else {
1306 printf("ignoring unknown option '%s'\n", p);
1307 }
1308 }
1309 }
1310
1311 static struct buildopt *
1312 cli_buildopt_new(const char *name)
1313 {
1314 struct buildopt *bopt;
1315
1316 bopt = kore_malloc(sizeof(*bopt));
1317 bopt->cflags = NULL;
1318 bopt->cxxflags = NULL;
1319 bopt->ldflags = NULL;
1320 bopt->single_binary = 0;
1321 bopt->kore_source = NULL;
1322 bopt->kore_flavor = NULL;
1323 bopt->name = kore_strdup(name);
1324
1325 TAILQ_INSERT_TAIL(&build_options, bopt, list);
1326 return (bopt);
1327 }
1328
1329 static struct buildopt *
1330 cli_buildopt_find(const char *name)
1331 {
1332 struct buildopt *bopt;
1333
1334 TAILQ_FOREACH(bopt, &build_options, list) {
1335 if (!strcmp(bopt->name, name))
1336 return (bopt);
1337 }
1338
1339 return (NULL);
1340 }
1341
1342 static struct buildopt *
1343 cli_buildopt_default(void)
1344 {
1345 struct buildopt *bopt;
1346
1347 if ((bopt = cli_buildopt_find("_default")) == NULL)
1348 fatal("no _default buildopt options");
1349
1350 return (bopt);
1351 }
1352
1353 static void
1354 cli_buildopt_cleanup(void)
1355 {
1356 struct buildopt *bopt, *next;
1357
1358 for (bopt = TAILQ_FIRST(&build_options); bopt != NULL; bopt = next) {
1359 next = TAILQ_NEXT(bopt, list);
1360 TAILQ_REMOVE(&build_options, bopt, list);
1361
1362 if (bopt->cflags != NULL)
1363 kore_buf_free(bopt->cflags);
1364 if (bopt->cxxflags != NULL)
1365 kore_buf_free(bopt->cxxflags);
1366 if (bopt->ldflags != NULL)
1367 kore_buf_free(bopt->ldflags);
1368 if (bopt->kore_source != NULL)
1369 kore_free(bopt->kore_source);
1370 if (bopt->kore_flavor != NULL)
1371 kore_free(bopt->kore_flavor);
1372 kore_free(bopt);
1373 }
1374 }
1375
1376 static void
1377 cli_buildopt_cflags(struct buildopt *bopt, const char *string)
1378 {
1379 if (bopt == NULL)
1380 bopt = cli_buildopt_default();
1381
1382 if (bopt->cflags == NULL)
1383 bopt->cflags = kore_buf_alloc(128);
1384
1385 kore_buf_appendf(bopt->cflags, "%s ", string);
1386 }
1387
1388 static void
1389 cli_buildopt_cxxflags(struct buildopt *bopt, const char *string)
1390 {
1391 if (bopt == NULL)
1392 bopt = cli_buildopt_default();
1393
1394 if (bopt->cxxflags == NULL)
1395 bopt->cxxflags = kore_buf_alloc(128);
1396
1397 kore_buf_appendf(bopt->cxxflags, "%s ", string);
1398 }
1399
1400 static void
1401 cli_buildopt_ldflags(struct buildopt *bopt, const char *string)
1402 {
1403 if (bopt == NULL)
1404 bopt = cli_buildopt_default();
1405
1406 if (bopt->ldflags == NULL)
1407 bopt->ldflags = kore_buf_alloc(128);
1408
1409 kore_buf_appendf(bopt->ldflags, "%s ", string);
1410 }
1411
1412 static void
1413 cli_buildopt_single_binary(struct buildopt *bopt, const char *string)
1414 {
1415 if (bopt == NULL)
1416 bopt = cli_buildopt_default();
1417 else
1418 cli_fatal("single_binary only supported in global context");
1419
1420 if (!strcmp(string, "yes"))
1421 bopt->single_binary = 1;
1422 else
1423 bopt->single_binary = 0;
1424 }
1425
1426 static void
1427 cli_buildopt_kore_source(struct buildopt *bopt, const char *string)
1428 {
1429 if (bopt == NULL)
1430 bopt = cli_buildopt_default();
1431 else
1432 cli_fatal("kore_source only supported in global context");
1433
1434 if (bopt->kore_source != NULL)
1435 kore_free(bopt->kore_source);
1436
1437 bopt->kore_source = kore_strdup(string);
1438 }
1439
1440 static void
1441 cli_buildopt_kore_flavor(struct buildopt *bopt, const char *string)
1442 {
1443 if (bopt == NULL)
1444 bopt = cli_buildopt_default();
1445 else
1446 cli_fatal("kore_flavor only supported in global context");
1447
1448 if (bopt->kore_flavor != NULL)
1449 kore_free(bopt->kore_flavor);
1450
1451 bopt->kore_flavor = kore_strdup(string);
1452 }
1453
1454 static void
1455 cli_build_flags_common(struct kore_buf* buf)
1456 {
1457 kore_buf_appendf(buf,
1458 "-fPIC -I%s/src -I%s/src/includes ", rootdir, rootdir);
1459 #if defined(PREFIX)
1460 kore_buf_appendf(buf, "-I%s/include ", PREFIX);
1461 #else
1462 kore_buf_appendf(buf, "-I/usr/local/include ");
1463 #endif
9491464 #if defined(__MACH__)
950 args[idx++] = "-dynamiclib";
951 args[idx++] = "-undefined";
952 args[idx++] = "suppress";
953 args[idx++] = "-flat_namespace";
1465 /* Add default openssl include path from homebrew / ports under OSX. */
1466 kore_buf_appendf(buf, "-I/opt/local/include ");
1467 kore_buf_appendf(buf, "-I/usr/local/opt/openssl/include ");
1468 #endif
1469 #if defined(KORE_USE_PGSQL)
1470 kore_buf_appendf(buf, "-I%s ", PGSQL_INCLUDE_PATH);
1471 #endif
1472 #if defined(KORE_NO_HTTP)
1473 kore_buf_appendf(buf, "-DKORE_NO_HTTP ");
1474 #endif
1475 #if defined(KORE_NO_TLS)
1476 kore_buf_appendf(buf, "-DKORE_NO_TLS ");
1477 #endif
1478 }
1479
1480 static void
1481 cli_build_cflags(struct buildopt *bopt)
1482 {
1483 struct buildopt *obopt;
1484 char *string;
1485
1486 if ((obopt = cli_buildopt_find(flavor)) == NULL)
1487 cli_fatal("no such build flavor: %s", flavor);
1488
1489 if (bopt->cflags == NULL)
1490 bopt->cflags = kore_buf_alloc(128);
1491
1492 cli_build_flags_common(bopt->cflags);
1493
1494 if (obopt != NULL && obopt->cflags != NULL) {
1495 kore_buf_append(bopt->cflags, obopt->cflags->data,
1496 obopt->cflags->offset);
1497 }
1498
1499 if (bopt->single_binary)
1500 kore_buf_appendf(bopt->cflags, "-DKORE_SINGLE_BINARY");
1501
1502 string = kore_buf_stringify(bopt->cflags, NULL);
1503 printf("CFLAGS=%s\n", string);
1504 cflags_count = kore_split_string(string, " ", cflags, CFLAGS_MAX);
1505 }
1506
1507 static void
1508 cli_build_cxxflags(struct buildopt *bopt)
1509 {
1510 struct buildopt *obopt;
1511 char *string;
1512
1513 if ((obopt = cli_buildopt_find(flavor)) == NULL)
1514 cli_fatal("no such build flavor: %s", flavor);
1515
1516 if (bopt->cxxflags == NULL)
1517 bopt->cxxflags = kore_buf_alloc(128);
1518
1519 cli_build_flags_common(bopt->cxxflags);
1520
1521 if (obopt != NULL && obopt->cxxflags != NULL) {
1522 kore_buf_append(bopt->cxxflags, obopt->cxxflags->data,
1523 obopt->cxxflags->offset);
1524 }
1525
1526 string = kore_buf_stringify(bopt->cxxflags, NULL);
1527 if (cxx_files_count > 0)
1528 printf("CXXFLAGS=%s\n", string);
1529 cxxflags_count = kore_split_string(string, " ", cxxflags, CXXFLAGS_MAX);
1530 }
1531
1532 static void
1533 cli_build_ldflags(struct buildopt *bopt)
1534 {
1535 struct buildopt *obopt;
1536 char *string;
1537
1538 if ((obopt = cli_buildopt_find(flavor)) == NULL)
1539 cli_fatal("no such build flavor: %s", flavor);
1540
1541 if (bopt->ldflags == NULL)
1542 bopt->ldflags = kore_buf_alloc(128);
1543
1544 if (bopt->single_binary == 0) {
1545 #if defined(__MACH__)
1546 kore_buf_appendf(bopt->ldflags,
1547 "-dynamiclib -undefined suppress -flat_namespace ");
9541548 #else
955 args[idx++] = "-shared";
956 #endif
957
958 has_cpp = 0;
959 TAILQ_FOREACH(cf, &source_files, list) {
960 if (cf->cpp)
961 has_cpp = 1;
962 args[idx++] = cf->opath;
963 }
964
965 if (has_cpp) {
966 if ((p = getenv("CXXLIB")) != NULL) {
967 (void)cli_vasprintf(&cpplib, "-l%s", p);
968 args[idx++] = cpplib;
969 } else {
970 args[idx++] = "-lstdc++";
971 }
972 }
973
974 for (i = 0; i < f; i++)
975 args[idx++] = flags[i];
976
977 args[idx++] = "-o";
978 args[idx++] = libname;
979 args[idx] = NULL;
980
981 execvp(compiler, args);
982 }
983
984 static void
985 cli_run_kore(void *arg)
986 {
987 char *args[4], *cpath;
988
989 (void)cli_vasprintf(&cpath, "conf/%s.conf", appl);
990
991 args[0] = "kore";
992 args[1] = "-fnrc";
993 args[2] = cpath;
994 args[3] = NULL;
995
996 execvp("kore", args);
1549 kore_buf_appendf(bopt->ldflags, "-shared ");
1550 #endif
1551 }
1552
1553 if (obopt != NULL && obopt->ldflags != NULL) {
1554 kore_buf_append(bopt->ldflags, obopt->ldflags->data,
1555 obopt->ldflags->offset);
1556 }
1557
1558 string = kore_buf_stringify(bopt->ldflags, NULL);
1559 printf("LDFLAGS=%s\n", string);
1560 ldflags_count = kore_split_string(string, " ", ldflags, LD_FLAGS_MAX);
1561 }
1562
1563 static void
1564 cli_flavor_load(void)
1565 {
1566 FILE *fp;
1567 char buf[BUFSIZ], pwd[MAXPATHLEN], *p, *conf;
1568
1569 if (getcwd(pwd, sizeof(pwd)) == NULL)
1570 cli_fatal("could not get cwd: %s", errno_s);
1571
1572 appl = basename(pwd);
1573 if (appl == NULL)
1574 cli_fatal("basename: %s", errno_s);
1575 appl = kore_strdup(appl);
1576 (void)cli_vasprintf(&conf, "conf/%s.conf", appl);
1577
1578 if (!cli_dir_exists("conf") || !cli_file_exists(conf))
1579 cli_fatal("%s doesn't appear to be a kore app", appl);
1580 free(conf);
1581
1582 if ((fp = fopen(".flavor", "r")) == NULL) {
1583 flavor = kore_strdup("dev");
1584 return;
1585 }
1586
1587 if (fgets(buf, sizeof(buf), fp) == NULL)
1588 cli_fatal("failed to read flavor from file");
1589
1590 if ((p = strchr(buf, '\n')) != NULL)
1591 *p = '\0';
1592
1593 flavor = kore_strdup(buf);
1594 (void)fclose(fp);
1595 }
1596
1597 static void
1598 cli_flavor_change(const char *name)
1599 {
1600 FILE *fp;
1601 int ret;
1602 struct buildopt *bopt;
1603
1604 if ((bopt = cli_buildopt_find(name)) == NULL)
1605 cli_fatal("no such flavor: %s", name);
1606
1607 if ((fp = fopen(".flavor.tmp", "w")) == NULL)
1608 cli_fatal("failed to open temporary file to save flavor");
1609
1610 ret = fprintf(fp, "%s\n", name);
1611 if (ret == -1 || (size_t)ret != (strlen(name) + 1))
1612 cli_fatal("failed to write new build flavor");
1613
1614 (void)fclose(fp);
1615
1616 if (rename(".flavor.tmp", ".flavor") == -1)
1617 cli_fatal("failed to replace build flavor");
1618
1619 cli_clean(0, NULL);
9971620 }
9981621
9991622 static void
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1313 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414 */
1515
16 #include <sys/param.h>
1617 #include <sys/stat.h>
1718
19 #include <stdio.h>
20 #include <string.h>
1821 #include <ctype.h>
1922 #include <limits.h>
2023 #include <fcntl.h>
2730 #include "pgsql.h"
2831 #endif
2932
33 #if defined(KORE_USE_TASKS)
34 #include "tasks.h"
35 #endif
36
3037 /* XXX - This is becoming a clusterfuck. Fix it. */
3138
32 static int configure_include(char **);
33 static int configure_bind(char **);
34 static int configure_load(char **);
35 static int configure_handler(char **);
36 static int configure_domain(char **);
37 static int configure_chroot(char **);
38 static int configure_runas(char **);
39 static int configure_workers(char **);
40 static int configure_pidfile(char **);
41 static int configure_accesslog(char **);
42 static int configure_certfile(char **);
43 static int configure_certkey(char **);
44 static int configure_rlimit_nofiles(char **);
45 static int configure_max_connections(char **);
46 static int configure_accept_threshold(char **);
47 static int configure_set_affinity(char **);
48 static int configure_tls_version(char **);
49 static int configure_tls_cipher(char **);
50 static int configure_tls_dhparam(char **);
51 static int configure_spdy_idle_time(char **);
52 static int configure_http_header_max(char **);
53 static int configure_http_body_max(char **);
54 static int configure_http_hsts_enable(char **);
55 static int configure_http_keepalive_time(char **);
56 static int configure_http_request_limit(char **);
57 static int configure_validator(char **);
58 static int configure_params(char **);
59 static int configure_validate(char **);
60 static int configure_client_certificates(char **);
61 static int configure_authentication(char **);
62 static int configure_authentication_uri(char **);
63 static int configure_authentication_type(char **);
64 static int configure_authentication_value(char **);
65 static int configure_authentication_validator(char **);
66 static int configure_websocket_maxframe(char **);
67 static int configure_websocket_timeout(char **);
68 static int configure_socket_backlog(char **);
39 #if !defined(KORE_SINGLE_BINARY)
40 static int configure_load(char *);
41 #else
42 static FILE *config_file_write(void);
43 extern u_int8_t asset_builtin_kore_conf[];
44 extern u_int32_t asset_len_builtin_kore_conf;
45 #endif
46
47 static int configure_include(char *);
48 static int configure_bind(char *);
49 static int configure_domain(char *);
50 static int configure_chroot(char *);
51 static int configure_runas(char *);
52 static int configure_workers(char *);
53 static int configure_pidfile(char *);
54 static int configure_rlimit_nofiles(char *);
55 static int configure_max_connections(char *);
56 static int configure_accept_threshold(char *);
57 static int configure_set_affinity(char *);
58 static int configure_socket_backlog(char *);
59
60 #if !defined(KORE_NO_TLS)
61 static int configure_certfile(char *);
62 static int configure_certkey(char *);
63 static int configure_tls_version(char *);
64 static int configure_tls_cipher(char *);
65 static int configure_tls_dhparam(char *);
66 static int configure_client_certificates(char *);
67 #endif
68
69 #if !defined(KORE_NO_HTTP)
70 static int configure_handler(int, char *);
71 static int configure_static_handler(char *);
72 static int configure_dynamic_handler(char *);
73 static int configure_accesslog(char *);
74 static int configure_http_header_max(char *);
75 static int configure_http_body_max(char *);
76 static int configure_http_hsts_enable(char *);
77 static int configure_http_keepalive_time(char *);
78 static int configure_http_request_limit(char *);
79 static int configure_http_body_disk_offload(char *);
80 static int configure_http_body_disk_path(char *);
81 static int configure_validator(char *);
82 static int configure_params(char *);
83 static int configure_validate(char *);
84 static int configure_authentication(char *);
85 static int configure_authentication_uri(char *);
86 static int configure_authentication_type(char *);
87 static int configure_authentication_value(char *);
88 static int configure_authentication_validator(char *);
89 static int configure_websocket_maxframe(char *);
90 static int configure_websocket_timeout(char *);
91 #endif
6992
7093 #if defined(KORE_USE_PGSQL)
71 static int configure_pgsql_conn_max(char **);
94 static int configure_pgsql_conn_max(char *);
95 #endif
96
97 #if defined(KORE_USE_TASKS)
98 static int configure_task_threads(char *);
7299 #endif
73100
74101 static void domain_sslstart(void);
75 static void kore_parse_config_file(char *);
102 static void kore_parse_config_file(const char *);
76103
77104 static struct {
78105 const char *name;
79 int (*configure)(char **);
106 int (*configure)(char *);
80107 } config_names[] = {
81108 { "include", configure_include },
82109 { "bind", configure_bind },
110 #if !defined(KORE_SINGLE_BINARY)
83111 { "load", configure_load },
84 { "static", configure_handler },
85 { "dynamic", configure_handler },
86 { "tls_version", configure_tls_version },
87 { "tls_cipher", configure_tls_cipher },
88 { "tls_dhparam", configure_tls_dhparam },
89 { "spdy_idle_time", configure_spdy_idle_time },
112 #endif
90113 { "domain", configure_domain },
91114 { "chroot", configure_chroot },
92115 { "runas", configure_runas },
96119 { "worker_accept_threshold", configure_accept_threshold },
97120 { "worker_set_affinity", configure_set_affinity },
98121 { "pidfile", configure_pidfile },
99 { "accesslog", configure_accesslog },
122 { "socket_backlog", configure_socket_backlog },
123 #if !defined(KORE_NO_TLS)
124 { "tls_version", configure_tls_version },
125 { "tls_cipher", configure_tls_cipher },
126 { "tls_dhparam", configure_tls_dhparam },
100127 { "certfile", configure_certfile },
101128 { "certkey", configure_certkey },
102129 { "client_certificates", configure_client_certificates },
130 #endif
131 #if !defined(KORE_NO_HTTP)
132 { "static", configure_static_handler },
133 { "dynamic", configure_dynamic_handler },
134 { "accesslog", configure_accesslog },
103135 { "http_header_max", configure_http_header_max },
104136 { "http_body_max", configure_http_body_max },
105137 { "http_hsts_enable", configure_http_hsts_enable },
106138 { "http_keepalive_time", configure_http_keepalive_time },
107139 { "http_request_limit", configure_http_request_limit },
140 { "http_body_disk_offload", configure_http_body_disk_offload },
141 { "http_body_disk_path", configure_http_body_disk_path },
108142 { "validator", configure_validator },
109143 { "params", configure_params },
110144 { "validate", configure_validate },
115149 { "authentication_validator", configure_authentication_validator },
116150 { "websocket_maxframe", configure_websocket_maxframe },
117151 { "websocket_timeout", configure_websocket_timeout },
118 { "socket_backlog", configure_socket_backlog },
152 #endif
119153 #if defined(KORE_USE_PGSQL)
120154 { "pgsql_conn_max", configure_pgsql_conn_max },
121155 #endif
156 #if defined(KORE_USE_TASKS)
157 { "task_threads", configure_task_threads },
158 #endif
122159 { NULL, NULL },
123160 };
124161
162 #if !defined(KORE_SINGLE_BINARY)
125163 char *config_file = NULL;
164 #endif
165
166 #if !defined(KORE_NO_HTTP)
126167 static u_int8_t current_method = 0;
127168 static struct kore_auth *current_auth = NULL;
169 static struct kore_module_handle *current_handler = NULL;
170 #endif
171
172 extern const char *__progname;
128173 static struct kore_domain *current_domain = NULL;
129 static struct kore_module_handle *current_handler = NULL;
130174
131175 void
132176 kore_parse_config(void)
133177 {
178 #if !defined(KORE_SINGLE_BINARY)
134179 kore_parse_config_file(config_file);
180 #else
181 kore_parse_config_file(NULL);
182 #endif
135183
136184 if (!kore_module_loaded())
137 fatal("no site module was loaded");
138
139 if (LIST_EMPTY(&listeners))
140 fatal("no listeners defined");
185 fatal("no application module was loaded");
141186
142187 if (skip_chroot != 1 && chroot_path == NULL) {
143188 fatal("missing a chroot path");
148193 }
149194
150195 if (skip_runas != 1 && runas_user == NULL) {
151 fatal("missing runas user");
196 fatal("missing runas user, use -r to skip it");
152197 }
153198
154199 if (getuid() != 0 && skip_runas == 0) {
155 fatal("cannot drop privileges, use -p to skip it");
200 fatal("cannot drop privileges, use -r to skip it");
156201 }
157202 }
158203
159204 static void
160 kore_parse_config_file(char *fpath)
205 kore_parse_config_file(const char *fpath)
161206 {
162207 FILE *fp;
163208 int i, lineno;
164 char buf[BUFSIZ], *p, *t, *argv[5];
165
209 char buf[BUFSIZ], *p, *t;
210
211 #if !defined(KORE_SINGLE_BINARY)
166212 if ((fp = fopen(fpath, "r")) == NULL)
167213 fatal("configuration given cannot be opened: %s", fpath);
214 #else
215 fp = config_file_write();
216 #endif
168217
169218 kore_debug("parsing configuration file '%s'", fpath);
170219
171220 lineno = 1;
172 while (fgets(buf, sizeof(buf), fp) != NULL) {
173 p = buf;
174 buf[strcspn(buf, "\n")] = '\0';
175
176 while (isspace(*p))
177 p++;
178 if (p[0] == '#' || p[0] == '\0') {
221 while ((p = kore_read_line(fp, buf, sizeof(buf))) != NULL) {
222 if (strlen(p) == 0) {
179223 lineno++;
180224 continue;
181225 }
182226
183 for (t = p; *t != '\0'; t++) {
184 if (*t == '\t')
185 *t = ' ';
186 }
187
227 #if !defined(KORE_NO_HTTP)
188228 if (!strcmp(p, "}") && current_handler != NULL) {
189229 lineno++;
190230 current_handler = NULL;
201241 current_auth = NULL;
202242 continue;
203243 }
244 #endif
204245
205246 if (!strcmp(p, "}") && current_domain != NULL)
206247 domain_sslstart();
210251 continue;
211252 }
212253
213 kore_split_string(p, " ", argv, 5);
254 if ((t = strchr(p, ' ')) == NULL) {
255 printf("ignoring \"%s\" on line %d\n", p, lineno++);
256 continue;
257 }
258
259 *(t)++ = '\0';
260
261 p = kore_text_trim(p, strlen(p));
262 t = kore_text_trim(t, strlen(t));
263
264 if (strlen(p) == 0 || strlen(t) == 0) {
265 printf("ignoring \"%s\" on line %d\n", p, lineno++);
266 continue;
267 }
268
214269 for (i = 0; config_names[i].name != NULL; i++) {
215 if (!strcmp(config_names[i].name, argv[0])) {
216 if (!config_names[i].configure(argv)) {
217 fatal("configuration error on line %d",
218 lineno);
219 }
220 break;
270 if (!strcmp(config_names[i].name, p)) {
271 if (config_names[i].configure(t))
272 break;
273 fatal("configuration error on line %d", lineno);
274 /* NOTREACHED */
221275 }
222276 }
223277
224 if (config_names[i].name == NULL) {
225 printf("unknown configuration option \"%s\" on line %d\n", p,
226 lineno);
278 if (config_names[i].name == NULL)
279 printf("ignoring \"%s\" on line %d\n", p, lineno);
280 lineno++;
281 }
282
283 fclose(fp);
284 }
285
286 static int
287 configure_include(char *path)
288 {
289 kore_parse_config_file(path);
290 return (KORE_RESULT_OK);
291 }
292
293 static int
294 configure_bind(char *options)
295 {
296 char *argv[4];
297
298 kore_split_string(options, " ", argv, 4);
299 if (argv[0] == NULL || argv[1] == NULL)
300 return (KORE_RESULT_ERROR);
301
302 return (kore_server_bind(argv[0], argv[1], argv[2]));
303 }
304
305 #if !defined(KORE_SINGLE_BINARY)
306 static int
307 configure_load(char *options)
308 {
309 char *argv[3];
310
311 kore_split_string(options, " ", argv, 3);
312 if (argv[0] == NULL)
313 return (KORE_RESULT_ERROR);
314
315 kore_module_load(argv[0], argv[1]);
316 return (KORE_RESULT_OK);
317 }
318 #else
319 static FILE *
320 config_file_write(void)
321 {
322 FILE *fp;
323 ssize_t ret;
324 int fd, len;
325 char fpath[MAXPATHLEN];
326
327 len = snprintf(fpath, sizeof(fpath), "/tmp/%s.XXXXXX", __progname);
328 if (len == -1 || (size_t)len >= sizeof(fpath))
329 fatal("failed to create temporary path");
330
331 if ((fd = mkstemp(fpath)) == -1)
332 fatal("mkstemp(%s): %s", fpath, errno_s);
333
334 (void)unlink(fpath);
335
336 for (;;) {
337 ret = write(fd, asset_builtin_kore_conf,
338 asset_len_builtin_kore_conf);
339 if (ret == -1) {
340 if (errno == EINTR)
341 continue;
342 fatal("failed to write temporary config: %s", errno_s);
227343 }
228344
229 lineno++;
230 }
231
232 fclose(fp);
233 }
234
235 static int
236 configure_include(char **argv)
237 {
238 if (argv[1] == NULL) {
239 printf("No file given in include directive\n");
240 return (KORE_RESULT_ERROR);
241 }
242
243 kore_parse_config_file(argv[1]);
244 return (KORE_RESULT_OK);
245 }
246
247 static int
248 configure_bind(char **argv)
249 {
250 if (argv[1] == NULL || argv[2] == NULL)
251 return (KORE_RESULT_ERROR);
252
253 return (kore_server_bind(argv[1], argv[2]));
254 }
255
256 static int
257 configure_load(char **argv)
258 {
259 if (argv[1] == NULL)
260 return (KORE_RESULT_ERROR);
261
262 kore_module_load(argv[1], argv[2]);
263 return (KORE_RESULT_OK);
264 }
265
266 static int
267 configure_tls_version(char **argv)
268 {
269 if (argv[1] == NULL)
270 return (KORE_RESULT_ERROR);
271
272 if (!strcmp(argv[1], "1.2")) {
345 if ((size_t)ret != asset_len_builtin_kore_conf)
346 fatal("failed to write temporary config");
347 break;
348 }
349
350 if ((fp = fdopen(fd, "w+")) == NULL)
351 fatal("fdopen(): %s", errno_s);
352
353 rewind(fp);
354
355 return (fp);
356 }
357 #endif
358
359 #if !defined(KORE_NO_TLS)
360 static int
361 configure_tls_version(char *version)
362 {
363 if (!strcmp(version, "1.2")) {
273364 tls_version = KORE_TLS_VERSION_1_2;
274 } else if (!strcmp(argv[1], "1.0")) {
365 } else if (!strcmp(version, "1.0")) {
275366 tls_version = KORE_TLS_VERSION_1_0;
276 } else if (!strcmp(argv[1], "both")) {
367 } else if (!strcmp(version, "both")) {
277368 tls_version = KORE_TLS_VERSION_BOTH;
278369 } else {
279 printf("unknown value for tls_version: %s\n", argv[1]);
280 return (KORE_RESULT_ERROR);
281 }
282
283 return (KORE_RESULT_OK);
284 }
285
286 static int
287 configure_tls_cipher(char **argv)
288 {
289 if (argv[1] == NULL)
290 return (KORE_RESULT_ERROR);
291
370 printf("unknown value for tls_version: %s\n", version);
371 return (KORE_RESULT_ERROR);
372 }
373
374 return (KORE_RESULT_OK);
375 }
376
377 static int
378 configure_tls_cipher(char *cipherlist)
379 {
292380 if (strcmp(kore_tls_cipher_list, KORE_DEFAULT_CIPHER_LIST)) {
293 kore_debug("duplicate tls_cipher directive specified");
294 return (KORE_RESULT_ERROR);
295 }
296
297 kore_tls_cipher_list = kore_strdup(argv[1]);
298 return (KORE_RESULT_OK);
299 }
300
301 static int
302 configure_tls_dhparam(char **argv)
303 {
304 #if !defined(KORE_BENCHMARK)
381 printf("tls_cipher specified twice\n");
382 return (KORE_RESULT_ERROR);
383 }
384
385 kore_tls_cipher_list = kore_strdup(cipherlist);
386 return (KORE_RESULT_OK);
387 }
388
389 static int
390 configure_tls_dhparam(char *path)
391 {
305392 BIO *bio;
306393
307 if (argv[1] == NULL)
308 return (KORE_RESULT_ERROR);
309
310394 if (tls_dhparam != NULL) {
311 kore_debug("duplicate tls_dhparam directive specified");
312 return (KORE_RESULT_ERROR);
313 }
314
315 if ((bio = BIO_new_file(argv[1], "r")) == NULL) {
316 printf("%s did not exist\n", argv[1]);
395 printf("tls_dhparam specified twice\n");
396 return (KORE_RESULT_ERROR);
397 }
398
399 if ((bio = BIO_new_file(path, "r")) == NULL) {
400 printf("%s did not exist\n", path);
317401 return (KORE_RESULT_ERROR);
318402 }
319403
324408 printf("PEM_read_bio_DHparams(): %s\n", ssl_errno_s);
325409 return (KORE_RESULT_ERROR);
326410 }
327 #endif
328 return (KORE_RESULT_OK);
329 }
330
331 static int
332 configure_spdy_idle_time(char **argv)
333 {
334 int err;
335
336 if (argv[1] == NULL)
337 return (KORE_RESULT_ERROR);
338
339 spdy_idle_time = kore_strtonum(argv[1], 10, 0, 65535, &err);
340 if (err != KORE_RESULT_OK) {
341 printf("spdy_idle_time has invalid value: %s\n", argv[1]);
342 return (KORE_RESULT_ERROR);
343 }
344
345 spdy_idle_time = spdy_idle_time * 1000;
346 return (KORE_RESULT_OK);
347 }
348
349 static int
350 configure_domain(char **argv)
351 {
352 if (argv[2] == NULL)
353 return (KORE_RESULT_ERROR);
411
412 return (KORE_RESULT_OK);
413 }
414
415 static int
416 configure_client_certificates(char *options)
417 {
418 char *argv[3];
419
420 if (current_domain == NULL) {
421 printf("client_certificates not specified in domain context\n");
422 return (KORE_RESULT_ERROR);
423 }
424
425 kore_split_string(options, " ", argv, 3);
426 if (argv[0] == NULL) {
427 printf("client_certificate is missing a parameter\n");
428 return (KORE_RESULT_ERROR);
429 }
430
431 if (current_domain->cafile != NULL) {
432 printf("client_certificate already set for %s\n",
433 current_domain->domain);
434 return (KORE_RESULT_ERROR);
435 }
436
437 current_domain->cafile = kore_strdup(argv[0]);
438 if (argv[1] != NULL)
439 current_domain->crlfile = kore_strdup(argv[1]);
440
441 return (KORE_RESULT_OK);
442 }
443
444 static int
445 configure_certfile(char *path)
446 {
447 if (current_domain == NULL) {
448 printf("certfile not specified in domain context\n");
449 return (KORE_RESULT_ERROR);
450 }
451
452 if (current_domain->certfile != NULL) {
453 printf("certfile specified twice for %s\n",
454 current_domain->domain);
455 return (KORE_RESULT_ERROR);
456 }
457
458 current_domain->certfile = kore_strdup(path);
459 return (KORE_RESULT_OK);
460 }
461
462 static int
463 configure_certkey(char *path)
464 {
465 if (current_domain == NULL) {
466 printf("certkey not specified in domain text\n");
467 return (KORE_RESULT_ERROR);
468 }
469
470 if (current_domain->certkey != NULL) {
471 printf("certkey specified twice for %s\n",
472 current_domain->domain);
473 return (KORE_RESULT_ERROR);
474 }
475
476 current_domain->certkey = kore_strdup(path);
477 return (KORE_RESULT_OK);
478 }
479
480 #endif /* !KORE_NO_TLS */
481
482 static int
483 configure_domain(char *options)
484 {
485 char *argv[3];
354486
355487 if (current_domain != NULL) {
356 printf("previous domain configuration not closed\n");
357 return (KORE_RESULT_ERROR);
358 }
359
360 if (strcmp(argv[2], "{")) {
361 printf("missing { for domain directive\n");
362 return (KORE_RESULT_ERROR);
363 }
364
365 if (!kore_domain_new(argv[1])) {
366 printf("could not create new domain %s\n", argv[1]);
367 return (KORE_RESULT_ERROR);
368 }
369
370 current_domain = kore_domain_lookup(argv[1]);
371 return (KORE_RESULT_OK);
372 }
373
374 static int
375 configure_handler(char **argv)
376 {
377 int type;
488 printf("nested domain contexts are not allowed\n");
489 return (KORE_RESULT_ERROR);
490 }
491
492 kore_split_string(options, " ", argv, 3);
493
494 if (strcmp(argv[1], "{")) {
495 printf("domain context not opened correctly\n");
496 return (KORE_RESULT_ERROR);
497 }
498
499 if (strlen(argv[0]) >= KORE_DOMAINNAME_LEN - 1) {
500 printf("domain name '%s' too long\n", argv[0]);
501 return (KORE_RESULT_ERROR);
502 }
503
504 if (!kore_domain_new(argv[0])) {
505 printf("could not create new domain %s\n", argv[0]);
506 return (KORE_RESULT_ERROR);
507 }
508
509 current_domain = kore_domain_lookup(argv[0]);
510 return (KORE_RESULT_OK);
511 }
512
513 #if !defined(KORE_NO_HTTP)
514 static int
515 configure_static_handler(char *options)
516 {
517 return (configure_handler(HANDLER_TYPE_STATIC, options));
518 }
519
520 static int
521 configure_dynamic_handler(char *options)
522 {
523 return (configure_handler(HANDLER_TYPE_DYNAMIC, options));
524 }
525
526 static int
527 configure_handler(int type, char *options)
528 {
529 char *argv[4];
378530
379531 if (current_domain == NULL) {
380 printf("missing domain for page handler\n");
381 return (KORE_RESULT_ERROR);
382 }
383
384 if (argv[1] == NULL || argv[2] == NULL)
385 return (KORE_RESULT_ERROR);
386
387 if (!strcmp(argv[0], "static"))
388 type = HANDLER_TYPE_STATIC;
389 else if (!strcmp(argv[0], "dynamic"))
390 type = HANDLER_TYPE_DYNAMIC;
391 else
392 return (KORE_RESULT_ERROR);
393
394 if (!kore_module_handler_new(argv[1],
395 current_domain->domain, argv[2], argv[3], type)) {
396 kore_debug("cannot create handler for %s", argv[1]);
397 return (KORE_RESULT_ERROR);
398 }
399
400 return (KORE_RESULT_OK);
401 }
402
403 static int
404 configure_client_certificates(char **argv)
532 printf("page handler not specified in domain context\n");
533 return (KORE_RESULT_ERROR);
534 }
535
536 kore_split_string(options, " ", argv, 4);
537
538 if (argv[0] == NULL || argv[1] == NULL) {
539 printf("missing parameters for page handler\n");
540 return (KORE_RESULT_ERROR);
541 }
542
543 if (!kore_module_handler_new(argv[0],
544 current_domain->domain, argv[1], argv[2], type)) {
545 printf("cannot create handler for %s\n", argv[0]);
546 return (KORE_RESULT_ERROR);
547 }
548
549 return (KORE_RESULT_OK);
550 }
551
552 static int
553 configure_accesslog(char *path)
405554 {
406555 if (current_domain == NULL) {
407 printf("missing domain for require_client_cert\n");
408 return (KORE_RESULT_ERROR);
409 }
410
411 if (argv[1] == NULL) {
412 printf("missing argument for require_client_cert\n");
413 return (KORE_RESULT_ERROR);
414 }
415
416 if (current_domain->cafile != NULL) {
417 printf("require_client_cert already set for %s\n",
556 kore_debug("accesslog not specified in domain context\n");
557 return (KORE_RESULT_ERROR);
558 }
559
560 if (current_domain->accesslog != -1) {
561 printf("domain %s already has an open accesslog\n",
418562 current_domain->domain);
419563 return (KORE_RESULT_ERROR);
420564 }
421565
422 current_domain->cafile = kore_strdup(argv[1]);
423 if (argv[2] != NULL)
424 current_domain->crlfile = kore_strdup(argv[2]);
425
426 return (KORE_RESULT_OK);
427 }
428
429 static int
430 configure_chroot(char **argv)
431 {
432 if (chroot_path != NULL) {
433 kore_debug("duplicate chroot path specified");
434 return (KORE_RESULT_ERROR);
435 }
436
437 if (argv[1] == NULL)
438 return (KORE_RESULT_ERROR);
439
440 chroot_path = kore_strdup(argv[1]);
441 return (KORE_RESULT_OK);
442 }
443
444 static int
445 configure_runas(char **argv)
446 {
447 if (runas_user != NULL) {
448 kore_debug("duplicate runas user specified");
449 return (KORE_RESULT_ERROR);
450 }
451
452 if (argv[1] == NULL)
453 return (KORE_RESULT_ERROR);
454
455 runas_user = kore_strdup(argv[1]);
456 return (KORE_RESULT_OK);
457 }
458
459 static int
460 configure_workers(char **argv)
461 {
462 int err;
463
464 if (worker_count != 0) {
465 kore_debug("duplicate worker directive specified");
466 return (KORE_RESULT_ERROR);
467 }
468
469 if (argv[1] == NULL)
470 return (KORE_RESULT_ERROR);
471
472 worker_count = kore_strtonum(argv[1], 10, 1, 255, &err);
473 if (err != KORE_RESULT_OK) {
474 printf("%s is not a correct worker number\n", argv[1]);
475 return (KORE_RESULT_ERROR);
476 }
477
478 return (KORE_RESULT_OK);
479 }
480
481 static int
482 configure_pidfile(char **argv)
483 {
484 if (argv[1] == NULL)
485 return (KORE_RESULT_ERROR);
486
487 if (strcmp(kore_pidfile, KORE_PIDFILE_DEFAULT)) {
488 kore_debug("duplicate pidfile directive specified");
489 return (KORE_RESULT_ERROR);
490 }
491
492 kore_pidfile = kore_strdup(argv[1]);
493 return (KORE_RESULT_OK);
494 }
495
496 static int
497 configure_accesslog(char **argv)
498 {
499 if (argv[1] == NULL)
500 return (KORE_RESULT_ERROR);
501
502 if (current_domain == NULL) {
503 kore_debug("missing domain for accesslog");
504 return (KORE_RESULT_ERROR);
505 }
506
507 if (current_domain->accesslog != -1) {
508 kore_debug("domain %s already has an open accesslog",
509 current_domain->domain);
510 return (KORE_RESULT_ERROR);
511 }
512
513 current_domain->accesslog = open(argv[1],
566 current_domain->accesslog = open(path,
514567 O_CREAT | O_APPEND | O_WRONLY,
515568 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
516569 if (current_domain->accesslog == -1) {
517 kore_debug("open(%s): %s", argv[1], errno_s);
518 return (KORE_RESULT_ERROR);
519 }
520
521 return (KORE_RESULT_OK);
522 }
523
524 static int
525 configure_certfile(char **argv)
526 {
527 if (argv[1] == NULL)
528 return (KORE_RESULT_ERROR);
529
530 if (current_domain == NULL) {
531 printf("missing domain for certfile\n");
532 return (KORE_RESULT_ERROR);
533 }
534
535 if (current_domain->certfile != NULL) {
536 kore_debug("domain already has a certfile set");
537 return (KORE_RESULT_ERROR);
538 }
539
540 current_domain->certfile = kore_strdup(argv[1]);
541 return (KORE_RESULT_OK);
542 }
543
544 static int
545 configure_certkey(char **argv)
546 {
547 if (argv[1] == NULL)
548 return (KORE_RESULT_ERROR);
549
550 if (current_domain == NULL) {
551 printf("missing domain for certkey\n");
552 return (KORE_RESULT_ERROR);
553 }
554
555 if (current_domain->certkey != NULL) {
556 kore_debug("domain already has a certkey set");
557 return (KORE_RESULT_ERROR);
558 }
559
560 current_domain->certkey = kore_strdup(argv[1]);
561 return (KORE_RESULT_OK);
562 }
563
564 static int
565 configure_max_connections(char **argv)
566 {
567 int err;
568
569 if (argv[1] == NULL)
570 return (KORE_RESULT_ERROR);
571
572 worker_max_connections = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err);
573 if (err != KORE_RESULT_OK) {
574 printf("bad value for worker_max_connections: %s\n", argv[1]);
575 return (KORE_RESULT_ERROR);
576 }
577
578 return (KORE_RESULT_OK);
579 }
580
581 static int
582 configure_rlimit_nofiles(char **argv)
583 {
584 int err;
585
586 if (argv[1] == NULL)
587 return (KORE_RESULT_ERROR);
588
589 worker_rlimit_nofiles = kore_strtonum(argv[1], 10, 1, UINT_MAX, &err);
590 if (err != KORE_RESULT_OK) {
591 printf("bad value for worker_rlimit_nofiles: %s\n", argv[1]);
592 return (KORE_RESULT_ERROR);
593 }
594
595 return (KORE_RESULT_OK);
596 }
597
598 static int
599 configure_accept_threshold(char **argv)
600 {
601 int err;
602
603 if (argv[1] == NULL)
604 return (KORE_RESULT_ERROR);
605
606 worker_accept_threshold = kore_strtonum(argv[1], 0, 1, UINT_MAX, &err);
607 if (err != KORE_RESULT_OK) {
608 printf("bad value for worker_accept_threshold: %s\n", argv[1]);
609 return (KORE_RESULT_ERROR);
610 }
611
612 return (KORE_RESULT_OK);
613 }
614
615 static int
616 configure_set_affinity(char **argv)
617 {
618 int err;
619
620 if (argv[1] == NULL)
621 return (KORE_RESULT_ERROR);
622
623 worker_set_affinity = kore_strtonum(argv[1], 10, 0, 1, &err);
624 if (err != KORE_RESULT_OK) {
625 printf("bad value for worker_set_affinity: %s\n", argv[1]);
626 return (KORE_RESULT_ERROR);
627 }
628
629 return (KORE_RESULT_OK);
630 }
631
632 static int
633 configure_http_header_max(char **argv)
634 {
635 int err;
636
637 if (argv[1] == NULL)
638 return (KORE_RESULT_ERROR);
639
640 if (http_header_max != HTTP_HEADER_MAX_LEN) {
641 kore_debug("http_header_max already set");
642 return (KORE_RESULT_ERROR);
643 }
644
645 http_header_max = kore_strtonum(argv[1], 10, 1, 65535, &err);
646 if (err != KORE_RESULT_OK) {
647 printf("bad http_header_max value: %s\n", argv[1]);
648 return (KORE_RESULT_ERROR);
649 }
650
651 return (KORE_RESULT_OK);
652 }
653
654 static int
655 configure_http_body_max(char **argv)
656 {
657 int err;
658
659 if (argv[1] == NULL)
660 return (KORE_RESULT_ERROR);
661
662 if (http_body_max != HTTP_BODY_MAX_LEN) {
663 kore_debug("http_body_max already set");
664 return (KORE_RESULT_ERROR);
665 }
666
667 http_body_max = kore_strtonum(argv[1], 10, 1, LONG_MAX, &err);
668 if (err != KORE_RESULT_OK) {
669 printf("bad http_body_max value: %s\n", argv[1]);
670 return (KORE_RESULT_ERROR);
671 }
672
673 return (KORE_RESULT_OK);
674 }
675
676 static int
677 configure_http_hsts_enable(char **argv)
678 {
679 int err;
680
681 if (argv[1] == NULL)
682 return (KORE_RESULT_ERROR);
683
684 if (http_hsts_enable != HTTP_HSTS_ENABLE) {
685 kore_debug("http_hsts_enable already set");
686 return (KORE_RESULT_ERROR);
687 }
688
689 http_hsts_enable = kore_strtonum(argv[1], 10, 0, LONG_MAX, &err);
690 if (err != KORE_RESULT_OK) {
691 printf("bad http_hsts_enable value: %s\n", argv[1]);
692 return (KORE_RESULT_ERROR);
693 }
694
695 return (KORE_RESULT_OK);
696 }
697
698 static int
699 configure_http_keepalive_time(char **argv)
700 {
701 int err;
702
703 if (argv[1] == NULL)
704 return (KORE_RESULT_ERROR);
705
706 if (http_keepalive_time != HTTP_KEEPALIVE_TIME) {
707 kore_debug("http_keepalive_time already set");
708 return (KORE_RESULT_ERROR);
709 }
710
711 http_keepalive_time = kore_strtonum(argv[1], 10, 0, USHRT_MAX, &err);
712 if (err != KORE_RESULT_OK) {
713 printf("bad http_keepalive_time value: %s\n", argv[1]);
714 return (KORE_RESULT_ERROR);
715 }
716
717 return (KORE_RESULT_OK);
718 }
719
720 static int
721 configure_http_request_limit(char **argv)
722 {
723 int err;
724
725 if (argv[1] == NULL)
726 return (KORE_RESULT_ERROR);
727
728 http_request_limit = kore_strtonum(argv[1], 10, 0, UINT_MAX, &err);
729 if (err != KORE_RESULT_OK) {
730 printf("bad http_request_limit value: %s\n", argv[1]);
731 return (KORE_RESULT_ERROR);
732 }
733
734 return (KORE_RESULT_OK);
735 }
736
737 static int
738 configure_validator(char **argv)
570 printf("accesslog open(%s): %s\n", path, errno_s);
571 return (KORE_RESULT_ERROR);
572 }
573
574 return (KORE_RESULT_OK);
575 }
576
577 static int
578 configure_http_header_max(char *option)
579 {
580 int err;
581
582 http_header_max = kore_strtonum(option, 10, 1, 65535, &err);
583 if (err != KORE_RESULT_OK) {
584 printf("bad http_header_max value: %s\n", option);
585 return (KORE_RESULT_ERROR);
586 }
587
588 return (KORE_RESULT_OK);
589 }
590
591 static int
592 configure_http_body_max(char *option)
593 {
594 int err;
595
596 http_body_max = kore_strtonum(option, 10, 0, LONG_MAX, &err);
597 if (err != KORE_RESULT_OK) {
598 printf("bad http_body_max value: %s\n", option);
599 return (KORE_RESULT_ERROR);
600 }
601
602 return (KORE_RESULT_OK);
603 }
604
605 static int
606 configure_http_body_disk_offload(char *option)
607 {
608 int err;
609
610 http_body_disk_offload = kore_strtonum(option, 10, 0, LONG_MAX, &err);
611 if (err != KORE_RESULT_OK) {
612 printf("bad http_body_disk_offload value: %s\n", option);
613 return (KORE_RESULT_ERROR);
614 }
615
616 return (KORE_RESULT_OK);
617 }
618
619 static int
620 configure_http_body_disk_path(char *path)
621 {
622 if (strcmp(http_body_disk_path, HTTP_BODY_DISK_PATH))
623 kore_free(http_body_disk_path);
624
625 http_body_disk_path = kore_strdup(path);
626 return (KORE_RESULT_OK);
627 }
628
629 static int
630 configure_http_hsts_enable(char *option)
631 {
632 int err;
633
634 http_hsts_enable = kore_strtonum(option, 10, 0, LONG_MAX, &err);
635 if (err != KORE_RESULT_OK) {
636 printf("bad http_hsts_enable value: %s\n", option);
637 return (KORE_RESULT_ERROR);
638 }
639
640 return (KORE_RESULT_OK);
641 }
642
643 static int
644 configure_http_keepalive_time(char *option)
645 {
646 int err;
647
648 http_keepalive_time = kore_strtonum(option, 10, 0, USHRT_MAX, &err);
649 if (err != KORE_RESULT_OK) {
650 printf("bad http_keepalive_time value: %s\n", option);
651 return (KORE_RESULT_ERROR);
652 }
653
654 return (KORE_RESULT_OK);
655 }
656
657 static int
658 configure_http_request_limit(char *option)
659 {
660 int err;
661
662 http_request_limit = kore_strtonum(option, 10, 0, UINT_MAX, &err);
663 if (err != KORE_RESULT_OK) {
664 printf("bad http_request_limit value: %s\n", option);
665 return (KORE_RESULT_ERROR);
666 }
667
668 return (KORE_RESULT_OK);
669 }
670
671 static int
672 configure_validator(char *name)
739673 {
740674 u_int8_t type;
741
742 if (argv[3] == NULL)
743 return (KORE_RESULT_ERROR);
744
745 if (!strcmp(argv[2], "regex")) {
675 char *tname, *value;
676
677 if ((tname = strchr(name, ' ')) == NULL) {
678 printf("missing validator name\n");
679 return (KORE_RESULT_ERROR);
680 }
681
682 *(tname)++ = '\0';
683 tname = kore_text_trim(tname, strlen(tname));
684 if ((value = strchr(tname, ' ')) == NULL) {
685 printf("missing validator value\n");
686 return (KORE_RESULT_ERROR);
687 }
688
689 *(value)++ = '\0';
690 value = kore_text_trim(value, strlen(value));
691
692 if (!strcmp(tname, "regex")) {
746693 type = KORE_VALIDATOR_TYPE_REGEX;
747 } else if (!strcmp(argv[2], "function")) {
694 } else if (!strcmp(tname, "function")) {
748695 type = KORE_VALIDATOR_TYPE_FUNCTION;
749696 } else {
750 printf("bad type for validator %s\n", argv[1]);
751 return (KORE_RESULT_ERROR);
752 }
753
754 if (!kore_validator_add(argv[1], type, argv[3])) {
755 printf("bad validator specified: %s\n", argv[1]);
756 return (KORE_RESULT_ERROR);
757 }
758
759 return (KORE_RESULT_OK);
760 }
761
762 static int
763 configure_params(char **argv)
697 printf("bad type for validator %s\n", tname);
698 return (KORE_RESULT_ERROR);
699 }
700
701 if (!kore_validator_add(name, type, value)) {
702 printf("bad validator specified: %s\n", tname);
703 return (KORE_RESULT_ERROR);
704 }
705
706 return (KORE_RESULT_OK);
707 }
708
709 static int
710 configure_params(char *options)
764711 {
765712 struct kore_module_handle *hdlr;
713 char *argv[3];
766714
767715 if (current_domain == NULL) {
768 printf("params keyword used in wrong context\n");
716 printf("params not used in domain context\n");
769717 return (KORE_RESULT_ERROR);
770718 }
771719
774722 return (KORE_RESULT_ERROR);
775723 }
776724
777 if (argv[2] == NULL)
778 return (KORE_RESULT_ERROR);
779
780 if (!strcasecmp(argv[1], "post")) {
725 kore_split_string(options, " ", argv, 3);
726 if (argv[1] == NULL)
727 return (KORE_RESULT_ERROR);
728
729 if (!strcasecmp(argv[0], "post")) {
781730 current_method = HTTP_METHOD_POST;
782 } else if (!strcasecmp(argv[1], "get")) {
731 } else if (!strcasecmp(argv[0], "get")) {
783732 current_method = HTTP_METHOD_GET;
784 } else if (!strcasecmp(argv[1], "put")) {
733 } else if (!strcasecmp(argv[0], "put")) {
785734 current_method = HTTP_METHOD_PUT;
786 } else if (!strcasecmp(argv[1], "delete")) {
735 } else if (!strcasecmp(argv[0], "delete")) {
787736 current_method = HTTP_METHOD_DELETE;
788 } else if (!strcasecmp(argv[1], "head")) {
737 } else if (!strcasecmp(argv[0], "head")) {
789738 current_method = HTTP_METHOD_HEAD;
790739 } else {
791740 printf("unknown method: %s in params block for %s\n",
792 argv[1], argv[2]);
741 argv[0], argv[1]);
793742 return (KORE_RESULT_ERROR);
794743 }
795744
798747 * in case of a dynamic page.
799748 */
800749 TAILQ_FOREACH(hdlr, &(current_domain->handlers), list) {
801 if (!strcmp(hdlr->path, argv[2])) {
750 if (!strcmp(hdlr->path, argv[1])) {
802751 current_handler = hdlr;
803752 return (KORE_RESULT_OK);
804753 }
805754 }
806755
807 printf("params for unknown page handler: %s\n", argv[2]);
756 printf("params for unknown page handler: %s\n", argv[1]);
808757 return (KORE_RESULT_ERROR);
809758 }
810759
811760 static int
812 configure_validate(char **argv)
761 configure_validate(char *options)
813762 {
814763 struct kore_handler_params *p;
815764 struct kore_validator *val;
765 char *argv[3];
816766
817767 if (current_handler == NULL) {
818 printf("validate keyword used in wrong context\n");
819 return (KORE_RESULT_ERROR);
820 }
821
822 if (argv[2] == NULL)
823 return (KORE_RESULT_ERROR);
824
825 if ((val = kore_validator_lookup(argv[2])) == NULL) {
826 printf("unknown validator %s for %s\n", argv[2], argv[1]);
768 printf("validate not used in domain context\n");
769 return (KORE_RESULT_ERROR);
770 }
771
772 kore_split_string(options, " ", argv, 3);
773 if (argv[1] == NULL)
774 return (KORE_RESULT_ERROR);
775
776 if ((val = kore_validator_lookup(argv[1])) == NULL) {
777 printf("unknown validator %s for %s\n", argv[1], argv[0]);
827778 return (KORE_RESULT_ERROR);
828779 }
829780
830781 p = kore_malloc(sizeof(*p));
831782 p->validator = val;
832783 p->method = current_method;
833 p->name = kore_strdup(argv[1]);
784 p->name = kore_strdup(argv[0]);
834785
835786 TAILQ_INSERT_TAIL(&(current_handler->params), p, list);
836
837 return (KORE_RESULT_OK);
838 }
839
840 static int
841 configure_authentication(char **argv)
842 {
843 if (argv[2] == NULL) {
844 printf("Missing name for authentication block\n");
845 return (KORE_RESULT_ERROR);
846 }
787 return (KORE_RESULT_OK);
788 }
789
790 static int
791 configure_authentication(char *options)
792 {
793 char *argv[3];
847794
848795 if (current_auth != NULL) {
849 printf("Previous authentication block not closed\n");
850 return (KORE_RESULT_ERROR);
851 }
852
853 if (strcmp(argv[2], "{")) {
796 printf("previous authentication block not closed\n");
797 return (KORE_RESULT_ERROR);
798 }
799
800 kore_split_string(options, " ", argv, 3);
801 if (argv[1] == NULL) {
802 printf("missing name for authentication block\n");
803 return (KORE_RESULT_ERROR);
804 }
805
806 if (strcmp(argv[1], "{")) {
854807 printf("missing { for authentication block\n");
855808 return (KORE_RESULT_ERROR);
856809 }
857810
858 if (!kore_auth_new(argv[1]))
859 return (KORE_RESULT_ERROR);
860
861 current_auth = kore_auth_lookup(argv[1]);
862
863 return (KORE_RESULT_OK);
864 }
865
866 static int
867 configure_authentication_type(char **argv)
811 if (!kore_auth_new(argv[0]))
812 return (KORE_RESULT_ERROR);
813
814 current_auth = kore_auth_lookup(argv[0]);
815
816 return (KORE_RESULT_OK);
817 }
818
819 static int
820 configure_authentication_type(char *option)
868821 {
869822 if (current_auth == NULL) {
870 printf("authentication_type outside authentication block\n");
871 return (KORE_RESULT_ERROR);
872 }
873
874 if (argv[1] == NULL) {
875 printf("missing parameter for authentication_type\n");
876 return (KORE_RESULT_ERROR);
877 }
878
879 if (!strcmp(argv[1], "cookie")) {
823 printf("authentication_type outside authentication context\n");
824 return (KORE_RESULT_ERROR);
825 }
826
827 if (!strcmp(option, "cookie")) {
880828 current_auth->type = KORE_AUTH_TYPE_COOKIE;
881 } else if (!strcmp(argv[1], "header")) {
829 } else if (!strcmp(option, "header")) {
882830 current_auth->type = KORE_AUTH_TYPE_HEADER;
883 } else if (!strcmp(argv[1], "request")) {
831 } else if (!strcmp(option, "request")) {
884832 current_auth->type = KORE_AUTH_TYPE_REQUEST;
885833 } else {
886 printf("unknown authentication type '%s'\n", argv[1]);
887 return (KORE_RESULT_ERROR);
888 }
889
890 return (KORE_RESULT_OK);
891 }
892
893 static int
894 configure_authentication_value(char **argv)
834 printf("unknown authentication type '%s'\n", option);
835 return (KORE_RESULT_ERROR);
836 }
837
838 return (KORE_RESULT_OK);
839 }
840
841 static int
842 configure_authentication_value(char *option)
895843 {
896844 if (current_auth == NULL) {
897 printf("authentication_value outside authentication block\n");
898 return (KORE_RESULT_ERROR);
899 }
900
901 if (argv[1] == NULL) {
902 printf("missing parameter for authentication_value\n");
903 return (KORE_RESULT_ERROR);
904 }
905
906 if (current_auth->value != NULL) {
907 printf("duplicate authentication_value found\n");
908 return (KORE_RESULT_ERROR);
909 }
910
911 current_auth->value = kore_strdup(argv[1]);
912 return (KORE_RESULT_OK);
913 }
914
915 static int
916 configure_authentication_validator(char **argv)
845 printf("authentication_value outside authentication context\n");
846 return (KORE_RESULT_ERROR);
847 }
848
849 if (current_auth->value != NULL)
850 kore_free(current_auth->value);
851 current_auth->value = kore_strdup(option);
852
853 return (KORE_RESULT_OK);
854 }
855
856 static int
857 configure_authentication_validator(char *validator)
917858 {
918859 struct kore_validator *val;
919860
922863 return (KORE_RESULT_ERROR);
923864 }
924865
925 if (argv[1] == NULL) {
926 printf("missing parameter for authentication_validator\n");
927 return (KORE_RESULT_ERROR);
928 }
929
930 if (current_auth->validator != NULL) {
931 printf("duplicate authentication_validator found\n");
932 return (KORE_RESULT_ERROR);
933 }
934
935 if ((val = kore_validator_lookup(argv[1])) == NULL) {
936 printf("authentication validator '%s' not found\n", argv[1]);
866 if ((val = kore_validator_lookup(validator)) == NULL) {
867 printf("authentication validator '%s' not found\n", validator);
937868 return (KORE_RESULT_ERROR);
938869 }
939870
943874 }
944875
945876 static int
946 configure_authentication_uri(char **argv)
877 configure_authentication_uri(char *uri)
947878 {
948879 if (current_auth == NULL) {
949 printf("authentication_uri outside authentication block\n");
950 return (KORE_RESULT_ERROR);
951 }
952
953 if (argv[1] == NULL) {
954 printf("missing parameter for authentication_uri\n");
955 return (KORE_RESULT_ERROR);
956 }
957
958 if (current_auth->redirect != NULL) {
959 printf("duplicate authentication_uri found\n");
960 return (KORE_RESULT_ERROR);
961 }
962
963 current_auth->redirect = kore_strdup(argv[1]);
964
965 return (KORE_RESULT_OK);
966 }
967
968 static int
969 configure_websocket_maxframe(char **argv)
880 printf("authentication_uri outside authentication context\n");
881 return (KORE_RESULT_ERROR);
882 }
883
884 if (current_auth->redirect != NULL)
885 kore_free(current_auth->redirect);
886 current_auth->redirect = kore_strdup(uri);
887
888 return (KORE_RESULT_OK);
889 }
890
891 static int
892 configure_websocket_maxframe(char *option)
970893 {
971894 int err;
972895
973 if (argv[1] == NULL) {
974 printf("missing parameter for kore_websocket_maxframe\n");
975 return (KORE_RESULT_ERROR);
976 }
977
978 kore_websocket_maxframe = kore_strtonum64(argv[1], 1, &err);
979 if (err != KORE_RESULT_OK) {
980 printf("bad kore_websocket_maxframe value\n");
981 return (KORE_RESULT_ERROR);
982 }
983
984 return (KORE_RESULT_OK);
985 }
986
987 static int
988 configure_websocket_timeout(char **argv)
896 kore_websocket_maxframe = kore_strtonum64(option, 1, &err);
897 if (err != KORE_RESULT_OK) {
898 printf("bad kore_websocket_maxframe value: %s\n", option);
899 return (KORE_RESULT_ERROR);
900 }
901
902 return (KORE_RESULT_OK);
903 }
904
905 static int
906 configure_websocket_timeout(char *option)
989907 {
990908 int err;
991909
992 if (argv[1] == NULL) {
993 printf("missing parameter for kore_websocket_timeout\n");
994 return (KORE_RESULT_ERROR);
995 }
996
997 kore_websocket_timeout = kore_strtonum64(argv[1], 1, &err);
998 if (err != KORE_RESULT_OK) {
999 printf("bad kore_websocket_timeout value\n");
910 kore_websocket_timeout = kore_strtonum64(option, 1, &err);
911 if (err != KORE_RESULT_OK) {
912 printf("bad kore_websocket_timeout value: %s\n", option);
1000913 return (KORE_RESULT_ERROR);
1001914 }
1002915
1005918 return (KORE_RESULT_OK);
1006919 }
1007920
1008 static int
1009 configure_socket_backlog(char **argv)
1010 {
1011 int err;
1012
1013 if (argv[1] == NULL)
1014 return (KORE_RESULT_ERROR);
1015
1016 kore_socket_backlog = kore_strtonum(argv[1], 10, 0, UINT_MAX, &err);
1017 if (err != KORE_RESULT_OK) {
1018 printf("bad socket_backlog value: %s\n", argv[1]);
921 #endif /* !KORE_NO_HTTP */
922
923 static int
924 configure_chroot(char *path)
925 {
926 if (chroot_path != NULL)
927 kore_free(chroot_path);
928 chroot_path = kore_strdup(path);
929
930 return (KORE_RESULT_OK);
931 }
932
933 static int
934 configure_runas(char *user)
935 {
936 if (runas_user != NULL)
937 kore_free(runas_user);
938 runas_user = kore_strdup(user);
939
940 return (KORE_RESULT_OK);
941 }
942
943 static int
944 configure_workers(char *option)
945 {
946 int err;
947
948 worker_count = kore_strtonum(option, 10, 1, 255, &err);
949 if (err != KORE_RESULT_OK) {
950 printf("%s is not a valid worker number\n", option);
951 return (KORE_RESULT_ERROR);
952 }
953
954 return (KORE_RESULT_OK);
955 }
956
957 static int
958 configure_pidfile(char *path)
959 {
960 if (strcmp(kore_pidfile, KORE_PIDFILE_DEFAULT))
961 kore_free(kore_pidfile);
962 kore_pidfile = kore_strdup(path);
963
964 return (KORE_RESULT_OK);
965 }
966
967 static int
968 configure_max_connections(char *option)
969 {
970 int err;
971
972 worker_max_connections = kore_strtonum(option, 10, 1, UINT_MAX, &err);
973 if (err != KORE_RESULT_OK) {
974 printf("bad value for worker_max_connections: %s\n", option);
975 return (KORE_RESULT_ERROR);
976 }
977
978 return (KORE_RESULT_OK);
979 }
980
981 static int
982 configure_rlimit_nofiles(char *option)
983 {
984 int err;
985
986 worker_rlimit_nofiles = kore_strtonum(option, 10, 1, UINT_MAX, &err);
987 if (err != KORE_RESULT_OK) {
988 printf("bad value for worker_rlimit_nofiles: %s\n", option);
989 return (KORE_RESULT_ERROR);
990 }
991
992 return (KORE_RESULT_OK);
993 }
994
995 static int
996 configure_accept_threshold(char *option)
997 {
998 int err;
999
1000 worker_accept_threshold = kore_strtonum(option, 0, 1, UINT_MAX, &err);
1001 if (err != KORE_RESULT_OK) {
1002 printf("bad value for worker_accept_threshold: %s\n", option);
1003 return (KORE_RESULT_ERROR);
1004 }
1005
1006 return (KORE_RESULT_OK);
1007 }
1008
1009 static int
1010 configure_set_affinity(char *option)
1011 {
1012 int err;
1013
1014 worker_set_affinity = kore_strtonum(option, 10, 0, 1, &err);
1015 if (err != KORE_RESULT_OK) {
1016 printf("bad value for worker_set_affinity: %s\n", option);
1017 return (KORE_RESULT_ERROR);
1018 }
1019
1020 return (KORE_RESULT_OK);
1021 }
1022
1023 static int
1024 configure_socket_backlog(char *option)
1025 {
1026 int err;
1027
1028 kore_socket_backlog = kore_strtonum(option, 10, 0, UINT_MAX, &err);
1029 if (err != KORE_RESULT_OK) {
1030 printf("bad socket_backlog value: %s\n", option);
10191031 return (KORE_RESULT_ERROR);
10201032 }
10211033
10301042 }
10311043
10321044 #if defined(KORE_USE_PGSQL)
1033
1034 static int
1035 configure_pgsql_conn_max(char **argv)
1036 {
1037 int err;
1038
1039 if (argv[1] == NULL) {
1040 printf("missing parameter for pgsql_conn_max\n");
1041 return (KORE_RESULT_ERROR);
1042 }
1043
1044 pgsql_conn_max = kore_strtonum(argv[1], 10, 0, USHRT_MAX, &err);
1045 if (err != KORE_RESULT_OK) {
1046 printf("bad value for pgsql_conn_max: %s\n", argv[1]);
1047 return (KORE_RESULT_ERROR);
1048 }
1049
1050 return (KORE_RESULT_OK);
1051 }
1052
1053 #endif
1045 static int
1046 configure_pgsql_conn_max(char *option)
1047 {
1048 int err;
1049
1050 pgsql_conn_max = kore_strtonum(option, 10, 0, USHRT_MAX, &err);
1051 if (err != KORE_RESULT_OK) {
1052 printf("bad value for pgsql_conn_max: %s\n", option);
1053 return (KORE_RESULT_ERROR);
1054 }
1055
1056 return (KORE_RESULT_OK);
1057 }
1058 #endif
1059
1060 #if defined(KORE_USE_TASKS)
1061 static int
1062 configure_task_threads(char *option)
1063 {
1064 int err;
1065
1066 kore_task_threads = kore_strtonum(option, 10, 0, UCHAR_MAX, &err);
1067 if (err != KORE_RESULT_OK) {
1068 printf("bad value for task_threads: %s\n", option);
1069 return (KORE_RESULT_ERROR);
1070 }
1071
1072 return (KORE_RESULT_OK);
1073 }
1074 #endif
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
2424 #include "http.h"
2525
2626 struct kore_pool connection_pool;
27 struct connection_list connections;
28 struct connection_list disconnected;
2729
2830 void
2931 kore_connection_init(void)
3032 {
33 TAILQ_INIT(&connections);
34 TAILQ_INIT(&disconnected);
35
3136 kore_pool_init(&connection_pool, "connection_pool",
3237 sizeof(struct connection), worker_max_connections);
3338 }
3439
40 void
41 kore_connection_cleanup(void)
42 {
43 kore_debug("connection_cleanup()");
44
45 /* Drop all connections */
46 kore_connection_prune(KORE_CONNECTION_PRUNE_ALL);
47 kore_pool_cleanup(&connection_pool);
48 }
49
3550 struct connection *
3651 kore_connection_new(void *owner)
3752 {
3954
4055 c = kore_pool_get(&connection_pool);
4156
57 #if !defined(KORE_NO_TLS)
4258 c->ssl = NULL;
59 c->cert = NULL;
60 c->tls_reneg = 0;
61 #endif
4362 c->flags = 0;
4463 c->rnb = NULL;
4564 c->snb = NULL;
46 c->cert = NULL;
47 c->wscbs = NULL;
4865 c->owner = owner;
49 c->tls_reneg = 0;
66 c->handle = NULL;
5067 c->disconnect = NULL;
5168 c->hdlr_extra = NULL;
52 c->inflate_started = 0;
53 c->deflate_started = 0;
54 c->client_stream_id = 0;
5569 c->proto = CONN_PROTO_UNKNOWN;
5670 c->type = KORE_TYPE_CONNECTION;
57 c->wsize_initial = SPDY_INIT_WSIZE;
58 c->spdy_send_wsize = SPDY_INIT_WSIZE;
59 c->spdy_recv_wsize = SPDY_INIT_WSIZE;
6071 c->idle_timer.start = 0;
6172 c->idle_timer.length = KORE_IDLE_TIMER_MAX;
6273
74 #if !defined(KORE_NO_HTTP)
75 c->wscbs = NULL;
76 TAILQ_INIT(&(c->http_requests));
77 #endif
78
6379 TAILQ_INIT(&(c->send_queue));
64 TAILQ_INIT(&(c->spdy_streams));
65 TAILQ_INIT(&(c->http_requests));
6680
6781 return (c);
6882 }
6983
7084 int
71 kore_connection_accept(struct listener *l, struct connection **out)
85 kore_connection_accept(struct listener *listener, struct connection **out)
7286 {
7387 struct connection *c;
7488 struct sockaddr *sin;
7589 socklen_t len;
7690
77 kore_debug("kore_connection_accept(%p)", l);
91 kore_debug("kore_connection_accept(%p)", listener);
7892
7993 *out = NULL;
80 c = kore_connection_new(l);
81
82 c->addrtype = l->addrtype;
94 c = kore_connection_new(listener);
95
96 c->addrtype = listener->addrtype;
8397 if (c->addrtype == AF_INET) {
8498 len = sizeof(struct sockaddr_in);
8599 sin = (struct sockaddr *)&(c->addr.ipv4);
88102 sin = (struct sockaddr *)&(c->addr.ipv6);
89103 }
90104
91 if ((c->fd = accept(l->fd, sin, &len)) == -1) {
105 if ((c->fd = accept(listener->fd, sin, &len)) == -1) {
92106 kore_pool_put(&connection_pool, c);
93107 kore_debug("accept(): %s", errno_s);
94108 return (KORE_RESULT_ERROR);
95109 }
96110
97 if (!kore_connection_nonblock(c->fd)) {
111 if (!kore_connection_nonblock(c->fd, 1)) {
98112 close(c->fd);
99113 kore_pool_put(&connection_pool, c);
100114 return (KORE_RESULT_ERROR);
101115 }
102116
103 #if !defined(KORE_BENCHMARK)
117 c->handle = kore_connection_handle;
118 TAILQ_INSERT_TAIL(&connections, c, list);
119
120 #if !defined(KORE_NO_TLS)
104121 c->state = CONN_STATE_SSL_SHAKE;
105122 c->write = net_write_ssl;
106123 c->read = net_read_ssl;
107124 #else
108125 c->state = CONN_STATE_ESTABLISHED;
109 c->proto = CONN_PROTO_HTTP;
110126 c->write = net_write;
111127 c->read = net_read;
112128
113 if (http_keepalive_time != 0)
114 c->idle_timer.length = http_keepalive_time * 1000;
115
116 net_recv_queue(c, http_header_max, NETBUF_CALL_CB_ALWAYS,
117 http_header_recv);
118 #endif
119
120 kore_worker_connection_add(c);
129 if (listener->connect != NULL) {
130 listener->connect(c);
131 } else {
132 #if !defined(KORE_NO_HTTP)
133 c->proto = CONN_PROTO_HTTP;
134 if (http_keepalive_time != 0)
135 c->idle_timer.length = http_keepalive_time * 1000;
136 net_recv_queue(c, http_header_max,
137 NETBUF_CALL_CB_ALWAYS, http_header_recv);
138 #endif
139 }
140 #endif
141
121142 kore_connection_start_idletimer(c);
122143
123144 *out = c;
124145 return (KORE_RESULT_OK);
146 }
147
148 void
149 kore_connection_check_timeout(void)
150 {
151 struct connection *c;
152 u_int64_t now;
153
154 now = kore_time_ms();
155 TAILQ_FOREACH(c, &connections, list) {
156 if (c->proto == CONN_PROTO_MSG)
157 continue;
158 if (!(c->flags & CONN_IDLE_TIMER_ACT))
159 continue;
160 kore_connection_check_idletimer(now, c);
161 }
162 }
163
164 void
165 kore_connection_prune(int all)
166 {
167 struct connection *c, *cnext;
168
169 if (all) {
170 for (c = TAILQ_FIRST(&connections); c != NULL; c = cnext) {
171 cnext = TAILQ_NEXT(c, list);
172 net_send_flush(c);
173 kore_connection_disconnect(c);
174 }
175 }
176
177 for (c = TAILQ_FIRST(&disconnected); c != NULL; c = cnext) {
178 cnext = TAILQ_NEXT(c, list);
179 TAILQ_REMOVE(&disconnected, c, list);
180 kore_connection_remove(c);
181 }
125182 }
126183
127184 void
133190 if (c->disconnect)
134191 c->disconnect(c);
135192
136 kore_worker_connection_move(c);
193 TAILQ_REMOVE(&connections, c, list);
194 TAILQ_INSERT_TAIL(&disconnected, c, list);
137195 }
138196 }
139197
140198 int
141199 kore_connection_handle(struct connection *c)
142200 {
143 #if !defined(KORE_BENCHMARK)
201 #if !defined(KORE_NO_TLS)
144202 int r;
145 u_int32_t len;
146 const u_char *data;
203 struct listener *listener;
147204 char cn[X509_CN_LENGTH];
148205 #endif
149206
151208 kore_connection_stop_idletimer(c);
152209
153210 switch (c->state) {
154 #if !defined(KORE_BENCHMARK)
211 #if !defined(KORE_NO_TLS)
155212 case CONN_STATE_SSL_SHAKE:
156213 if (c->ssl == NULL) {
157214 c->ssl = SSL_new(primary_dom->ssl_ctx);
191248 "no CN found in client certificate");
192249 return (KORE_RESULT_ERROR);
193250 }
251 } else {
252 c->cert = NULL;
194253 }
195254
196255 r = SSL_get_verify_result(c->ssl);
200259 return (KORE_RESULT_ERROR);
201260 }
202261
203 SSL_get0_next_proto_negotiated(c->ssl, &data, &len);
204 if (data) {
205 if (!memcmp(data, "spdy/3", MIN(6, len))) {
206 c->proto = CONN_PROTO_SPDY;
207 c->idle_timer.length = spdy_idle_time;
208 net_recv_queue(c, SPDY_FRAME_SIZE, 0,
209 spdy_frame_recv);
210 } else if (!memcmp(data, "http/1.1", MIN(8, len))) {
211 c->proto = CONN_PROTO_HTTP;
212 if (http_keepalive_time != 0) {
213 c->idle_timer.length =
214 http_keepalive_time * 1000;
215 }
216
217 net_recv_queue(c, http_header_max,
218 NETBUF_CALL_CB_ALWAYS,
219 http_header_recv);
220 } else {
221 kore_log(LOG_NOTICE,
222 "npn: received unknown protocol");
223 return (KORE_RESULT_ERROR);
262 if (c->owner != NULL) {
263 listener = (struct listener *)c->owner;
264 if (listener->connect != NULL) {
265 listener->connect(c);
266 return (KORE_RESULT_OK);
224267 }
225 } else {
226 c->proto = CONN_PROTO_HTTP;
227 if (http_keepalive_time != 0) {
228 c->idle_timer.length =
229 http_keepalive_time * 1000;
230 }
231
232 net_recv_queue(c, http_header_max,
233 NETBUF_CALL_CB_ALWAYS,
234 http_header_recv);
235 }
268 }
269
270 #if !defined(KORE_NO_HTTP)
271 c->proto = CONN_PROTO_HTTP;
272 if (http_keepalive_time != 0) {
273 c->idle_timer.length =
274 http_keepalive_time * 1000;
275 }
276
277 net_recv_queue(c, http_header_max,
278 NETBUF_CALL_CB_ALWAYS, http_header_recv);
279 #endif
236280
237281 c->state = CONN_STATE_ESTABLISHED;
238282 /* FALLTHROUGH */
239 #endif /* !KORE_BENCHMARK */
283 #endif /* !KORE_NO_TLS */
240284 case CONN_STATE_ESTABLISHED:
241285 if (c->flags & CONN_READ_POSSIBLE) {
242286 if (!net_recv_flush(c))
264308 kore_connection_remove(struct connection *c)
265309 {
266310 struct netbuf *nb, *next;
267 struct spdy_stream *s, *snext;
311 #if !defined(KORE_NO_HTTP)
268312 struct http_request *req, *rnext;
313 #endif
269314
270315 kore_debug("kore_connection_remove(%p)", c);
271316
272 #if !defined(KORE_BENCHMARK)
317 #if !defined(KORE_NO_TLS)
273318 if (c->ssl != NULL) {
274319 SSL_shutdown(c->ssl);
275320 SSL_free(c->ssl);
282327 close(c->fd);
283328
284329 if (c->hdlr_extra != NULL)
285 kore_mem_free(c->hdlr_extra);
286
287 if (c->inflate_started)
288 inflateEnd(&(c->z_inflate));
289 if (c->deflate_started)
290 deflateEnd(&(c->z_deflate));
291
330 kore_free(c->hdlr_extra);
331
332 #if !defined(KORE_NO_HTTP)
292333 for (req = TAILQ_FIRST(&(c->http_requests)); req != NULL; req = rnext) {
293334 rnext = TAILQ_NEXT(req, olist);
294335 TAILQ_REMOVE(&(c->http_requests), req, olist);
295336 req->flags |= HTTP_REQUEST_DELETE;
296337 http_request_wakeup(req);
297338 }
339 #endif
298340
299341 for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = next) {
300342 next = TAILQ_NEXT(nb, list);
301343 TAILQ_REMOVE(&(c->send_queue), nb, list);
302344 if (!(nb->flags & NETBUF_IS_STREAM)) {
303 kore_mem_free(nb->buf);
345 kore_free(nb->buf);
304346 } else if (nb->cb != NULL) {
305347 (void)nb->cb(nb);
306348 }
308350 }
309351
310352 if (c->rnb != NULL) {
311 kore_mem_free(c->rnb->buf);
353 kore_free(c->rnb->buf);
312354 kore_pool_put(&nb_pool, c->rnb);
313355 }
314356
315 for (s = TAILQ_FIRST(&(c->spdy_streams)); s != NULL; s = snext) {
316 snext = TAILQ_NEXT(s, list);
317 TAILQ_REMOVE(&(c->spdy_streams), s, list);
318
319 if (s->hblock != NULL) {
320 if (s->hblock->header_block != NULL)
321 kore_mem_free(s->hblock->header_block);
322 kore_mem_free(s->hblock);
323 }
324
325 kore_mem_free(s);
326 }
327
328 kore_worker_connection_remove(c);
329357 kore_pool_put(&connection_pool, c);
330358 }
331359
337365 d = now - c->idle_timer.start;
338366 if (d >= c->idle_timer.length) {
339367 kore_debug("%p idle for %d ms, expiring", c, d);
340 if (c->proto == CONN_PROTO_SPDY)
341 spdy_session_teardown(c, SPDY_SESSION_ERROR_OK);
342 else
343 kore_connection_disconnect(c);
368 kore_connection_disconnect(c);
344369 }
345370 }
346371
363388 }
364389
365390 int
366 kore_connection_nonblock(int fd)
391 kore_connection_nonblock(int fd, int nodelay)
367392 {
368393 int flags;
369394
380405 return (KORE_RESULT_ERROR);
381406 }
382407
383 flags = 1;
384 if (setsockopt(fd, IPPROTO_TCP,
385 TCP_NODELAY, (char *)&flags, sizeof(flags)) == -1) {
386 kore_log(LOG_NOTICE,
387 "failed to set TCP_NODELAY on %d", fd);
408 if (nodelay) {
409 flags = 1;
410 if (setsockopt(fd, IPPROTO_TCP,
411 TCP_NODELAY, (char *)&flags, sizeof(flags)) == -1) {
412 kore_log(LOG_NOTICE,
413 "failed to set TCP_NODELAY on %d", fd);
414 }
388415 }
389416
390417 return (KORE_RESULT_OK);
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1515
1616 #include <sys/param.h>
1717
18 #if !defined(KORE_NO_TLS)
19 #include <openssl/x509.h>
20 #include <openssl/bio.h>
21 #include <openssl/evp.h>
22 #include <openssl/ec.h>
23 #include <openssl/ecdsa.h>
24 #include <poll.h>
25 #endif
26
27 #include <fnmatch.h>
28
1829 #include "kore.h"
1930
2031 #define SSL_SESSION_ID "kore_ssl_sessionid"
2132
2233 struct kore_domain_h domains;
2334 struct kore_domain *primary_dom = NULL;
35
36 #if !defined(KORE_NO_TLS)
37 static u_int8_t keymgr_buf[2048];
38 static size_t keymgr_buflen = 0;
39 static int keymgr_response = 0;
2440 DH *tls_dhparam = NULL;
2541 int tls_version = KORE_TLS_VERSION_1_2;
42 #endif
2643
2744 static void domain_load_crl(struct kore_domain *);
2845
29 #if !defined(KORE_BENCHMARK)
46 #if !defined(KORE_NO_TLS)
3047 static int domain_x509_verify(int, X509_STORE_CTX *);
48
49 static void keymgr_init(void);
50 static void keymgr_await_data(void);
51 static void keymgr_msg_response(struct kore_msg *, const void *);
52
53 static int keymgr_rsa_init(RSA *);
54 static int keymgr_rsa_finish(RSA *);
55 static int keymgr_rsa_privenc(int, const unsigned char *,
56 unsigned char *, RSA *, int);
57
58 static ECDSA_SIG *keymgr_ecdsa_sign(const unsigned char *, int,
59 const BIGNUM *, const BIGNUM *, EC_KEY *);
60
61 #if !defined(LIBRESSL_VERSION_TEXT)
62 /*
63 * Run own ecdsa_method data structure as OpenSSL has this in ecs_locl.h
64 * and does not export this on systems.
65 *
66 * XXX - OpenSSL is merging ECDSA functionality into EC in 1.1.0.
67 */
68 struct ecdsa_method {
69 const char *name;
70 ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *,
71 int, const BIGNUM *, const BIGNUM *, EC_KEY *);
72 int (*ecdsa_sign_setup)(EC_KEY *, BN_CTX *, BIGNUM **,
73 BIGNUM **);
74 int (*ecdsa_do_verify)(const unsigned char *, int,
75 const ECDSA_SIG *, EC_KEY *);
76 int flags;
77 char *app_data;
78 };
79 #endif
80
81 static ECDSA_METHOD keymgr_ecdsa = {
82 "kore ECDSA keymgr method",
83 keymgr_ecdsa_sign,
84 NULL,
85 NULL,
86 0,
87 NULL
88 };
89
90 static RSA_METHOD keymgr_rsa = {
91 "kore RSA keymgr method",
92 NULL,
93 NULL,
94 keymgr_rsa_privenc,
95 NULL,
96 NULL,
97 NULL,
98 keymgr_rsa_init,
99 keymgr_rsa_finish,
100 RSA_METHOD_FLAG_NO_CHECK,
101 NULL,
102 NULL,
103 NULL,
104 NULL
105 };
106
31107 #endif
32108
33109 void
34110 kore_domain_init(void)
35111 {
36112 TAILQ_INIT(&domains);
113 }
114
115 void
116 kore_domain_cleanup(void)
117 {
118 struct kore_domain *dom;
119
120 while ((dom = TAILQ_FIRST(&domains)) != NULL) {
121 TAILQ_REMOVE(&domains, dom, list);
122 kore_domain_free(dom);
123 }
37124 }
38125
39126 int
48135
49136 dom = kore_malloc(sizeof(*dom));
50137 dom->accesslog = -1;
138 #if !defined(KORE_NO_TLS)
51139 dom->cafile = NULL;
52140 dom->certkey = NULL;
53141 dom->ssl_ctx = NULL;
54142 dom->certfile = NULL;
55143 dom->crlfile = NULL;
144 #endif
56145 dom->domain = kore_strdup(domain);
57146 TAILQ_INIT(&(dom->handlers));
58147 TAILQ_INSERT_TAIL(&domains, dom, list);
64153 }
65154
66155 void
156 kore_domain_free(struct kore_domain *dom)
157 {
158 #if !defined(KORE_NO_HTTP)
159 struct kore_module_handle *hdlr;
160 #endif
161 if (dom == NULL)
162 return;
163
164 if (primary_dom == dom)
165 primary_dom = NULL;
166
167 TAILQ_REMOVE(&domains, dom, list);
168
169 if (dom->domain != NULL)
170 kore_free(dom->domain);
171
172 #if !defined(KORE_NO_TLS)
173 if (dom->ssl_ctx != NULL)
174 SSL_CTX_free(dom->ssl_ctx);
175 if (dom->cafile != NULL)
176 kore_free(dom->cafile);
177 if (dom->certkey != NULL)
178 kore_free(dom->certkey);
179 if (dom->certfile != NULL)
180 kore_free(dom->certfile);
181 if (dom->crlfile != NULL)
182 kore_free(dom->crlfile);
183 #endif
184
185 #if !defined(KORE_NO_HTTP)
186 /* Drop all handlers associated with this domain */
187 while ((hdlr = TAILQ_FIRST(&(dom->handlers))) != NULL) {
188 TAILQ_REMOVE(&(dom->handlers), hdlr, list);
189 kore_module_handler_free(hdlr);
190 }
191 #endif
192 kore_free(dom);
193 }
194
195 void
67196 kore_domain_sslstart(struct kore_domain *dom)
68197 {
69 #if !defined(KORE_BENCHMARK)
198 #if !defined(KORE_NO_TLS)
199 BIO *in;
200 RSA *rsa;
201 X509 *x509;
202 EVP_PKEY *pkey;
70203 STACK_OF(X509_NAME) *certs;
204 EC_KEY *eckey;
71205 X509_STORE *store;
72206 const SSL_METHOD *method;
73207 #if !defined(OPENSSL_NO_EC)
99233 dom->certfile, ssl_errno_s);
100234 }
101235
102 if (!SSL_CTX_use_PrivateKey_file(dom->ssl_ctx, dom->certkey,
103 SSL_FILETYPE_PEM)) {
104 fatal("SSL_CTX_use_PrivateKey_file(%s): %s",
105 dom->certkey, ssl_errno_s);
106 }
236 if ((in = BIO_new(BIO_s_file_internal())) == NULL)
237 fatal("BIO_new: %s", ssl_errno_s);
238 if (BIO_read_filename(in, dom->certfile) <= 0)
239 fatal("BIO_read_filename: %s", ssl_errno_s);
240 if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
241 fatal("PEM_read_bio_X509: %s", ssl_errno_s);
242
243 BIO_free(in);
244
245 if ((pkey = X509_get_pubkey(x509)) == NULL)
246 fatal("certificate has no public key");
247
248 switch (EVP_PKEY_id(pkey)) {
249 case EVP_PKEY_RSA:
250 if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
251 fatal("no RSA public key present");
252 RSA_set_app_data(rsa, dom);
253 RSA_set_method(rsa, &keymgr_rsa);
254 break;
255 case EVP_PKEY_EC:
256 if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
257 fatal("no EC public key present");
258 ECDSA_set_ex_data(eckey, 0, dom);
259 ECDSA_set_method(eckey, &keymgr_ecdsa);
260 break;
261 default:
262 fatal("unknown public key in certificate");
263 }
264
265 if (!SSL_CTX_use_PrivateKey(dom->ssl_ctx, pkey))
266 fatal("SSL_CTX_use_PrivateKey(): %s", ssl_errno_s);
107267
108268 if (!SSL_CTX_check_private_key(dom->ssl_ctx))
109269 fatal("Public/Private key for %s do not match", dom->domain);
114274 SSL_CTX_set_tmp_dh(dom->ssl_ctx, tls_dhparam);
115275 SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_DH_USE);
116276
117 #if !defined(OPENSSL_NO_EC)
118 if ((ecdh = EC_KEY_new_by_curve_name(NID_secp384r1)) != NULL) {
119 SSL_CTX_set_tmp_ecdh(dom->ssl_ctx, ecdh);
120 EC_KEY_free(ecdh);
121 }
122 #endif
277 if ((ecdh = EC_KEY_new_by_curve_name(NID_secp384r1)) == NULL)
278 fatal("EC_KEY_new_by_curve_name: %s", ssl_errno_s);
279
280 SSL_CTX_set_tmp_ecdh(dom->ssl_ctx, ecdh);
281 EC_KEY_free(ecdh);
123282
124283 SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_COMPRESSION);
125284
153312 * Note that OpenBSD has since heartbleed removed freelists
154313 * from its OpenSSL in base so we don't need to care about it.
155314 */
156 #if !defined(OpenBSD) || (OpenBSD < 201405)
315 #if !defined(LIBRESSL_VERSION_TEXT)
157316 dom->ssl_ctx->freelist_max_len = 0;
158317 #endif
159318 SSL_CTX_set_mode(dom->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
169328
170329 SSL_CTX_set_info_callback(dom->ssl_ctx, kore_tls_info_callback);
171330 SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_tls_sni_cb);
172 SSL_CTX_set_next_protos_advertised_cb(dom->ssl_ctx,
173 kore_tls_npn_cb, NULL);
174
175 kore_mem_free(dom->certfile);
176 kore_mem_free(dom->certkey);
177 #endif
331
332 kore_free(dom->certfile);
333 dom->certfile = NULL;
334 #endif
335 }
336
337 void
338 kore_domain_callback(void (*cb)(struct kore_domain *))
339 {
340 struct kore_domain *dom;
341
342 TAILQ_FOREACH(dom, &domains, list) {
343 cb(dom);
344 }
178345 }
179346
180347 struct kore_domain *
183350 struct kore_domain *dom;
184351
185352 TAILQ_FOREACH(dom, &domains, list) {
186 if (!strcmp(dom->domain, domain))
353 if (!fnmatch(dom->domain, domain, FNM_CASEFOLD))
187354 return (dom);
188355 }
189356
195362 {
196363 struct kore_domain *dom;
197364
198 TAILQ_FOREACH(dom, &domains, list)
199 close(dom->accesslog);
365 TAILQ_FOREACH(dom, &domains, list) {
366 if (dom->accesslog != -1) {
367 (void)close(dom->accesslog);
368 }
369 }
200370 }
201371
202372 void
208378 domain_load_crl(dom);
209379 }
210380
381 void
382 kore_domain_keymgr_init(void)
383 {
384 #if !defined(KORE_NO_TLS)
385 keymgr_init();
386 kore_msg_register(KORE_MSG_KEYMGR_RESP, keymgr_msg_response);
387 #endif
388 }
389
211390 static void
212391 domain_load_crl(struct kore_domain *dom)
213392 {
214 #if !defined(KORE_BENCHMARK)
393 #if !defined(KORE_NO_TLS)
215394 X509_STORE *store;
216395
217396 ERR_clear_error();
240419 #endif
241420 }
242421
243 #if !defined(KORE_BENCHMARK)
422 #if !defined(KORE_NO_TLS)
423 static void
424 keymgr_init(void)
425 {
426 const RSA_METHOD *meth;
427
428 if ((meth = RSA_get_default_method()) == NULL)
429 fatal("failed to obtain RSA method");
430
431 keymgr_rsa.rsa_pub_enc = meth->rsa_pub_enc;
432 keymgr_rsa.rsa_pub_dec = meth->rsa_pub_dec;
433 keymgr_rsa.bn_mod_exp = meth->bn_mod_exp;
434 }
435
436 static int
437 keymgr_rsa_init(RSA *rsa)
438 {
439 if (rsa != NULL) {
440 rsa->flags |= RSA_FLAG_EXT_PKEY | RSA_METHOD_FLAG_NO_CHECK;
441 return (1);
442 }
443
444 return (0);
445 }
446
447 static int
448 keymgr_rsa_privenc(int flen, const unsigned char *from, unsigned char *to,
449 RSA *rsa, int padding)
450 {
451 int ret;
452 size_t len;
453 struct kore_keyreq *req;
454 struct kore_domain *dom;
455
456 len = sizeof(*req) + flen;
457 if (len > sizeof(keymgr_buf))
458 fatal("keymgr_buf too small");
459
460 if ((dom = RSA_get_app_data(rsa)) == NULL)
461 fatal("RSA key has no domain attached");
462 if (strlen(dom->domain) >= KORE_DOMAINNAME_LEN - 1)
463 fatal("domain name too long");
464
465 memset(keymgr_buf, 0, sizeof(keymgr_buf));
466
467 req = (struct kore_keyreq *)keymgr_buf;
468 req->data_len = flen;
469 req->padding = padding;
470 req->domain_len = strlen(dom->domain);
471
472 memcpy(&req->data[0], from, req->data_len);
473 memcpy(req->domain, dom->domain, req->domain_len);
474
475 kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
476 keymgr_await_data();
477
478 ret = -1;
479 if (keymgr_response) {
480 if (keymgr_buflen < INT_MAX &&
481 (int)keymgr_buflen == RSA_size(rsa)) {
482 ret = RSA_size(rsa);
483 memcpy(to, keymgr_buf, RSA_size(rsa));
484 }
485 }
486
487 keymgr_buflen = 0;
488 keymgr_response = 0;
489 kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
490
491 return (ret);
492 }
493
494 static int
495 keymgr_rsa_finish(RSA *rsa)
496 {
497 return (1);
498 }
499
500 static ECDSA_SIG *
501 keymgr_ecdsa_sign(const unsigned char *dgst, int dgst_len,
502 const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
503 {
504 size_t len;
505 ECDSA_SIG *sig;
506 const u_int8_t *ptr;
507 struct kore_domain *dom;
508 struct kore_keyreq *req;
509
510 if (in_kinv != NULL || in_r != NULL)
511 return (NULL);
512
513 len = sizeof(*req) + dgst_len;
514 if (len > sizeof(keymgr_buf))
515 fatal("keymgr_buf too small");
516
517 if ((dom = ECDSA_get_ex_data(eckey, 0)) == NULL)
518 fatal("EC_KEY has no domain");
519
520 memset(keymgr_buf, 0, sizeof(keymgr_buf));
521
522 req = (struct kore_keyreq *)keymgr_buf;
523 req->data_len = dgst_len;
524 req->domain_len = strlen(dom->domain);
525
526 memcpy(&req->data[0], dgst, req->data_len);
527 memcpy(req->domain, dom->domain, req->domain_len);
528
529 kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
530 keymgr_await_data();
531
532 if (keymgr_response) {
533 ptr = keymgr_buf;
534 sig = d2i_ECDSA_SIG(NULL, &ptr, keymgr_buflen);
535 } else {
536 sig = NULL;
537 }
538
539 keymgr_buflen = 0;
540 keymgr_response = 0;
541 kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
542
543 return (sig);
544 }
545
546 static void
547 keymgr_await_data(void)
548 {
549 int ret;
550 struct pollfd pfd[1];
551 u_int64_t start, cur;
552
553 /*
554 * We need to wait until the keymgr responds to us, so keep doing
555 * net_recv_flush() until our callback for KORE_MSG_KEYMGR_RESP
556 * tells us that we have obtained the response.
557 *
558 * This means other internal messages can still be delivered by
559 * this worker process to the appropriate callbacks but we do not
560 * drop out until we've either received an answer from the keymgr
561 * or until the timeout has been reached.
562 *
563 * It will however block any other I/O and request handling on
564 * this worker until either of the above criteria is met.
565 */
566 start = kore_time_ms();
567 kore_platform_disable_read(worker->msg[1]->fd);
568
569 keymgr_response = 0;
570 memset(keymgr_buf, 0, sizeof(keymgr_buf));
571
572 for (;;) {
573 pfd[0].fd = worker->msg[1]->fd;
574 pfd[0].events = POLLIN;
575 pfd[0].revents = 0;
576
577 ret = poll(pfd, 1, 100);
578 if (ret == -1) {
579 if (errno == EINTR)
580 continue;
581 fatal("poll: %s", errno_s);
582 }
583
584 cur = kore_time_ms();
585 if ((cur - start) > 1000)
586 break;
587
588 if (ret == 0)
589 continue;
590
591 if (pfd[0].revents & (POLLERR | POLLHUP))
592 break;
593 if (!(pfd[0].revents & POLLIN))
594 break;
595
596 worker->msg[1]->flags |= CONN_READ_POSSIBLE;
597 if (!net_recv_flush(worker->msg[1]))
598 break;
599
600 if (keymgr_response)
601 break;
602 }
603 }
604
605 static void
606 keymgr_msg_response(struct kore_msg *msg, const void *data)
607 {
608 keymgr_response = 1;
609 keymgr_buflen = msg->length;
610
611 if (keymgr_buflen > sizeof(keymgr_buf))
612 return;
613
614 memcpy(keymgr_buf, data, keymgr_buflen);
615 }
616
244617 static int
245618 domain_x509_verify(int ok, X509_STORE_CTX *ctx)
246619 {
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1717
1818 #include <ctype.h>
1919 #include <inttypes.h>
20
21 #include "spdy.h"
20 #include <stdio.h>
21 #include <string.h>
22
23 #include <fcntl.h>
24 #include <unistd.h>
25
2226 #include "kore.h"
2327 #include "http.h"
2428
3034 #include "tasks.h"
3135 #endif
3236
33 static int http_body_recv(struct netbuf *);
34 static void http_error_response(struct connection *,
35 struct spdy_stream *, int);
36 static void http_argument_add(struct http_request *, const char *,
37 void *, u_int32_t, int);
38 static void http_file_add(struct http_request *, const char *,
39 const char *, u_int8_t *, u_int32_t);
40 static void http_response_normal(struct http_request *,
41 struct connection *, int, void *, u_int32_t);
42 static void http_response_spdy(struct http_request *,
43 struct connection *, struct spdy_stream *,
44 int, void *, u_int32_t);
37 static int http_body_recv(struct netbuf *);
38 static int http_body_rewind(struct http_request *);
39 static void http_error_response(struct connection *, int);
40 static void http_argument_add(struct http_request *, const char *, char *);
41 static void http_response_normal(struct http_request *,
42 struct connection *, int, const void *, size_t);
43 static void multipart_add_field(struct http_request *, struct kore_buf *,
44 const char *, const char *, const int);
45 static void multipart_file_add(struct http_request *, struct kore_buf *,
46 const char *, const char *, const char *, const int);
47 static int multipart_find_data(struct kore_buf *, struct kore_buf *,
48 size_t *, struct http_request *, const void *, size_t);
49 static int multipart_parse_headers(struct http_request *,
50 struct kore_buf *, struct kore_buf *,
51 const char *, const int);
4552
4653 static struct kore_buf *header_buf;
4754 static char http_version[32];
4855 static u_int16_t http_version_len;
49 static char http_version_spdy[32];
5056 static TAILQ_HEAD(, http_request) http_requests;
5157 static TAILQ_HEAD(, http_request) http_requests_sleeping;
5258 static struct kore_pool http_request_pool;
5359 static struct kore_pool http_header_pool;
5460 static struct kore_pool http_host_pool;
5561 static struct kore_pool http_path_pool;
62 static struct kore_pool http_body_path;
5663
5764 int http_request_count = 0;
5865 u_int32_t http_request_limit = HTTP_REQUEST_LIMIT;
6067 u_int16_t http_header_max = HTTP_HEADER_MAX_LEN;
6168 u_int16_t http_keepalive_time = HTTP_KEEPALIVE_TIME;
6269 u_int64_t http_body_max = HTTP_BODY_MAX_LEN;
70 u_int64_t http_body_disk_offload = HTTP_BODY_DISK_OFFLOAD;
71 char *http_body_disk_path = HTTP_BODY_DISK_PATH;
6372
6473 void
6574 http_init(void)
6978 TAILQ_INIT(&http_requests);
7079 TAILQ_INIT(&http_requests_sleeping);
7180
72 header_buf = kore_buf_create(1024);
73
74 l = snprintf(http_version_spdy, sizeof(http_version_spdy),
75 "kore (%d.%d.%d-%s)", KORE_VERSION_MAJOR, KORE_VERSION_MINOR,
76 KORE_VERSION_PATCH, KORE_VERSION_STATE);
77 if (l == -1 || (size_t)l >= sizeof(http_version_spdy))
78 fatal("http_init(): http_version_spdy buffer too small");
81 header_buf = kore_buf_alloc(1024);
7982
8083 l = snprintf(http_version, sizeof(http_version),
8184 "server: kore (%d.%d.%d-%s)\r\n", KORE_VERSION_MAJOR,
9598 "http_host_pool", KORE_DOMAINNAME_LEN, prealloc);
9699 kore_pool_init(&http_path_pool,
97100 "http_path_pool", HTTP_URI_LEN, prealloc);
101 kore_pool_init(&http_body_path,
102 "http_body_path", HTTP_BODY_PATH_MAX, prealloc);
103 }
104
105 void
106 http_cleanup(void)
107 {
108 if (header_buf != NULL) {
109 kore_buf_free(header_buf);
110 header_buf = NULL;
111 }
112
113 kore_pool_cleanup(&http_request_pool);
114 kore_pool_cleanup(&http_header_pool);
115 kore_pool_cleanup(&http_host_pool);
116 kore_pool_cleanup(&http_path_pool);
117 kore_pool_cleanup(&http_body_path);
98118 }
99119
100120 int
101 http_request_new(struct connection *c, struct spdy_stream *s, const char *host,
121 http_request_new(struct connection *c, const char *host,
102122 const char *method, const char *path, const char *version,
103123 struct http_request **out)
104124 {
105125 char *p;
106126 struct http_request *req;
127 struct kore_module_handle *hdlr;
107128 int m, flags;
108 size_t hostlen, pathlen;
109
110 kore_debug("http_request_new(%p, %p, %s, %s, %s, %s)", c, s,
111 host, method, path, version);
129 size_t hostlen, pathlen, qsoff;
130
131 kore_debug("http_request_new(%p, %s, %s, %s, %s)", c, host,
132 method, path, version);
112133
113134 if ((hostlen = strlen(host)) >= KORE_DOMAINNAME_LEN - 1) {
114 http_error_response(c, s, 500);
135 http_error_response(c, 500);
115136 return (KORE_RESULT_ERROR);
116137 }
117138
118139 if ((pathlen = strlen(path)) >= HTTP_URI_LEN - 1) {
119 http_error_response(c, s, 414);
140 http_error_response(c, 414);
120141 return (KORE_RESULT_ERROR);
121142 }
122143
123144 if (strcasecmp(version, "http/1.1")) {
124 http_error_response(c, s, 505);
145 http_error_response(c, 505);
125146 return (KORE_RESULT_ERROR);
126147 }
148
149 if ((p = strchr(path, '?')) != NULL) {
150 *p = '\0';
151 qsoff = p - path;
152 } else {
153 qsoff = 0;
154 }
155
156 if ((hdlr = kore_module_handler_find(host, path)) == NULL) {
157 http_error_response(c, 404);
158 return (KORE_RESULT_ERROR);
159 }
160
161 if (p != NULL)
162 *p = '?';
127163
128164 if (!strcasecmp(method, "get")) {
129165 m = HTTP_METHOD_GET;
141177 m = HTTP_METHOD_HEAD;
142178 flags = HTTP_REQUEST_COMPLETE;
143179 } else {
144 http_error_response(c, s, 400);
180 http_error_response(c, 400);
145181 return (KORE_RESULT_ERROR);
146182 }
147183
151187 req->start = 0;
152188 req->owner = c;
153189 req->status = 0;
154 req->stream = s;
155190 req->method = m;
156 req->hdlr = NULL;
191 req->hdlr = hdlr;
157192 req->agent = NULL;
158193 req->flags = flags;
159194 req->fsm_state = 0;
160195 req->http_body = NULL;
196 req->http_body_fd = -1;
161197 req->hdlr_extra = NULL;
162198 req->query_string = NULL;
163 req->multipart_body = NULL;
199 req->http_body_length = 0;
200 req->http_body_offset = 0;
201 req->http_body_path = NULL;
164202
165203 if ((p = strrchr(host, ':')) != NULL)
166204 *p = '\0';
167205
168206 req->host = kore_pool_get(&http_host_pool);
169 (void)memcpy(req->host, host, hostlen);
207 memcpy(req->host, host, hostlen);
170208 req->host[hostlen] = '\0';
171209
172210 req->path = kore_pool_get(&http_path_pool);
173 (void)memcpy(req->path, path, pathlen);
211 memcpy(req->path, path, pathlen);
174212 req->path[pathlen] = '\0';
175213
176 if ((req->query_string = strchr(req->path, '?')) != NULL)
214 if (qsoff > 0) {
215 req->query_string = req->path + qsoff;
177216 *(req->query_string)++ = '\0';
217 } else {
218 req->query_string = NULL;
219 }
178220
179221 TAILQ_INIT(&(req->resp_headers));
180222 TAILQ_INIT(&(req->req_headers));
181223 TAILQ_INIT(&(req->arguments));
182224 TAILQ_INIT(&(req->files));
183225
184 if (s != NULL) {
185 if (!http_request_header(req, "user-agent", &(req->agent)))
186 req->agent = kore_strdup("unknown");
187 }
188
189226 #if defined(KORE_USE_TASKS)
190227 LIST_INIT(&(req->tasks));
191228 #endif
253290 continue;
254291
255292 count++;
256 http_process_request(req, 0);
293 http_process_request(req);
257294 }
258295 }
259296
260297 void
261 http_process_request(struct http_request *req, int retry_only)
262 {
263 struct kore_module_handle *hdlr;
264 int r, (*cb)(struct http_request *);
298 http_process_request(struct http_request *req)
299 {
300 int r, (*cb)(struct http_request *);
265301
266302 kore_debug("http_process_request: %p->%p (%s)",
267303 req->owner, req, req->path);
268304
269 if (req->flags & HTTP_REQUEST_DELETE)
305 if (req->flags & HTTP_REQUEST_DELETE || req->hdlr == NULL)
270306 return;
271307
272 if (req->hdlr != NULL)
273 hdlr = req->hdlr;
308 req->start = kore_time_ms();
309 if (req->hdlr->auth != NULL && !(req->flags & HTTP_REQUEST_AUTHED))
310 r = kore_auth_run(req, req->hdlr->auth);
274311 else
275 hdlr = kore_module_handler_find(req->host, req->path);
276
277 req->start = kore_time_ms();
278 if (hdlr == NULL) {
279 r = http_generic_404(req);
280 } else {
281 if (req->hdlr != hdlr && hdlr->auth != NULL)
282 r = kore_auth_run(req, hdlr->auth);
283 else
284 r = KORE_RESULT_OK;
285
286 switch (r) {
287 case KORE_RESULT_OK:
288 req->hdlr = hdlr;
289 cb = hdlr->addr;
290 worker->active_hdlr = hdlr;
291 r = cb(req);
292 worker->active_hdlr = NULL;
293 break;
294 case KORE_RESULT_RETRY:
295 break;
296 case KORE_RESULT_ERROR:
297 /*
298 * Set r to KORE_RESULT_OK so we can properly
299 * flush the result from kore_auth_run().
300 */
301 r = KORE_RESULT_OK;
302 break;
303 default:
304 fatal("kore_auth() returned unknown %d", r);
305 }
312 r = KORE_RESULT_OK;
313
314 switch (r) {
315 case KORE_RESULT_OK:
316 *(void **)&(cb) = req->hdlr->addr;
317 worker->active_hdlr = req->hdlr;
318 r = cb(req);
319 worker->active_hdlr = NULL;
320 break;
321 case KORE_RESULT_RETRY:
322 break;
323 case KORE_RESULT_ERROR:
324 /*
325 * Set r to KORE_RESULT_OK so we can properly
326 * flush the result from kore_auth_run().
327 */
328 r = KORE_RESULT_OK;
329 break;
330 default:
331 fatal("kore_auth() returned unknown %d", r);
306332 }
307333 req->end = kore_time_ms();
308334 req->total += req->end - req->start;
309
310 if (retry_only == 1 && r != KORE_RESULT_RETRY)
311 fatal("http_process_request: expected RETRY but got %d", r);
312335
313336 switch (r) {
314337 case KORE_RESULT_OK:
325348 fatal("A page handler returned an unknown result: %d", r);
326349 }
327350
328 if (hdlr != NULL && hdlr->dom->accesslog != -1)
351 if (req->hdlr->dom->accesslog != -1)
329352 kore_accesslog(req);
330353
331354 req->flags |= HTTP_REQUEST_DELETE;
401424 next = TAILQ_NEXT(hdr, list);
402425
403426 TAILQ_REMOVE(&(req->resp_headers), hdr, list);
404 kore_mem_free(hdr->header);
405 kore_mem_free(hdr->value);
427 kore_free(hdr->header);
428 kore_free(hdr->value);
406429 kore_pool_put(&http_header_pool, hdr);
407430 }
408431
410433 next = TAILQ_NEXT(hdr, list);
411434
412435 TAILQ_REMOVE(&(req->req_headers), hdr, list);
413 kore_mem_free(hdr->header);
414 kore_mem_free(hdr->value);
436 kore_free(hdr->header);
437 kore_free(hdr->value);
415438 kore_pool_put(&http_header_pool, hdr);
416439 }
417440
419442 qnext = TAILQ_NEXT(q, list);
420443
421444 TAILQ_REMOVE(&(req->arguments), q, list);
422 kore_mem_free(q->name);
423
424 if (q->value != NULL)
425 kore_mem_free(q->value);
445 kore_free(q->name);
426446 if (q->s_value != NULL)
427 kore_mem_free(q->s_value);
428
429 kore_mem_free(q);
447 kore_free(q->s_value);
448 kore_free(q);
430449 }
431450
432451 for (f = TAILQ_FIRST(&(req->files)); f != NULL; f = fnext) {
433452 fnext = TAILQ_NEXT(f, list);
434453 TAILQ_REMOVE(&(req->files), f, list);
435454
436 kore_mem_free(f->filename);
437 kore_mem_free(f->name);
438 kore_mem_free(f);
455 kore_free(f->filename);
456 kore_free(f->name);
457 kore_free(f);
439458 }
440459
441460 if (req->http_body != NULL)
442461 kore_buf_free(req->http_body);
443 if (req->multipart_body != NULL)
444 kore_mem_free(req->multipart_body);
445
446 if (req->agent != NULL)
447 kore_mem_free(req->agent);
462
463 if (req->http_body_fd != -1)
464 (void)close(req->http_body_fd);
465
466 if (req->http_body_path != NULL) {
467 if (unlink(req->http_body_path) == -1) {
468 kore_log(LOG_NOTICE, "failed to unlink %s: %s",
469 req->http_body_path, errno_s);
470 }
471 kore_pool_put(&http_body_path, req->http_body_path);
472 }
473
448474 if (req->hdlr_extra != NULL &&
449475 !(req->flags & HTTP_REQUEST_RETAIN_EXTRA))
450 kore_mem_free(req->hdlr_extra);
476 kore_free(req->hdlr_extra);
451477
452478 kore_pool_put(&http_request_pool, req);
453479 http_request_count--;
454480 }
455481
456482 void
457 http_response(struct http_request *req, int status, void *d, u_int32_t l)
458 {
459 kore_debug("http_response(%p, %d, %p, %d)", req, status, d, l);
483 http_response(struct http_request *req, int status, const void *d, size_t l)
484 {
485 kore_debug("http_response(%p, %d, %p, %zu)", req, status, d, l);
460486
461487 req->status = status;
462488
463489 switch (req->owner->proto) {
464 case CONN_PROTO_SPDY:
465 http_response_spdy(req, req->owner, req->stream, status, d, l);
466 break;
467490 case CONN_PROTO_HTTP:
491 case CONN_PROTO_WEBSOCKET:
468492 http_response_normal(req, req->owner, status, d, l);
469493 break;
470494 default:
475499
476500 void
477501 http_response_stream(struct http_request *req, int status, void *base,
478 u_int64_t len, int (*cb)(struct netbuf *), void *arg)
502 size_t len, int (*cb)(struct netbuf *), void *arg)
479503 {
480504 struct netbuf *nb;
481505
482506 req->status = status;
483507
484508 switch (req->owner->proto) {
485 case CONN_PROTO_SPDY:
486 http_response_spdy(req, req->owner,
487 req->stream, status, NULL, len);
488 break;
489509 case CONN_PROTO_HTTP:
490510 http_response_normal(req, req->owner, status, NULL, len);
491511 break;
495515 }
496516
497517 if (req->method != HTTP_METHOD_HEAD) {
498 net_send_stream(req->owner, base, len, req->stream, cb, &nb);
518 net_send_stream(req->owner, base, len, cb, &nb);
499519 nb->extra = arg;
500520 }
501521 }
503523 int
504524 http_request_header(struct http_request *req, const char *header, char **out)
505525 {
506 int r;
507526 struct http_header *hdr;
508527
509 if (req->owner->proto == CONN_PROTO_SPDY) {
510 r = spdy_stream_get_header(req->stream->hblock, header, out);
511 } else {
512 TAILQ_FOREACH(hdr, &(req->req_headers), list) {
513 if (!strcasecmp(hdr->header, header)) {
514 r = strlen(hdr->value) + 1;
515 *out = kore_malloc(r);
516 kore_strlcpy(*out, hdr->value, r);
517 return (KORE_RESULT_OK);
518 }
519 }
520
521 r = KORE_RESULT_ERROR;
522 }
523
524 return (r);
528 TAILQ_FOREACH(hdr, &(req->req_headers), list) {
529 if (!strcasecmp(hdr->header, header)) {
530 *out = hdr->value;
531 return (KORE_RESULT_OK);
532 }
533 }
534
535 return (KORE_RESULT_ERROR);
525536 }
526537
527538 int
528539 http_header_recv(struct netbuf *nb)
529540 {
530541 size_t len;
531 u_int64_t clen;
542 ssize_t ret;
532543 struct http_header *hdr;
533544 struct http_request *req;
545 u_int64_t bytes_left;
534546 u_int8_t *end_headers;
535 int h, i, v, skip, bytes_left;
547 int h, i, v, skip, l;
536548 char *request[4], *host[3], *hbuf;
537549 char *p, *headers[HTTP_REQ_HEADER_MAX];
538550 struct connection *c = (struct connection *)nb->owner;
553565
554566 *end_headers = '\0';
555567 end_headers += skip;
556 nb->flags |= NETBUF_FORCE_REMOVE;
557568 len = end_headers - nb->buf;
558569 hbuf = (char *)nb->buf;
559570
560571 h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
561572 if (h < 2) {
562 http_error_response(c, NULL, 400);
573 http_error_response(c, 400);
563574 return (KORE_RESULT_OK);
564575 }
565576
566577 v = kore_split_string(headers[0], " ", request, 4);
567578 if (v != 3) {
568 http_error_response(c, NULL, 400);
579 http_error_response(c, 400);
569580 return (KORE_RESULT_OK);
570581 }
571582
577588
578589 v = kore_split_string(headers[i], ":", host, 3);
579590 if (v != 2) {
580 http_error_response(c, NULL, 400);
591 http_error_response(c, 400);
581592 return (KORE_RESULT_OK);
582593 }
583594
584595 if ((host[1] - host[0]) != 5 ||
585596 strncasecmp(host[0], "host", 4) || host[1] == '\0') {
586 http_error_response(c, NULL, 400);
597 http_error_response(c, 400);
587598 return (KORE_RESULT_OK);
588599 }
589600
593604 }
594605
595606 if (host[0] == NULL) {
596 http_error_response(c, NULL, 400);
607 http_error_response(c, 400);
597608 return (KORE_RESULT_OK);
598609 }
599610
600 if (!http_request_new(c, NULL, host[1],
611 if (!http_request_new(c, host[1],
601612 request[0], request[1], request[2], &req))
602613 return (KORE_RESULT_OK);
603614
621632
622633 if (req->agent == NULL &&
623634 !strcasecmp(hdr->header, "user-agent"))
624 req->agent = kore_strdup(hdr->value);
635 req->agent = hdr->value;
625636 }
626637
627638 if (req->flags & HTTP_REQUEST_EXPECT_BODY) {
639 if (http_body_max == 0) {
640 req->flags |= HTTP_REQUEST_DELETE;
641 http_error_response(req->owner, 405);
642 return (KORE_RESULT_OK);
643 }
644
628645 if (!http_request_header(req, "content-length", &p)) {
629646 kore_debug("expected body but no content-length");
630647 req->flags |= HTTP_REQUEST_DELETE;
631 http_error_response(req->owner, NULL, 411);
632 return (KORE_RESULT_OK);
633 }
634
635 clen = kore_strtonum(p, 10, 0, LONG_MAX, &v);
648 http_error_response(req->owner, 411);
649 return (KORE_RESULT_OK);
650 }
651
652 req->content_length = kore_strtonum(p, 10, 0, LONG_MAX, &v);
636653 if (v == KORE_RESULT_ERROR) {
637654 kore_debug("content-length invalid: %s", p);
638 kore_mem_free(p);
639655 req->flags |= HTTP_REQUEST_DELETE;
640 http_error_response(req->owner, NULL, 411);
641 return (KORE_RESULT_OK);
642 }
643
644 kore_mem_free(p);
645
646 if (clen == 0) {
656 http_error_response(req->owner, 411);
657 return (KORE_RESULT_OK);
658 }
659
660 if (req->content_length == 0) {
647661 req->flags |= HTTP_REQUEST_COMPLETE;
648662 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
649663 return (KORE_RESULT_OK);
650664 }
651665
652 if (clen > http_body_max) {
666 if (req->content_length > http_body_max) {
653667 kore_log(LOG_NOTICE, "body too large (%ld > %ld)",
654 clen, http_body_max);
668 req->content_length, http_body_max);
655669 req->flags |= HTTP_REQUEST_DELETE;
656 http_error_response(req->owner, NULL, 411);
657 return (KORE_RESULT_OK);
658 }
659
660 req->http_body = kore_buf_create(clen);
661 kore_buf_append(req->http_body, end_headers,
662 (nb->s_off - len));
663
664 bytes_left = clen - (nb->s_off - len);
670 http_error_response(req->owner, 413);
671 return (KORE_RESULT_OK);
672 }
673
674 req->http_body_length = req->content_length;
675
676 if (http_body_disk_offload > 0 &&
677 req->content_length > http_body_disk_offload) {
678 req->http_body_path = kore_pool_get(&http_body_path);
679 l = snprintf(req->http_body_path, HTTP_BODY_PATH_MAX,
680 "%s/http_body.XXXXXX", http_body_disk_path);
681 if (l == -1 || (size_t)l >= HTTP_BODY_PATH_MAX) {
682 req->flags |= HTTP_REQUEST_DELETE;
683 http_error_response(req->owner, 500);
684 return (KORE_RESULT_ERROR);
685 }
686
687 req->http_body = NULL;
688 req->http_body_fd = mkstemp(req->http_body_path);
689 if (req->http_body_fd == -1) {
690 req->flags |= HTTP_REQUEST_DELETE;
691 http_error_response(req->owner, 500);
692 return (KORE_RESULT_OK);
693 }
694
695 ret = write(req->http_body_fd,
696 end_headers, (nb->s_off - len));
697 if (ret == -1 || (size_t)ret != (nb->s_off - len)) {
698 req->flags |= HTTP_REQUEST_DELETE;
699 http_error_response(req->owner, 500);
700 return (KORE_RESULT_OK);
701 }
702 } else {
703 req->http_body_fd = -1;
704 req->http_body = kore_buf_alloc(req->content_length);
705 kore_buf_append(req->http_body, end_headers,
706 (nb->s_off - len));
707 }
708
709 bytes_left = req->content_length - (nb->s_off - len);
665710 if (bytes_left > 0) {
666711 kore_debug("%ld/%ld (%ld - %ld) more bytes for body",
667 bytes_left, clen, nb->s_off, len);
668 net_recv_reset(c, bytes_left, http_body_recv);
712 bytes_left, req->content_length, nb->s_off, len);
713 net_recv_reset(c,
714 MIN(bytes_left, NETBUF_SEND_PAYLOAD_MAX),
715 http_body_recv);
669716 c->rnb->extra = req;
670 c->rnb->flags &= ~NETBUF_CALL_CB_ALWAYS;
717 http_request_sleep(req);
718 req->content_length = bytes_left;
671719 } else if (bytes_left == 0) {
672720 req->flags |= HTTP_REQUEST_COMPLETE;
673721 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
722 if (!http_body_rewind(req)) {
723 req->flags |= HTTP_REQUEST_DELETE;
724 http_error_response(req->owner, 500);
725 return (KORE_RESULT_OK);
726 }
674727 } else {
675 kore_debug("bytes_left would become zero (%ld)", clen);
676 http_error_response(req->owner, NULL, 500);
728 http_error_response(req->owner, 500);
677729 }
678730 }
679731
680732 return (KORE_RESULT_OK);
681 }
682
683 int
684 http_populate_arguments(struct http_request *req)
685 {
686 u_int32_t len;
687 int i, v, c, count;
688 char *query, *args[HTTP_MAX_QUERY_ARGS], *val[3];
689
690 if (req->method == HTTP_METHOD_POST) {
691 if (req->http_body == NULL)
692 return (0);
693 query = http_body_text(req);
694 } else {
695 if (req->query_string == NULL)
696 return (0);
697 query = kore_strdup(req->query_string);
698 }
699
700 count = 0;
701 v = kore_split_string(query, "&", args, HTTP_MAX_QUERY_ARGS);
702 for (i = 0; i < v; i++) {
703 c = kore_split_string(args[i], "=", val, 3);
704 if (c != 1 && c != 2) {
705 kore_debug("malformed query argument");
706 continue;
707 }
708
709 if (val[1] != NULL) {
710 len = strlen(val[1]);
711 http_argument_add(req, val[0], val[1],
712 len, HTTP_ARG_TYPE_STRING);
713 count++;
714 }
715 }
716
717 kore_mem_free(query);
718 return (count);
719733 }
720734
721735 int
722736 http_argument_get(struct http_request *req, const char *name,
723 void **out, void *nout, u_int32_t *len, int type)
737 void **out, void *nout, int type)
724738 {
725739 struct http_arg *q;
726740
727 if (len != NULL)
728 *len = 0;
729
730741 TAILQ_FOREACH(q, &(req->arguments), list) {
731 if (!strcmp(q->name, name)) {
732 switch (type) {
733 case HTTP_ARG_TYPE_RAW:
734 if (len != NULL)
735 *len = q->len;
736 *out = q->value;
737 return (KORE_RESULT_OK);
738 case HTTP_ARG_TYPE_BYTE:
739 COPY_ARG_TYPE(*(u_int8_t *)q->value,
740 len, u_int8_t);
741 return (KORE_RESULT_OK);
742 case HTTP_ARG_TYPE_INT16:
743 COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t);
744 return (KORE_RESULT_OK);
745 case HTTP_ARG_TYPE_UINT16:
746 COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t);
747 return (KORE_RESULT_OK);
748 case HTTP_ARG_TYPE_INT32:
749 COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t);
750 return (KORE_RESULT_OK);
751 case HTTP_ARG_TYPE_UINT32:
752 COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t);
753 return (KORE_RESULT_OK);
754 case HTTP_ARG_TYPE_INT64:
755 COPY_AS_INTTYPE_64(int64_t, 1);
756 return (KORE_RESULT_OK);
757 case HTTP_ARG_TYPE_UINT64:
758 COPY_AS_INTTYPE_64(u_int64_t, 0);
759 return (KORE_RESULT_OK);
760 case HTTP_ARG_TYPE_STRING:
761 CACHE_STRING();
762 *out = q->s_value;
763 if (len != NULL)
764 *len = q->s_len - 1;
765 return (KORE_RESULT_OK);
766 default:
767 return (KORE_RESULT_ERROR);
768 }
769 }
742 if (strcmp(q->name, name))
743 continue;
744
745 switch (type) {
746 case HTTP_ARG_TYPE_RAW:
747 *out = q->s_value;
748 return (KORE_RESULT_OK);
749 case HTTP_ARG_TYPE_BYTE:
750 COPY_ARG_TYPE(*(u_int8_t *)q->s_value, u_int8_t);
751 return (KORE_RESULT_OK);
752 case HTTP_ARG_TYPE_INT16:
753 COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t);
754 return (KORE_RESULT_OK);
755 case HTTP_ARG_TYPE_UINT16:
756 COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t);
757 return (KORE_RESULT_OK);
758 case HTTP_ARG_TYPE_INT32:
759 COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t);
760 return (KORE_RESULT_OK);
761 case HTTP_ARG_TYPE_UINT32:
762 COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t);
763 return (KORE_RESULT_OK);
764 case HTTP_ARG_TYPE_INT64:
765 COPY_AS_INTTYPE_64(int64_t, 1);
766 return (KORE_RESULT_OK);
767 case HTTP_ARG_TYPE_UINT64:
768 COPY_AS_INTTYPE_64(u_int64_t, 0);
769 return (KORE_RESULT_OK);
770 case HTTP_ARG_TYPE_STRING:
771 *out = q->s_value;
772 return (KORE_RESULT_OK);
773 default:
774 break;
775 }
776
777 return (KORE_RESULT_ERROR);
770778 }
771779
772780 return (KORE_RESULT_ERROR);
820828 return (KORE_RESULT_OK);
821829 }
822830
823 int
824 http_file_lookup(struct http_request *req, const char *name, char **fname,
825 u_int8_t **data, u_int32_t *len)
831 struct http_file *
832 http_file_lookup(struct http_request *req, const char *name)
826833 {
827834 struct http_file *f;
828835
829836 TAILQ_FOREACH(f, &(req->files), list) {
830 if (!strcmp(f->name, name)) {
831 *len = f->len;
832 *data = f->data;
833 *fname = f->filename;
834 return (KORE_RESULT_OK);
835 }
836 }
837
838 return (KORE_RESULT_ERROR);
839 }
840
841 int
842 http_populate_multipart_form(struct http_request *req, int *v)
843 {
844 int h, i, c, l;
845 u_int32_t blen, slen, len;
846 u_int8_t *s, *end, *e, *end_headers, *data;
847 char *d, *val, *type, *boundary, *fname;
848 char *headers[5], *args[5], *opt[5], *name;
849
850 *v = 0;
837 if (!strcmp(f->name, name))
838 return (f);
839 }
840
841 return (NULL);
842 }
843
844 ssize_t
845 http_file_read(struct http_file *file, void *buf, size_t len)
846 {
847 ssize_t ret;
848 size_t toread, off;
849
850 if (file->length < file->offset)
851 return (-1);
852 if ((file->offset + len) < file->offset)
853 return (-1);
854 if ((file->position + file->offset) < file->position)
855 return (-1);
856
857 off = file->position + file->offset;
858 toread = MIN(len, (file->length - file->offset));
859 if (toread <= 0)
860 return (0);
861
862 if (file->req->http_body_fd != -1) {
863 if (lseek(file->req->http_body_fd, off, SEEK_SET) == -1) {
864 kore_log(LOG_ERR, "http_file_read: lseek(%s): %s",
865 file->req->http_body_path, errno_s);
866 return (-1);
867 }
868
869 for (;;) {
870 ret = read(file->req->http_body_fd, buf, toread);
871 if (ret == -1) {
872 if (errno == EINTR)
873 continue;
874 kore_log(LOG_ERR, "failed to read %s: %s",
875 file->req->http_body_path, errno_s);
876 return (-1);
877 }
878 if (ret == 0)
879 return (0);
880 break;
881 }
882 } else if (file->req->http_body != NULL) {
883 if (off > file->req->http_body->length)
884 return (0);
885 memcpy(buf, file->req->http_body->data + off, toread);
886 ret = toread;
887 } else {
888 kore_log(LOG_ERR, "http_file_read: called without body");
889 return (-1);
890 }
891
892 file->offset += (size_t)ret;
893 return (ret);
894 }
895
896 void
897 http_file_rewind(struct http_file *file)
898 {
899 file->offset = 0;
900 }
901
902 void
903 http_populate_post(struct http_request *req)
904 {
905 ssize_t ret;
906 int i, v;
907 struct kore_buf *body;
908 char data[BUFSIZ];
909 char *args[HTTP_MAX_QUERY_ARGS], *val[3], *string;
851910
852911 if (req->method != HTTP_METHOD_POST)
853 return (KORE_RESULT_ERROR);
912 return;
913
914 if (req->http_body != NULL) {
915 body = NULL;
916 req->http_body->offset = req->content_length;
917 string = kore_buf_stringify(req->http_body, NULL);
918 } else {
919 body = kore_buf_alloc(128);
920 for (;;) {
921 ret = http_body_read(req, data, sizeof(data));
922 if (ret == -1)
923 goto out;
924 if (ret == 0)
925 break;
926 kore_buf_append(body, data, ret);
927 }
928 string = kore_buf_stringify(body, NULL);
929 }
930
931 v = kore_split_string(string, "&", args, HTTP_MAX_QUERY_ARGS);
932 for (i = 0; i < v; i++) {
933 kore_split_string(args[i], "=", val, 3);
934 if (val[0] != NULL && val[1] != NULL)
935 http_argument_add(req, val[0], val[1]);
936 }
937
938 out:
939 if (body != NULL)
940 kore_buf_free(body);
941 }
942
943 void
944 http_populate_get(struct http_request *req)
945 {
946 int i, v;
947 char *query, *args[HTTP_MAX_QUERY_ARGS], *val[3];
948
949 if (req->method != HTTP_METHOD_GET || req->query_string == NULL)
950 return;
951
952 query = kore_strdup(req->query_string);
953 v = kore_split_string(query, "&", args, HTTP_MAX_QUERY_ARGS);
954 for (i = 0; i < v; i++) {
955 kore_split_string(args[i], "=", val, 3);
956 if (val[0] != NULL && val[1] != NULL)
957 http_argument_add(req, val[0], val[1]);
958 }
959
960 kore_free(query);
961 }
962
963 void
964 http_populate_multipart_form(struct http_request *req)
965 {
966 int h, blen;
967 struct kore_buf *in, *out;
968 char *type, *val, *args[3];
969 char boundary[HTTP_BOUNDARY_MAX];
970
971 if (req->method != HTTP_METHOD_POST)
972 return;
854973
855974 if (!http_request_header(req, "content-type", &type))
856 return (KORE_RESULT_ERROR);
975 return;
857976
858977 h = kore_split_string(type, ";", args, 3);
859 if (h != 2) {
860 kore_mem_free(type);
861 return (KORE_RESULT_ERROR);
862 }
863
864 if (strcasecmp(args[0], "multipart/form-data")) {
865 kore_mem_free(type);
866 return (KORE_RESULT_ERROR);
867 }
868
869 if ((val = strchr(args[1], '=')) == NULL) {
870 kore_mem_free(type);
871 return (KORE_RESULT_ERROR);
872 }
978 if (h != 2)
979 return;
980
981 if (strcasecmp(args[0], "multipart/form-data"))
982 return;
983
984 if ((val = strchr(args[1], '=')) == NULL)
985 return;
873986
874987 val++;
875 slen = strlen(val);
876 boundary = kore_malloc(slen + 3);
877 if (!kore_snprintf(boundary, slen + 3, &l, "--%s", val)) {
878 kore_mem_free(boundary);
879 kore_mem_free(type);
880 return (KORE_RESULT_ERROR);
881 }
882
883 slen = l;
884 kore_mem_free(type);
885
886 req->multipart_body = http_body_bytes(req, &blen);
887 if (slen < 3 || blen < (slen * 2)) {
888 kore_mem_free(boundary);
889 return (KORE_RESULT_ERROR);
890 }
891
892 end = req->multipart_body + blen - 2;
893 if (end < req->multipart_body || (end - 2) < req->multipart_body) {
894 kore_mem_free(boundary);
895 return (KORE_RESULT_ERROR);
896 }
897
898 if (memcmp((end - slen - 2), boundary, slen) ||
899 memcmp((end - 2), "--", 2)) {
900 kore_mem_free(boundary);
901 return (KORE_RESULT_ERROR);
902 }
903
904 s = req->multipart_body + slen + 2;
905 while (s < end) {
906 e = kore_mem_find(s, end - s, boundary, slen);
907 if (e == NULL) {
908 kore_mem_free(boundary);
909 return (KORE_RESULT_ERROR);
910 }
911
912 *(e - 2) = '\0';
913 end_headers = kore_mem_find(s, (e - 2) - s, "\r\n\r\n", 4);
914 if (end_headers == NULL) {
915 kore_mem_free(boundary);
916 return (KORE_RESULT_ERROR);
917 }
918
919 *end_headers = '\0';
920 data = end_headers + 4;
921
922 h = kore_split_string((char *)s, "\r\n", headers, 5);
923 for (i = 0; i < h; i++) {
924 c = kore_split_string(headers[i], ":", args, 5);
925 if (c != 2)
926 continue;
927
928 /* Ignore other headers for now. */
929 if (strcasecmp(args[0], "content-disposition"))
930 continue;
931
932 for (d = args[1]; isspace(*d); d++)
933 ;
934
935 c = kore_split_string(d, ";", opt, 5);
936 if (c < 2)
937 continue;
938
939 if (strcasecmp(opt[0], "form-data"))
940 continue;
941
942 if ((val = strchr(opt[1], '=')) == NULL)
943 continue;
944 if (strlen(val) < 3)
945 continue;
946
947 val++;
948 kore_strip_chars(val, '"', &name);
949
950 if (opt[2] == NULL) {
951 *v = *v + 1;
952 http_argument_add(req, name,
953 data, (e - 2) - data, HTTP_ARG_TYPE_STRING);
954 kore_mem_free(name);
955 continue;
988 blen = snprintf(boundary, sizeof(boundary), "--%s", val);
989 if (blen == -1 || (size_t)blen >= sizeof(boundary))
990 return;
991
992 in = kore_buf_alloc(128);
993 out = kore_buf_alloc(128);
994
995 if (!multipart_find_data(in, NULL, NULL, req, boundary, blen))
996 goto cleanup;
997
998 for (;;) {
999 if (!multipart_find_data(in, NULL, NULL, req, "\r\n", 2))
1000 break;
1001 if (in->offset < 4 && req->http_body_length == 0)
1002 break;
1003 if (!multipart_find_data(in, out, NULL, req, "\r\n\r\n", 4))
1004 break;
1005 if (!multipart_parse_headers(req, in, out, boundary, blen))
1006 break;
1007
1008 kore_buf_reset(out);
1009 }
1010
1011 cleanup:
1012 kore_buf_free(in);
1013 kore_buf_free(out);
1014 }
1015
1016 ssize_t
1017 http_body_read(struct http_request *req, void *out, size_t len)
1018 {
1019 ssize_t ret;
1020 size_t toread;
1021
1022 toread = MIN(req->http_body_length, len);
1023 if (toread <= 0)
1024 return (0);
1025
1026 if (req->http_body_fd != -1) {
1027 for (;;) {
1028 ret = read(req->http_body_fd, out, toread);
1029 if (ret == -1) {
1030 if (errno == EINTR)
1031 continue;
1032 kore_log(LOG_ERR, "failed to read %s: %s",
1033 req->http_body_path, errno_s);
1034 return (-1);
9561035 }
957
958 for (d = opt[2]; isspace(*d); d++)
959 ;
960
961 len = MIN(strlen("filename="), strlen(d));
962 if (!strncasecmp(d, "filename=", len)) {
963 if ((val = strchr(d, '=')) == NULL) {
964 kore_mem_free(name);
965 continue;
966 }
967
968 val++;
969 kore_strip_chars(val, '"', &fname);
970 if (strlen(fname) > 0) {
971 *v = *v + 1;
972 http_file_add(req, name, fname,
973 data, (e - 2) - data);
974 }
975
976 kore_mem_free(fname);
977 } else {
978 kore_debug("got unknown: %s", opt[2]);
979 }
980
981 kore_mem_free(name);
982 }
983
984 s = e + slen + 2;
985 }
986
987 kore_mem_free(boundary);
988
989 return (KORE_RESULT_OK);
990 }
991
992 int
993 http_generic_404(struct http_request *req)
994 {
995 kore_debug("http_generic_404(%s, %d, %s)",
996 req->host, req->method, req->path);
997
998 http_response(req, 404, NULL, 0);
999
1000 return (KORE_RESULT_OK);
1001 }
1002
1003 char *
1004 http_body_text(struct http_request *req)
1005 {
1006 u_int32_t len;
1007 u_int8_t *data;
1008 char *text;
1009
1010 if (req->http_body == NULL)
1011 return (NULL);
1012
1013 data = kore_buf_release(req->http_body, &len);
1014 req->http_body = NULL;
1015 len++;
1016
1017 text = kore_malloc(len);
1018 kore_strlcpy(text, (char *)data, len);
1019 kore_mem_free(data);
1020
1021 return (text);
1022 }
1023
1024 u_int8_t *
1025 http_body_bytes(struct http_request *req, u_int32_t *len)
1026 {
1027 u_int8_t *data;
1028
1029 if (req->http_body == NULL)
1030 return (NULL);
1031
1032 data = kore_buf_release(req->http_body, len);
1033 req->http_body = NULL;
1034
1035 return (data);
1036 if (ret == 0)
1037 return (0);
1038 break;
1039 }
1040 } else if (req->http_body != NULL) {
1041 memcpy(out,
1042 (req->http_body->data + req->http_body->offset), toread);
1043 req->http_body->offset += toread;
1044 ret = toread;
1045 } else {
1046 kore_log(LOG_ERR, "http_body_read: called without body");
1047 return (-1);
1048 }
1049
1050 req->http_body_length -= (size_t)ret;
1051 req->http_body_offset += (size_t)ret;
1052
1053 return (ret);
10361054 }
10371055
10381056 int
10741092 return (KORE_RESULT_OK);
10751093 }
10761094
1095 static int
1096 multipart_find_data(struct kore_buf *in, struct kore_buf *out,
1097 size_t *olen, struct http_request *req, const void *needle, size_t len)
1098 {
1099 ssize_t ret;
1100 size_t left;
1101 u_int8_t *p, first, data[4096];
1102
1103 if (olen != NULL)
1104 *olen = 0;
1105
1106 first = *(const u_int8_t *)needle;
1107 for (;;) {
1108 if (in->offset < len) {
1109 ret = http_body_read(req, data, sizeof(data));
1110 if (ret == -1)
1111 return (KORE_RESULT_ERROR);
1112 if (ret == 0)
1113 return (KORE_RESULT_ERROR);
1114
1115 kore_buf_append(in, data, ret);
1116 continue;
1117 }
1118
1119 p = kore_mem_find(in->data, in->offset, &first, 1);
1120 if (p == NULL) {
1121 if (out != NULL)
1122 kore_buf_append(out, in->data, in->offset);
1123 if (olen != NULL)
1124 *olen += in->offset;
1125 kore_buf_reset(in);
1126 continue;
1127 }
1128
1129 left = in->offset - (p - in->data);
1130 if (left < len) {
1131 if (out != NULL)
1132 kore_buf_append(out, in->data, (p - in->data));
1133 if (olen != NULL)
1134 *olen += (p - in->data);
1135 memmove(in->data, p, left);
1136 in->offset = left;
1137 continue;
1138 }
1139
1140 if (!memcmp(p, needle, len)) {
1141 if (out != NULL)
1142 kore_buf_append(out, in->data, p - in->data);
1143 if (olen != NULL)
1144 *olen += (p - in->data);
1145
1146 in->offset = left - len;
1147 if (in->offset > 0)
1148 memmove(in->data, p + len, in->offset);
1149 return (KORE_RESULT_OK);
1150 }
1151
1152 if (out != NULL)
1153 kore_buf_append(out, in->data, (p - in->data) + 1);
1154 if (olen != NULL)
1155 *olen += (p - in->data) + 1;
1156
1157 in->offset = left - 1;
1158 if (in->offset > 0)
1159 memmove(in->data, p + 1, in->offset);
1160 }
1161
1162 return (KORE_RESULT_ERROR);
1163 }
1164
1165 static int
1166 multipart_parse_headers(struct http_request *req, struct kore_buf *in,
1167 struct kore_buf *hbuf, const char *boundary, const int blen)
1168 {
1169 int h, c, i;
1170 char *headers[5], *args[5], *opt[5];
1171 char *d, *val, *name, *fname, *string;
1172
1173 string = kore_buf_stringify(hbuf, NULL);
1174 h = kore_split_string(string, "\r\n", headers, 5);
1175 for (i = 0; i < h; i++) {
1176 c = kore_split_string(headers[i], ":", args, 5);
1177 if (c != 2)
1178 continue;
1179
1180 /* Ignore other headers for now. */
1181 if (strcasecmp(args[0], "content-disposition"))
1182 continue;
1183
1184 for (d = args[1]; isspace(*d); d++)
1185 ;
1186
1187 c = kore_split_string(d, ";", opt, 5);
1188 if (c < 2)
1189 continue;
1190
1191 if (strcasecmp(opt[0], "form-data"))
1192 continue;
1193
1194 if ((val = strchr(opt[1], '=')) == NULL)
1195 continue;
1196 if (strlen(val) < 3)
1197 continue;
1198
1199 val++;
1200 kore_strip_chars(val, '"', &name);
1201
1202 if (opt[2] == NULL) {
1203 multipart_add_field(req, in, name, boundary, blen);
1204 kore_free(name);
1205 continue;
1206 }
1207
1208 for (d = opt[2]; isspace(*d); d++)
1209 ;
1210
1211 if (!strncasecmp(d, "filename=", 9)) {
1212 if ((val = strchr(d, '=')) == NULL) {
1213 kore_free(name);
1214 continue;
1215 }
1216
1217 val++;
1218 kore_strip_chars(val, '"', &fname);
1219 if (strlen(fname) > 0) {
1220 multipart_file_add(req,
1221 in, name, fname, boundary, blen);
1222 }
1223 kore_free(fname);
1224 } else {
1225 kore_debug("got unknown: %s", opt[2]);
1226 }
1227
1228 kore_free(name);
1229 }
1230
1231 return (KORE_RESULT_OK);
1232 }
1233
10771234 static void
1078 http_argument_add(struct http_request *req, const char *name,
1079 void *value, u_int32_t len, int type)
1235 multipart_add_field(struct http_request *req, struct kore_buf *in,
1236 const char *name, const char *boundary, const int blen)
1237 {
1238 struct kore_buf *data;
1239 char *string;
1240
1241 data = kore_buf_alloc(128);
1242
1243 if (!multipart_find_data(in, data, NULL, req, boundary, blen)) {
1244 kore_buf_free(data);
1245 return;
1246 }
1247
1248 if (data->offset < 3) {
1249 kore_buf_free(data);
1250 return;
1251 }
1252
1253 data->offset -= 2;
1254 string = kore_buf_stringify(data, NULL);
1255 http_argument_add(req, name, string);
1256 kore_buf_free(data);
1257 }
1258
1259 static void
1260 multipart_file_add(struct http_request *req, struct kore_buf *in,
1261 const char *name, const char *fname, const char *boundary, const int blen)
1262 {
1263 struct http_file *f;
1264 size_t position, len;
1265
1266 position= req->http_body_offset - in->offset;
1267 if (!multipart_find_data(in, NULL, &len, req, boundary, blen))
1268 return;
1269
1270 if (len < 3)
1271 return;
1272 len -= 2;
1273
1274 f = kore_malloc(sizeof(struct http_file));
1275 f->req = req;
1276 f->offset = 0;
1277 f->length = len;
1278 f->position = position;
1279 f->name = kore_strdup(name);
1280 f->filename = kore_strdup(fname);
1281
1282 TAILQ_INSERT_TAIL(&(req->files), f, list);
1283 }
1284
1285 static void
1286 http_argument_add(struct http_request *req, const char *name, char *value)
10801287 {
10811288 struct http_arg *q;
10821289 struct kore_handler_params *p;
10831290
1084 if (len == 0 || value == NULL) {
1085 kore_debug("http_argument_add: with NULL value");
1086 return;
1087 }
1088
10891291 TAILQ_FOREACH(p, &(req->hdlr->params), list) {
10901292 if (p->method != req->method)
10911293 continue;
1092
1093 if (!strcmp(p->name, name)) {
1094 if (type == HTTP_ARG_TYPE_STRING) {
1095 http_argument_urldecode(value);
1096 len = strlen(value);
1097 }
1098
1099 if (kore_validator_check(req, p->validator, value)) {
1100 q = kore_malloc(sizeof(struct http_arg));
1101 q->len = len;
1102 q->s_value = NULL;
1103 q->name = kore_strdup(name);
1104 q->value = kore_malloc(len);
1105 memcpy(q->value, value, len);
1106 TAILQ_INSERT_TAIL(&(req->arguments), q, list);
1107 }
1108
1109 return;
1110 }
1111 }
1112 }
1113
1114 static void
1115 http_file_add(struct http_request *req, const char *name, const char *filename,
1116 u_int8_t *data, u_int32_t len)
1117 {
1118 struct http_file *f;
1119
1120 f = kore_malloc(sizeof(struct http_file));
1121 f->len = len;
1122 f->data = data;
1123 f->name = kore_strdup(name);
1124 f->filename = kore_strdup(filename);
1125
1126 TAILQ_INSERT_TAIL(&(req->files), f, list);
1294 if (strcmp(p->name, name))
1295 continue;
1296
1297 http_argument_urldecode(value);
1298 if (!kore_validator_check(req, p->validator, value))
1299 break;
1300
1301 q = kore_malloc(sizeof(struct http_arg));
1302 q->name = kore_strdup(name);
1303 q->s_value = kore_strdup(value);
1304 TAILQ_INSERT_TAIL(&(req->arguments), q, list);
1305 break;
1306 }
11271307 }
11281308
11291309 static int
11301310 http_body_recv(struct netbuf *nb)
11311311 {
1312 ssize_t ret;
1313 u_int64_t bytes_left;
11321314 struct http_request *req = (struct http_request *)nb->extra;
11331315
1134 kore_buf_append(req->http_body, nb->buf, nb->s_off);
1135
1136 req->flags |= HTTP_REQUEST_COMPLETE;
1137 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
1138
1139 nb->extra = NULL;
1140 kore_debug("received all body data for request %p", req);
1316 if (req->http_body_fd != -1) {
1317 ret = write(req->http_body_fd, nb->buf, nb->s_off);
1318 if (ret == -1 || (size_t)ret != nb->s_off) {
1319 req->flags |= HTTP_REQUEST_DELETE;
1320 http_error_response(req->owner, 500);
1321 return (KORE_RESULT_ERROR);
1322 }
1323 } else if (req->http_body != NULL) {
1324 kore_buf_append(req->http_body, nb->buf, nb->s_off);
1325 } else {
1326 req->flags |= HTTP_REQUEST_DELETE;
1327 http_error_response(req->owner, 500);
1328 return (KORE_RESULT_ERROR);
1329 }
1330
1331 req->content_length -= nb->s_off;
1332
1333 if (req->content_length == 0) {
1334 nb->extra = NULL;
1335 http_request_wakeup(req);
1336 req->flags |= HTTP_REQUEST_COMPLETE;
1337 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
1338 req->content_length = req->http_body_length;
1339 if (!http_body_rewind(req)) {
1340 req->flags |= HTTP_REQUEST_DELETE;
1341 http_error_response(req->owner, 500);
1342 return (KORE_RESULT_ERROR);
1343 }
1344 net_recv_reset(nb->owner, http_header_max, http_header_recv);
1345 } else {
1346 bytes_left = req->content_length;
1347 net_recv_reset(nb->owner,
1348 MIN(bytes_left, NETBUF_SEND_PAYLOAD_MAX),
1349 http_body_recv);
1350 }
11411351
11421352 return (KORE_RESULT_OK);
11431353 }
11441354
1355 static int
1356 http_body_rewind(struct http_request *req)
1357 {
1358 if (req->http_body_fd != -1) {
1359 if (lseek(req->http_body_fd, 0, SEEK_SET) == -1) {
1360 kore_log(LOG_ERR, "lseek(%s) failed: %s",
1361 req->http_body_path, errno_s);
1362 return (KORE_RESULT_ERROR);
1363 }
1364 } else {
1365 kore_buf_reset(req->http_body);
1366 }
1367
1368 return (KORE_RESULT_OK);
1369 }
1370
11451371 static void
1146 http_error_response(struct connection *c, struct spdy_stream *s, int status)
1147 {
1148 kore_debug("http_error_response(%p, %p, %d)", c, s, status);
1372 http_error_response(struct connection *c, int status)
1373 {
1374 kore_debug("http_error_response(%p, %d)", c, status);
11491375
11501376 switch (c->proto) {
1151 case CONN_PROTO_SPDY:
1152 http_response_spdy(NULL, c, s, status, NULL, 0);
1153 break;
11541377 case CONN_PROTO_HTTP:
1155 if (s != NULL)
1156 kore_log(LOG_NOTICE, "http_error_response: s != NULL");
11571378 http_response_normal(NULL, c, status, NULL, 0);
11581379 break;
11591380 default:
11631384 }
11641385
11651386 static void
1166 http_response_spdy(struct http_request *req, struct connection *c,
1167 struct spdy_stream *s, int status, void *d, u_int32_t len)
1168 {
1169 u_int32_t hlen;
1170 struct http_header *hdr;
1171 u_int8_t *htext;
1172 struct spdy_header_block *hblock;
1173 char sbuf[512];
1174
1175 (void)snprintf(sbuf, sizeof(sbuf), "%d %s",
1176 status, http_status_text(status));
1177
1178 hblock = spdy_header_block_create(SPDY_HBLOCK_NORMAL);
1179 spdy_header_block_add(hblock, ":status", sbuf);
1180 spdy_header_block_add(hblock, ":version", "HTTP/1.1");
1181 spdy_header_block_add(hblock, ":server", http_version_spdy);
1182
1183 if (http_hsts_enable) {
1184 (void)snprintf(sbuf, sizeof(sbuf),
1185 "max-age=%" PRIu64 "; includeSubDomains", http_hsts_enable);
1186 spdy_header_block_add(hblock,
1187 ":strict-transport-security", sbuf);
1188 }
1189
1190 if (req != NULL) {
1191 TAILQ_FOREACH(hdr, &(req->resp_headers), list)
1192 spdy_header_block_add(hblock, hdr->header, hdr->value);
1193 }
1194
1195 htext = spdy_header_block_release(c, hblock, &hlen);
1196 if (htext == NULL) {
1197 spdy_session_teardown(c, SPDY_SESSION_ERROR_INTERNAL);
1198 return;
1199 }
1200
1201 spdy_frame_send(c, SPDY_CTRL_FRAME_SYN_REPLY, 0, hlen, s, 0);
1202 net_send_queue(c, htext, hlen, NULL, NETBUF_LAST_CHAIN);
1203 kore_mem_free(htext);
1204
1205 if (len > 0 && req != NULL && req->method != HTTP_METHOD_HEAD) {
1206 s->send_size += len;
1207 s->flags |= SPDY_DATAFRAME_PRELUDE;
1208
1209 if (d != NULL)
1210 net_send_queue(c, d, len, s, NETBUF_LAST_CHAIN);
1211 }
1212
1213 if ((req != NULL && req->method == HTTP_METHOD_HEAD) ||
1214 (len == 0 && !(s->flags & SPDY_NO_CLOSE))) {
1215 spdy_frame_send(c, SPDY_DATA_FRAME, FLAG_FIN, 0, s, 0);
1216 spdy_stream_close(c, s, SPDY_KEEP_NETBUFS);
1217 }
1218 }
1219
1220 static void
12211387 http_response_normal(struct http_request *req, struct connection *c,
1222 int status, void *d, u_int32_t len)
1388 int status, const void *d, size_t len)
12231389 {
12241390 struct http_header *hdr;
12251391 char *conn;
12411407 if ((*conn == 'c' || *conn == 'C') &&
12421408 !strcasecmp(conn, "close"))
12431409 connection_close = 1;
1244 kore_mem_free(conn);
1245 }
1246 }
1247
1248 if (http_keepalive_time && connection_close == 0) {
1249 kore_buf_appendf(header_buf, "connection: keep-alive\r\n");
1250 kore_buf_appendf(header_buf, "keep-alive: timeout=%d\r\n",
1251 http_keepalive_time);
1252 } else {
1253 c->flags |= CONN_CLOSE_EMPTY;
1254 kore_buf_appendf(header_buf, "connection: close\r\n");
1410 }
1411 }
1412
1413 /* Note that req CAN be NULL. */
1414 if (req != NULL && req->owner->proto != CONN_PROTO_WEBSOCKET) {
1415 if (http_keepalive_time && connection_close == 0) {
1416 kore_buf_appendf(header_buf,
1417 "connection: keep-alive\r\n");
1418 kore_buf_appendf(header_buf,
1419 "keep-alive: timeout=%d\r\n", http_keepalive_time);
1420 } else {
1421 c->flags |= CONN_CLOSE_EMPTY;
1422 kore_buf_appendf(header_buf, "connection: close\r\n");
1423 }
12551424 }
12561425
12571426 if (http_hsts_enable) {
12701439 if (status != 204 && status >= 200 &&
12711440 !(req->flags & HTTP_REQUEST_NO_CONTENT_LENGTH)) {
12721441 kore_buf_appendf(header_buf,
1273 "content-length: %d\r\n", len);
1442 "content-length: %zu\r\n", len);
12741443 }
12751444 } else {
12761445 if (status != 204 && status >= 200) {
12771446 kore_buf_appendf(header_buf,
1278 "content-length: %d\r\n", len);
1447 "content-length: %zu\r\n", len);
12791448 }
12801449 }
12811450
12821451 kore_buf_append(header_buf, "\r\n", 2);
1283 net_send_queue(c, header_buf->data, header_buf->offset,
1284 NULL, NETBUF_LAST_CHAIN);
1452 net_send_queue(c, header_buf->data, header_buf->offset);
12851453
12861454 if (d != NULL && req != NULL && req->method != HTTP_METHOD_HEAD)
1287 net_send_queue(c, d, len, NULL, NETBUF_LAST_CHAIN);
1455 net_send_queue(c, d, len);
12881456
12891457 if (!(c->flags & CONN_CLOSE_EMPTY))
12901458 net_recv_reset(c, http_header_max, http_header_recv);
14231591
14241592 return (r);
14251593 }
1594
1595 const char *
1596 http_method_text(int method)
1597 {
1598 char *r;
1599
1600 switch(method) {
1601 case HTTP_METHOD_GET:
1602 r = "GET";
1603 break;
1604 case HTTP_METHOD_POST:
1605 r = "POST";
1606 break;
1607 case HTTP_METHOD_PUT:
1608 r = "PUT";
1609 break;
1610 case HTTP_METHOD_DELETE:
1611 r = "DELETE";
1612 break;
1613 case HTTP_METHOD_HEAD:
1614 r = "HEAD";
1615 break;
1616 default:
1617 r = "";
1618 break;
1619 }
1620
1621 return (r);
1622 }
0 /*
1 * Copyright (c) 2016 Raphaël Monrouzeau <raphael.monrouzeau@gmail.com>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #include <limits.h>
17 #include <stdbool.h>
18
19 #include <yajl/yajl_tree.h>
20 #include <yajl/yajl_gen.h>
21
22 #include "kore.h"
23 #include "http.h"
24 #include "jsonrpc.h"
25
26 static void
27 init_log(struct jsonrpc_log *log)
28 {
29 log->msg = NULL;
30 log->next = log;
31 log->prev = log;
32 }
33
34 static void
35 append_log(struct jsonrpc_log *prev, int lvl, char *msg)
36 {
37 struct jsonrpc_log *new = kore_malloc(sizeof(struct jsonrpc_log));
38
39 new->lvl = lvl;
40 new->msg = msg;
41
42 new->prev = prev;
43 new->next = prev->next;
44 prev->next->prev = new;
45 prev->next = new;
46 }
47
48 static void
49 free_log(struct jsonrpc_log *root)
50 {
51 for (struct jsonrpc_log *it = root->next; it != root; it = it->next) {
52 kore_free(it);
53 }
54 }
55
56 static void
57 init_request(struct jsonrpc_request *req)
58 {
59 init_log(&req->log);
60 kore_buf_init(&req->buf, 256);
61 req->gen = NULL;
62 req->http = NULL;
63 req->json = NULL;
64 req->id = NULL;
65 req->method = NULL;
66 req->params = NULL;
67 req->log_levels = (1 << LOG_EMERG) | (1 << LOG_ERR) | (1 << LOG_WARNING)
68 | (1 << LOG_NOTICE);
69 req->flags = 0;
70 }
71
72 void
73 jsonrpc_destroy_request(struct jsonrpc_request *req)
74 {
75 if (req->gen != NULL) {
76 yajl_gen_free(req->gen);
77 req->gen = NULL;
78 }
79 if (req->json != NULL) {
80 yajl_tree_free(req->json);
81 req->json = NULL;
82 }
83 kore_buf_cleanup(&req->buf);
84 free_log(&req->log);
85 }
86
87 void
88 jsonrpc_log(struct jsonrpc_request *req, int lvl, const char *fmt, ...)
89 {
90 va_list ap;
91 char *msg;
92 size_t start = req->buf.offset;
93
94 va_start(ap, fmt);
95 kore_buf_appendv(&req->buf, fmt, ap);
96 va_end(ap);
97
98 msg = kore_buf_stringify(&req->buf, NULL) + start;
99
100 append_log(&req->log, lvl, msg);
101 }
102
103 static int
104 read_json_body(struct http_request *http_req, struct jsonrpc_request *req)
105 {
106 char *body_string;
107 ssize_t body_len = 0, chunk_len;
108 u_int8_t chunk_buffer[BUFSIZ];
109 char error_buffer[1024];
110
111 for (;;) {
112 chunk_len = http_body_read(http_req, chunk_buffer,
113 sizeof(chunk_buffer));
114 if (chunk_len == -1) {
115 jsonrpc_log(req, LOG_CRIT,
116 "Failed to read request body");
117 return (JSONRPC_SERVER_ERROR);
118 }
119
120 if (chunk_len == 0)
121 break;
122
123 if (body_len > SSIZE_MAX - chunk_len) {
124 jsonrpc_log(req, LOG_CRIT,
125 "Request body bigger than the platform accepts");
126 return (JSONRPC_SERVER_ERROR);
127 }
128 body_len += chunk_len;
129
130 kore_buf_append(&req->buf, chunk_buffer, chunk_len);
131 }
132
133 /* Grab our body data as a NUL-terminated string. */
134 body_string = kore_buf_stringify(&req->buf, NULL);
135
136 /* Parse the body via yajl now. */
137 *error_buffer = 0;
138 req->json = yajl_tree_parse(body_string, error_buffer,
139 sizeof(error_buffer));
140 if (req->json == NULL) {
141 if (strlen(error_buffer)) {
142 jsonrpc_log(req, LOG_ERR, "Invalid json: %s",
143 error_buffer);
144 } else {
145 jsonrpc_log(req, LOG_ERR, "Invalid json");
146 }
147 return (JSONRPC_PARSE_ERROR);
148 }
149
150 return (0);
151 }
152
153 static int
154 parse_json_body(struct jsonrpc_request *req)
155 {
156 static const char *proto_path[] = { "jsonrpc", NULL };
157 static const char *id_path[] = { "id", NULL };
158 static const char *method_path[] = { "method", NULL };
159 static const char *params_path[] = { "params", NULL };
160
161 /* Check protocol first. */
162 yajl_val proto = yajl_tree_get(req->json, proto_path, yajl_t_string);
163 if (proto == NULL) {
164 jsonrpc_log(req, LOG_ERR,
165 "JSON-RPC protocol MUST be indicated and \"2.0\"");
166 return (JSONRPC_PARSE_ERROR);
167 }
168
169 char *proto_string = YAJL_GET_STRING(proto);
170 if (proto_string == NULL) {
171 jsonrpc_log(req, LOG_ERR,
172 "JSON-RPC protocol MUST be indicated and \"2.0\"");
173 return (JSONRPC_PARSE_ERROR);
174 }
175
176 if (strcmp("2.0", proto_string) != 0) {
177 jsonrpc_log(req, LOG_ERR,
178 "JSON-RPC protocol MUST be indicated and \"2.0\"");
179 return (JSONRPC_PARSE_ERROR);
180 }
181
182 /* Check id. */
183 if ((req->id = yajl_tree_get(req->json, id_path, yajl_t_any)) != NULL) {
184 if (YAJL_IS_NUMBER(req->id)) {
185 if (!YAJL_IS_INTEGER(req->id)) {
186 jsonrpc_log(req, LOG_ERR,
187 "JSON-RPC id SHOULD NOT contain fractional"
188 " parts");
189 return (JSONRPC_PARSE_ERROR);
190 }
191 } else if (!YAJL_IS_STRING(req->id)) {
192 jsonrpc_log(req, LOG_ERR,
193 "JSON-RPC id MUST contain a String or Number");
194 return (JSONRPC_PARSE_ERROR);
195 }
196 }
197
198 /* Check method. */
199 if ((req->method = YAJL_GET_STRING(yajl_tree_get(req->json, method_path,
200 yajl_t_string))) == NULL) {
201 jsonrpc_log(req, LOG_ERR,
202 "JSON-RPC method MUST exist and be a String");
203 return (JSONRPC_PARSE_ERROR);
204 }
205
206 /* Check params. */
207 req->params = yajl_tree_get(req->json, params_path, yajl_t_any);
208 if (!(req->params == NULL || YAJL_IS_ARRAY(req->params)
209 || YAJL_IS_OBJECT(req->params))) {
210 jsonrpc_log(req, LOG_ERR,
211 "JSON-RPC params MUST be Object or Array");
212 return (JSONRPC_PARSE_ERROR);
213 }
214
215 return (0);
216 }
217
218 int
219 jsonrpc_read_request(struct http_request *http_req, struct jsonrpc_request *req)
220 {
221 int ret;
222
223 init_request(req);
224 req->http = http_req;
225
226 if ((ret = read_json_body(http_req, req)) != 0)
227 return (ret);
228
229 return parse_json_body(req);
230 }
231
232 static int
233 write_id(yajl_gen gen, yajl_val id)
234 {
235 int status;
236
237 if (YAJL_GEN_KO(status = YAJL_GEN_CONST_STRING(gen, "id")))
238 return (status);
239
240 if (YAJL_IS_NULL(id))
241 return yajl_gen_null(gen);
242
243 if (YAJL_IS_NUMBER(id)) {
244 if (YAJL_IS_INTEGER(id))
245 return yajl_gen_integer(gen, YAJL_GET_INTEGER(id));
246 return yajl_gen_null(gen);
247 }
248
249 if (YAJL_IS_STRING(id)) {
250 char *id_str = YAJL_GET_STRING(id);
251
252 return yajl_gen_string(gen, (unsigned char *)id_str,
253 strlen(id_str));
254 }
255
256 return yajl_gen_null(gen);
257 }
258
259 static int
260 open_response(yajl_gen genctx, yajl_val id)
261 {
262 int status;
263
264 if (YAJL_GEN_KO(status = yajl_gen_map_open(genctx)))
265 goto failed;
266 if (YAJL_GEN_KO(status = YAJL_GEN_CONST_STRING(genctx, "jsonrpc")))
267 goto failed;
268 if (YAJL_GEN_KO(status = YAJL_GEN_CONST_STRING(genctx, "2.0")))
269 goto failed;
270 status = write_id(genctx, id);
271 failed:
272 return (status);
273 }
274
275 static int
276 close_response(yajl_gen genctx)
277 {
278 int status;
279
280 if (YAJL_GEN_KO(status = yajl_gen_map_close(genctx)))
281 goto failed;
282 status = yajl_gen_map_close(genctx);
283 failed:
284 return (status);
285 }
286
287 static int
288 write_log(struct jsonrpc_request *req)
289 {
290 bool wrote_smth = false;
291 int status = 0;
292
293 for (struct jsonrpc_log *log = req->log.next; log != &req->log;
294 log = log->next) {
295
296 if (((1 << log->lvl) & req->log_levels) == 0)
297 continue;
298
299 if (!wrote_smth) {
300 if (YAJL_GEN_KO(status = YAJL_GEN_CONST_STRING(req->gen,
301 "data")))
302 goto failed;
303 if (YAJL_GEN_KO(status = yajl_gen_array_open(req->gen)))
304 goto failed;
305 yajl_gen_config(req->gen, yajl_gen_validate_utf8, 1);
306 wrote_smth = true;
307 }
308
309 if (YAJL_GEN_KO(status = yajl_gen_array_open(req->gen)))
310 goto failed;
311 if (YAJL_GEN_KO(status = yajl_gen_integer(req->gen, log->lvl)))
312 goto failed;
313 if (YAJL_GEN_KO(status = yajl_gen_string(req->gen,
314 (unsigned char *)log->msg, strlen(log->msg))))
315 goto failed;
316 if (YAJL_GEN_KO(status = yajl_gen_array_close(req->gen)))
317 goto failed;
318 }
319
320 if (wrote_smth) {
321 yajl_gen_config(req->gen, yajl_gen_validate_utf8, 0);
322 status = yajl_gen_array_close(req->gen);
323 }
324 failed:
325 return (status);
326 }
327
328 static int
329 write_error(struct jsonrpc_request *req, int code, const char *message)
330 {
331 int status;
332
333 yajl_gen_config(req->gen, yajl_gen_validate_utf8, 0);
334
335 if (YAJL_GEN_KO(status = open_response(req->gen, req->id)))
336 goto failed;
337 if (YAJL_GEN_KO(status = YAJL_GEN_CONST_STRING(req->gen, "error")))
338 goto failed;
339 if (YAJL_GEN_KO(status = yajl_gen_map_open(req->gen)))
340 goto failed;
341 if (YAJL_GEN_KO(status = YAJL_GEN_CONST_STRING(req->gen, "code")))
342 goto failed;
343 if (YAJL_GEN_KO(status = yajl_gen_integer(req->gen, code)))
344 goto failed;
345 if (YAJL_GEN_KO(status = YAJL_GEN_CONST_STRING(req->gen, "message")))
346 goto failed;
347
348 yajl_gen_config(req->gen, yajl_gen_validate_utf8, 1);
349
350 if (YAJL_GEN_KO(status = yajl_gen_string(req->gen,
351 (const unsigned char *)message, strlen(message))))
352 goto failed;
353
354 yajl_gen_config(req->gen, yajl_gen_validate_utf8, 0);
355
356 if (YAJL_GEN_KO(status = write_log(req)))
357 goto failed;
358
359 status = close_response(req->gen);
360 failed:
361 return (status);
362 }
363
364 static const char *
365 known_msg(int code)
366 {
367 switch (code) {
368 case JSONRPC_PARSE_ERROR:
369 return (JSONRPC_PARSE_ERROR_MSG);
370 case JSONRPC_INVALID_REQUEST:
371 return (JSONRPC_INVALID_REQUEST_MSG);
372 case JSONRPC_METHOD_NOT_FOUND:
373 return (JSONRPC_METHOD_NOT_FOUND_MSG);
374 case JSONRPC_INVALID_PARAMS:
375 return (JSONRPC_INVALID_PARAMS_MSG);
376 case JSONRPC_INTERNAL_ERROR:
377 return (JSONRPC_INTERNAL_ERROR_MSG);
378 case JSONRPC_SERVER_ERROR:
379 return (JSONRPC_SERVER_ERROR_MSG);
380 case JSONRPC_LIMIT_REACHED:
381 return (JSONRPC_LIMIT_REACHED_MSG);
382 default:
383 return (NULL);
384 }
385 }
386
387 int
388 jsonrpc_error(struct jsonrpc_request *req, int code, const char *msg)
389 {
390 char *msg_fallback;
391 const unsigned char *body = NULL;
392 size_t body_len = 0;
393 int status;
394
395 if (req->id == NULL)
396 goto succeeded;
397
398 if ((req->gen = yajl_gen_alloc(NULL)) == NULL) {
399 kore_log(LOG_ERR, "jsonrpc_error: Failed to allocate yajl gen");
400 goto failed;
401 }
402
403 yajl_gen_config(req->gen, yajl_gen_beautify,
404 req->flags & yajl_gen_beautify);
405
406 if (msg == NULL)
407 msg = known_msg(code);
408
409 if (msg == NULL) {
410 size_t start = req->buf.offset;
411 kore_buf_appendf(&req->buf, "%d", code);
412 msg_fallback = kore_buf_stringify(&req->buf, NULL) + start;
413 }
414
415 if (YAJL_GEN_KO(status = write_error(req, code,
416 msg ? msg : msg_fallback))) {
417 kore_log(LOG_ERR, "jsonrpc_error: Failed to yajl gen text [%d]",
418 status);
419 goto failed;
420 }
421
422 http_response_header(req->http, "content-type", "application/json");
423 yajl_gen_get_buf(req->gen, &body, &body_len);
424 succeeded:
425 http_response(req->http, 200, body, body_len);
426 if (req->gen != NULL)
427 yajl_gen_clear(req->gen);
428 jsonrpc_destroy_request(req);
429 return (KORE_RESULT_OK);
430 failed:
431 http_response(req->http, 500, NULL, 0);
432 jsonrpc_destroy_request(req);
433 return (KORE_RESULT_OK);
434 }
435
436 int
437 jsonrpc_result(struct jsonrpc_request *req,
438 int (*write_result)(struct jsonrpc_request *, void *), void *ctx)
439 {
440 const unsigned char *body = NULL;
441 size_t body_len = 0;
442
443 if (req->id == NULL)
444 goto succeeded;
445
446 if ((req->gen = yajl_gen_alloc(NULL)) == NULL) {
447 kore_log(LOG_ERR, "jsonrpc_result: Failed to allocate yajl gen");
448 goto failed;
449 }
450
451 yajl_gen_config(req->gen, yajl_gen_beautify,
452 req->flags & yajl_gen_beautify);
453
454 yajl_gen_config(req->gen, yajl_gen_validate_utf8, 0);
455
456 if (YAJL_GEN_KO(open_response(req->gen, req->id)))
457 goto failed;
458 if (YAJL_GEN_KO(YAJL_GEN_CONST_STRING(req->gen, "result")))
459 goto failed;
460 if (YAJL_GEN_KO(write_result(req, ctx)))
461 goto failed;
462 if (YAJL_GEN_KO(yajl_gen_map_close(req->gen)))
463 goto failed;
464
465 http_response_header(req->http, "content-type", "application/json");
466 yajl_gen_get_buf(req->gen, &body, &body_len);
467 succeeded:
468 http_response(req->http, 200, body, body_len);
469 if (req->gen != NULL)
470 yajl_gen_clear(req->gen);
471 jsonrpc_destroy_request(req);
472 return (KORE_RESULT_OK);
473 failed:
474 http_response(req->http, 500, NULL, 0);
475 jsonrpc_destroy_request(req);
476 return (KORE_RESULT_OK);
477 }
0 /*
1 * Copyright (c) 2016 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #include <sys/param.h>
17
18 #include <openssl/evp.h>
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <signal.h>
23 #include <unistd.h>
24
25 #include "kore.h"
26
27 #if !defined(KORE_NO_TLS)
28 struct key {
29 EVP_PKEY *pkey;
30 struct kore_domain *dom;
31 TAILQ_ENTRY(key) list;
32 };
33
34 static TAILQ_HEAD(, key) keys;
35 extern volatile sig_atomic_t sig_recv;
36 static int initialized = 0;
37
38 static void keymgr_load_privatekey(struct kore_domain *);
39 static void keymgr_msg_recv(struct kore_msg *, const void *);
40
41 static void keymgr_rsa_encrypt(struct kore_msg *, const void *,
42 struct key *);
43 static void keymgr_ecdsa_sign(struct kore_msg *, const void *,
44 struct key *);
45
46 void
47 kore_keymgr_run(void)
48 {
49 int quit;
50
51 quit = 0;
52 initialized = 1;
53 TAILQ_INIT(&keys);
54
55 kore_listener_cleanup();
56 kore_module_cleanup();
57
58 kore_domain_callback(keymgr_load_privatekey);
59 kore_worker_privdrop();
60
61 net_init();
62 kore_connection_init();
63 kore_platform_event_init();
64
65 kore_msg_worker_init();
66 kore_msg_register(KORE_MSG_KEYMGR_REQ, keymgr_msg_recv);
67
68 kore_log(LOG_NOTICE, "key manager started");
69
70 while (quit != 1) {
71 if (sig_recv != 0) {
72 switch (sig_recv) {
73 case SIGQUIT:
74 case SIGINT:
75 case SIGTERM:
76 quit = 1;
77 break;
78 default:
79 break;
80 }
81 sig_recv = 0;
82 }
83
84 kore_platform_event_wait(1000);
85 kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
86 }
87
88 kore_keymgr_cleanup();
89 kore_platform_event_cleanup();
90 kore_connection_cleanup();
91 net_cleanup();
92 }
93
94 void
95 kore_keymgr_cleanup(void)
96 {
97 struct key *key, *next;
98
99 kore_log(LOG_NOTICE, "cleaning up keys");
100
101 if (initialized == 0)
102 return;
103
104 for (key = TAILQ_FIRST(&keys); key != NULL; key = next) {
105 next = TAILQ_NEXT(key, list);
106 TAILQ_REMOVE(&keys, key, list);
107
108 EVP_PKEY_free(key->pkey);
109 kore_free(key);
110 }
111 }
112
113 static void
114 keymgr_load_privatekey(struct kore_domain *dom)
115 {
116 FILE *fp;
117 struct key *key;
118
119 if (dom->certkey == NULL)
120 return;
121
122 if ((fp = fopen(dom->certkey, "r")) == NULL)
123 fatal("failed to open private key: %s", dom->certkey);
124
125 key = kore_malloc(sizeof(*key));
126 key->dom = dom;
127
128 if ((key->pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)) == NULL)
129 fatal("PEM_read_PrivateKey: %s", ssl_errno_s);
130
131 (void)fclose(fp);
132 kore_free(dom->certkey);
133 dom->certkey = NULL;
134
135 TAILQ_INSERT_TAIL(&keys, key, list);
136 }
137
138 static void
139 keymgr_msg_recv(struct kore_msg *msg, const void *data)
140 {
141 const struct kore_keyreq *req;
142 struct key *key;
143
144 if (msg->length < sizeof(*req))
145 return;
146
147 req = (const struct kore_keyreq *)data;
148 if (msg->length != (sizeof(*req) + req->data_len))
149 return;
150
151 key = NULL;
152 TAILQ_FOREACH(key, &keys, list) {
153 if (!strncmp(key->dom->domain, req->domain, req->domain_len))
154 break;
155 }
156
157 if (key == NULL)
158 return;
159
160 switch (EVP_PKEY_id(key->pkey)) {
161 case EVP_PKEY_RSA:
162 keymgr_rsa_encrypt(msg, data, key);
163 break;
164 case EVP_PKEY_EC:
165 keymgr_ecdsa_sign(msg, data, key);
166 break;
167 default:
168 break;
169 }
170 }
171
172 static void
173 keymgr_rsa_encrypt(struct kore_msg *msg, const void *data, struct key *key)
174 {
175 int ret;
176 const struct kore_keyreq *req;
177 size_t keylen;
178 u_int8_t buf[1024];
179
180 req = (const struct kore_keyreq *)data;
181
182 keylen = RSA_size(key->pkey->pkey.rsa);
183 if (req->data_len > keylen || keylen > sizeof(buf))
184 return;
185
186 ret = RSA_private_encrypt(req->data_len, req->data,
187 buf, key->pkey->pkey.rsa, req->padding);
188 if (ret != RSA_size(key->pkey->pkey.rsa))
189 return;
190
191 kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, buf, ret);
192 }
193
194 static void
195 keymgr_ecdsa_sign(struct kore_msg *msg, const void *data, struct key *key)
196 {
197 size_t len;
198 const struct kore_keyreq *req;
199 unsigned int siglen;
200 u_int8_t sig[1024];
201
202 req = (const struct kore_keyreq *)data;
203
204 len = ECDSA_size(key->pkey->pkey.ec);
205 if (req->data_len > len || len > sizeof(sig))
206 return;
207
208 if (ECDSA_sign(key->pkey->save_type, req->data, req->data_len,
209 sig, &siglen, key->pkey->pkey.ec) == 0)
210 return;
211
212 if (siglen > sizeof(sig))
213 return;
214
215 kore_msg_send(msg->src, KORE_MSG_KEYMGR_RESP, sig, siglen);
216 }
217
218 #endif
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1414 */
1515
1616 #include <sys/types.h>
17 #include <sys/stat.h>
18
1719 #include <sys/socket.h>
1820 #include <sys/resource.h>
1921
22 #include <stdio.h>
2023 #include <netdb.h>
2124 #include <signal.h>
2225
2326 #include "kore.h"
27
28 #if !defined(KORE_NO_HTTP)
29 #include "http.h"
30 #endif
2431
2532 volatile sig_atomic_t sig_recv;
2633
3946 char *kore_pidfile = KORE_PIDFILE_DEFAULT;
4047 char *kore_tls_cipher_list = KORE_DEFAULT_CIPHER_LIST;
4148
49 extern char *__progname;
50
4251 static void usage(void);
4352 static void version(void);
4453 static void kore_server_start(void);
4857 static void
4958 usage(void)
5059 {
60 #if !defined(KORE_SINGLE_BINARY)
5161 fprintf(stderr, "Usage: kore [options | command]\n");
62 #else
63 fprintf(stderr, "Usage: %s [options]\n", __progname);
64 #endif
5265 fprintf(stderr, "\n");
5366 fprintf(stderr, "Available options:\n");
54 fprintf(stderr, "\t-c\tspecify the configuration file to use\n");
55 fprintf(stderr, "\t-d\trun with debug on (if compiled in)\n");
56 fprintf(stderr, "\t-f\tstart kore in foreground mode\n");
67 #if !defined(KORE_SINGLE_BINARY)
68 fprintf(stderr, "\t-c\tconfiguration to use\n");
69 #endif
70 #if defined(KORE_DEBUG)
71 fprintf(stderr, "\t-d\trun with debug on)\n");
72 #endif
73 fprintf(stderr, "\t-f\tstart in foreground\n");
5774 fprintf(stderr, "\t-h\tthis help text\n");
58 fprintf(stderr, "\t-n\tdo not chroot (if not starting kore as root)\n");
59 fprintf(stderr, "\t-r\tdo not runas (uid drop) (if not starting kore as root)\n");
60 fprintf(stderr, "\t-v\tdisplay kore's version information\n");
61
75 fprintf(stderr, "\t-n\tdo not chroot\n");
76 fprintf(stderr, "\t-r\tdo not drop privileges\n");
77 fprintf(stderr, "\t-v\tdisplay kore build information\n");
78
79 #if !defined(KORE_SINGLE_BINARY)
6280 kore_cli_usage(0);
81 #else
82 fprintf(stderr, "\nbuilt with https://kore.io\n");
83 exit(1);
84 #endif
6385 }
6486
6587 static void
6688 version(void)
6789 {
68 printf("kore %d.%d.%d-%s ", KORE_VERSION_MAJOR, KORE_VERSION_MINOR,
90 printf("%d.%d.%d-%s ", KORE_VERSION_MAJOR, KORE_VERSION_MINOR,
6991 KORE_VERSION_PATCH, KORE_VERSION_STATE);
92 #if defined(KORE_NO_TLS)
93 printf("no-tls ");
94 #endif
95 #if defined(KORE_NO_HTTP)
96 printf("no-http ");
97 #endif
7098 #if defined(KORE_USE_PGSQL)
7199 printf("pgsql ");
72100 #endif
73101 #if defined(KORE_USE_TASKS)
74102 printf("tasks ");
75103 #endif
104 #if defined(KORE_DEBUG)
105 printf("debug ");
106 #endif
107 #if defined(KORE_SINGLE_BINARY)
108 printf("single ");
109 #endif
76110 printf("\n");
77111
78112 exit(0);
81115 int
82116 main(int argc, char *argv[])
83117 {
84 struct listener *l;
85 int ch, flags;
118 int ch, flags;
86119
87120 flags = 0;
88121
122 #if !defined(KORE_SINGLE_BINARY)
89123 while ((ch = getopt(argc, argv, "c:dfhnrv")) != -1) {
124 #else
125 while ((ch = getopt(argc, argv, "dfhnrv")) != -1) {
126 #endif
90127 flags++;
91128 switch (ch) {
129 #if !defined(KORE_SINGLE_BINARY)
92130 case 'c':
93131 config_file = optarg;
94132 break;
133 #endif
134 #if defined(KORE_DEBUG)
95135 case 'd':
96 #if defined(KORE_DEBUG)
97136 kore_debug = 1;
98 #else
99 printf("kore not compiled with debug support\n");
100 #endif
101 break;
137 break;
138 #endif
102139 case 'f':
103140 foreground = 1;
104141 break;
124161
125162 kore_mem_init();
126163
164 #if !defined(KORE_SINGLE_BINARY)
127165 if (argc > 0) {
128166 if (flags)
129167 fatal("You cannot specify kore flags and a command");
130168 return (kore_cli_main(argc, argv));
131169 }
170 #endif
132171
133172 kore_pid = getpid();
134173 nlisteners = 0;
135174 LIST_INIT(&listeners);
136175
137176 kore_log_init();
177 #if !defined(KORE_NO_HTTP)
138178 kore_auth_init();
179 kore_validator_init();
180 #endif
139181 kore_domain_init();
140182 kore_module_init();
141 kore_validator_init();
142183 kore_server_sslstart();
143184
185 #if !defined(KORE_SINGLE_BINARY)
144186 if (config_file == NULL)
145187 usage();
188 #else
189 kore_module_load(NULL, NULL);
190 #endif
146191
147192 kore_parse_config();
148193 kore_platform_init();
194
195 #if !defined(KORE_NO_HTTP)
149196 kore_accesslog_init();
197 if (http_body_disk_offload > 0) {
198 if (mkdir(http_body_disk_path, 0700) == -1 && errno != EEXIST) {
199 printf("can't create http_body_disk_path '%s': %s\n",
200 http_body_disk_path, errno_s);
201 return (KORE_RESULT_ERROR);
202 }
203 }
204 #endif
150205
151206 sig_recv = 0;
152207 signal(SIGHUP, kore_signal);
153208 signal(SIGQUIT, kore_signal);
209 signal(SIGTERM, kore_signal);
154210
155211 if (foreground)
156212 signal(SIGINT, kore_signal);
165221 if (!foreground)
166222 unlink(kore_pidfile);
167223
168 LIST_FOREACH(l, &listeners, list)
169 close(l->fd);
170
224 kore_listener_cleanup();
171225 kore_log(LOG_NOTICE, "goodbye");
226
172227 return (0);
173228 }
174229
175 #if !defined(KORE_BENCHMARK)
176 int
177 kore_tls_npn_cb(SSL *ssl, const u_char **data, unsigned int *len, void *arg)
178 {
179 kore_debug("kore_tls_npn_cb(): sending protocols");
180
181 *data = (const unsigned char *)KORE_SSL_PROTO_STRING;
182 *len = strlen(KORE_SSL_PROTO_STRING);
183
184 return (SSL_TLSEXT_ERR_OK);
185 }
186
230 #if !defined(KORE_NO_TLS)
187231 int
188232 kore_tls_sni_cb(SSL *ssl, int *ad, void *arg)
189233 {
224268 #endif
225269
226270 int
227 kore_server_bind(const char *ip, const char *port)
271 kore_server_bind(const char *ip, const char *port, const char *ccb)
228272 {
229273 struct listener *l;
230274 int on, r;
231 struct addrinfo *results;
275 struct addrinfo hints, *results;
232276
233277 kore_debug("kore_server_bind(%s, %s)", ip, port);
234278
235 r = getaddrinfo(ip, port, NULL, &results);
279 memset(&hints, 0, sizeof(hints));
280 hints.ai_family = AF_UNSPEC;
281 hints.ai_socktype = SOCK_STREAM;
282 hints.ai_protocol = IPPROTO_TCP;
283 hints.ai_flags = 0;
284
285 r = getaddrinfo(ip, port, &hints, &results);
236286 if (r != 0)
237287 fatal("getaddrinfo(%s): %s", ip, gai_strerror(r));
238288
244294 fatal("getaddrinfo(): unknown address family %d", l->addrtype);
245295
246296 if ((l->fd = socket(results->ai_family, SOCK_STREAM, 0)) == -1) {
247 kore_mem_free(l);
297 kore_free(l);
248298 freeaddrinfo(results);
249299 kore_debug("socket(): %s", errno_s);
250300 printf("failed to create socket: %s\n", errno_s);
251301 return (KORE_RESULT_ERROR);
252302 }
253303
254 if (!kore_connection_nonblock(l->fd)) {
255 kore_mem_free(l);
304 if (!kore_connection_nonblock(l->fd, 1)) {
305 kore_free(l);
256306 freeaddrinfo(results);
257307 printf("failed to make socket non blocking: %s\n", errno_s);
258308 return (KORE_RESULT_ERROR);
262312 if (setsockopt(l->fd, SOL_SOCKET,
263313 SO_REUSEADDR, (const char *)&on, sizeof(on)) == -1) {
264314 close(l->fd);
265 kore_mem_free(l);
315 kore_free(l);
266316 freeaddrinfo(results);
267317 kore_debug("setsockopt(): %s", errno_s);
268318 printf("failed to set SO_REUSEADDR: %s\n", errno_s);
271321
272322 if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) {
273323 close(l->fd);
274 kore_mem_free(l);
324 kore_free(l);
275325 freeaddrinfo(results);
276326 kore_debug("bind(): %s", errno_s);
277327 printf("failed to bind to %s port %s: %s\n", ip, port, errno_s);
282332
283333 if (listen(l->fd, kore_socket_backlog) == -1) {
284334 close(l->fd);
285 kore_mem_free(l);
335 kore_free(l);
286336 kore_debug("listen(): %s", errno_s);
287337 printf("failed to listen on socket: %s\n", errno_s);
288338 return (KORE_RESULT_ERROR);
289339 }
290340
341 if (ccb != NULL) {
342 *(void **)&(l->connect) = kore_module_getsym(ccb);
343 if (l->connect == NULL) {
344 printf("no such callback: '%s'\n", ccb);
345 close(l->fd);
346 kore_free(l);
347 return (KORE_RESULT_ERROR);
348 }
349 } else {
350 l->connect = NULL;
351 }
352
291353 nlisteners++;
292354 LIST_INSERT_HEAD(&listeners, l, list);
293355
294 if (foreground)
356 if (foreground) {
357 #if !defined(KORE_NO_TLS)
295358 kore_log(LOG_NOTICE, "running on https://%s:%s", ip, port);
359 #else
360 kore_log(LOG_NOTICE, "running on http://%s:%s", ip, port);
361 #endif
362 }
296363
297364 return (KORE_RESULT_OK);
365 }
366
367 void
368 kore_listener_cleanup(void)
369 {
370 struct listener *l;
371
372 while (!LIST_EMPTY(&listeners)) {
373 l = LIST_FIRST(&listeners);
374 LIST_REMOVE(l, list);
375 close(l->fd);
376 kore_free(l);
377 }
298378 }
299379
300380 void
306386 static void
307387 kore_server_sslstart(void)
308388 {
309 #if !defined(KORE_BENCHMARK)
389 #if !defined(KORE_NO_TLS)
310390 kore_debug("kore_server_sslstart()");
311391
312392 SSL_library_init();
317397 static void
318398 kore_server_start(void)
319399 {
400 u_int32_t tmp;
320401 int quit;
321402
322403 if (foreground == 0 && daemon(1, 1) == -1)
326407 if (!foreground)
327408 kore_write_kore_pid();
328409
329 kore_log(LOG_NOTICE, "kore is starting up");
410 kore_log(LOG_NOTICE, "%s is starting up", __progname);
330411 #if defined(KORE_USE_PGSQL)
331412 kore_log(LOG_NOTICE, "pgsql built-in enabled");
332413 #endif
333414 #if defined(KORE_USE_TASKS)
334415 kore_log(LOG_NOTICE, "tasks built-in enabled");
335416 #endif
417 #if defined(KORE_USE_JSONRPC)
418 kore_log(LOG_NOTICE, "jsonrpc built-in enabled");
419 #endif
336420
337421 kore_platform_proctitle("kore [parent]");
422 kore_msg_init();
338423 kore_worker_init();
339424
425 /* Set worker_max_connections for kore_connection_init(). */
426 tmp = worker_max_connections;
427 worker_max_connections = worker_count;
428
429 net_init();
430 kore_connection_init();
431 kore_platform_event_init();
432 kore_msg_parent_init();
433
340434 quit = 0;
435 worker_max_connections = tmp;
341436 while (quit != 1) {
342437 if (sig_recv != 0) {
343438 switch (sig_recv) {
344439 case SIGHUP:
440 #if !defined(KORE_SINGLE_BINARY)
345441 kore_worker_dispatch_signal(sig_recv);
346442 kore_module_reload(0);
443 #endif
347444 break;
348445 case SIGINT:
349446 case SIGQUIT:
447 case SIGTERM:
350448 quit = 1;
351449 kore_worker_dispatch_signal(sig_recv);
352450 continue;
359457 sig_recv = 0;
360458 }
361459
362 if (!kore_accesslog_wait())
363 break;
364
365460 kore_worker_wait(0);
366 }
461 kore_platform_event_wait(100);
462 kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
463 }
464
465 kore_platform_event_cleanup();
466 kore_connection_cleanup();
467 kore_domain_cleanup();
468 net_cleanup();
367469 }
368470
369471 static void
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
7070 events = kore_calloc(event_count, sizeof(struct epoll_event));
7171 }
7272
73 void
74 kore_platform_event_cleanup(void)
75 {
76 if (efd != -1) {
77 close(efd);
78 efd = -1;
79 }
80
81 if (events != NULL) {
82 kore_free(events);
83 events = NULL;
84 }
85 }
86
7387 int
7488 kore_platform_event_wait(u_int64_t timer)
7589 {
153167 !(c->flags & CONN_WRITE_BLOCK))
154168 c->flags |= CONN_WRITE_POSSIBLE;
155169
156 if (!kore_connection_handle(c))
170 if (c->handle != NULL && !c->handle(c))
157171 kore_connection_disconnect(c);
158172 break;
159173 #if defined(KORE_USE_PGSQL)
208222 }
209223
210224 void
225 kore_platform_schedule_write(int fd, void *data)
226 {
227 kore_platform_event_schedule(fd, EPOLLOUT, 0, data);
228 }
229
230 void
211231 kore_platform_disable_read(int fd)
212232 {
213233 if (epoll_ctl(efd, EPOLL_CTL_DEL, fd, NULL) == -1)
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
2020
2121 #include "kore.h"
2222
23 #define KORE_MEM_BLOCKS 11
24 #define KORE_MEM_BLOCK_SIZE_MAX 8192
25 #define KORE_MEM_BLOCK_PREALLOC 128
26
27 #define KORE_MEM_ALIGN (sizeof(size_t))
2328 #define KORE_MEM_MAGIC 0xd0d0
2429 #define KORE_MEMSIZE(x) \
25 (*(u_int32_t *)((u_int8_t *)x - sizeof(u_int32_t)))
30 (*(size_t *)((u_int8_t *)x - sizeof(size_t)))
2631 #define KORE_MEMINFO(x) \
2732 (struct meminfo *)((u_int8_t *)x + KORE_MEMSIZE(x))
2833
3035 u_int16_t magic;
3136 };
3237
38 struct memblock {
39 struct kore_pool pool;
40 };
41
42 static size_t memblock_index(size_t);
43
44 static struct memblock blocks[KORE_MEM_BLOCKS];
45
3346 void
3447 kore_mem_init(void)
3548 {
49 int i, len;
50 char name[32];
51 u_int32_t size, elm, mlen;
52
53 size = 8;
54
55 for (i = 0; i < KORE_MEM_BLOCKS; i++) {
56 len = snprintf(name, sizeof(name), "block-%u", size);
57 if (len == -1 || (size_t)len >= sizeof(name))
58 fatal("kore_mem_init: snprintf");
59
60 elm = (KORE_MEM_BLOCK_PREALLOC * 1024) / size;
61 mlen = sizeof(size_t) + size +
62 sizeof(struct meminfo) + KORE_MEM_ALIGN;
63 mlen = mlen & ~(KORE_MEM_ALIGN - 1);
64
65 kore_pool_init(&blocks[i].pool, name, mlen, elm);
66
67 size = size << 1;
68 }
3669 }
3770
3871 void *
3972 kore_malloc(size_t len)
4073 {
41 size_t mlen;
4274 void *ptr;
4375 struct meminfo *mem;
4476 u_int8_t *addr;
45 u_int32_t *plen;
77 size_t mlen, idx, *plen;
4678
4779 if (len == 0)
4880 fatal("kore_malloc(): zero size");
4981
50 mlen = sizeof(u_int32_t) + len + sizeof(struct meminfo);
51 if ((ptr = malloc(mlen)) == NULL)
52 fatal("kore_malloc(%d): %d", len, errno);
82 if (len <= KORE_MEM_BLOCK_SIZE_MAX) {
83 idx = memblock_index(len);
84 ptr = kore_pool_get(&blocks[idx].pool);
85 } else {
86 mlen = sizeof(size_t) + len + sizeof(struct meminfo);
87 if ((ptr = calloc(1, mlen)) == NULL)
88 fatal("kore_malloc(%zd): %d", len, errno);
89 }
5390
54 plen = (u_int32_t *)ptr;
91 plen = (size_t *)ptr;
5592 *plen = len;
56 addr = (u_int8_t *)ptr + sizeof(u_int32_t);
93 addr = (u_int8_t *)ptr + sizeof(size_t);
5794
5895 mem = KORE_MEMINFO(addr);
5996 mem->magic = KORE_MEM_MAGIC;
60
61 #if defined(KORE_PEDANTIC_MALLOC)
62 explicit_bzero(addr, len);
63 #endif
6497
6598 return (addr);
6699 }
83116
84117 nptr = kore_malloc(len);
85118 memcpy(nptr, ptr, MIN(len, KORE_MEMSIZE(ptr)));
86 kore_mem_free(ptr);
119 kore_free(ptr);
87120 }
88121
89122 return (nptr);
95128 if (memb == 0 || len == 0)
96129 fatal("kore_calloc(): zero size");
97130 if (SIZE_MAX / memb < len)
98 fatal("kore_calloc: memb * len > SIZE_MAX");
131 fatal("kore_calloc(): memb * len > SIZE_MAX");
99132
100133 return (kore_malloc(memb * len));
101134 }
102135
103136 void
104 kore_mem_free(void *ptr)
137 kore_free(void *ptr)
105138 {
106 u_int8_t *addr;
107 struct meminfo *mem;
139 u_int8_t *addr;
140 struct meminfo *mem;
141 size_t len, idx;
108142
109143 if (ptr == NULL)
110144 return;
111145
112146 mem = KORE_MEMINFO(ptr);
113147 if (mem->magic != KORE_MEM_MAGIC)
114 fatal("kore_mem_free(): magic boundary not found");
148 fatal("kore_free(): magic boundary not found");
115149
116 #if defined(KORE_PEDANTIC_MALLOC)
117 explicit_bzero(ptr, KORE_MEMSIZE(ptr));
118 #endif
150 len = KORE_MEMSIZE(ptr);
151 addr = (u_int8_t *)ptr - sizeof(size_t);
119152
120 addr = (u_int8_t *)ptr - sizeof(u_int32_t);
121 free(addr);
153 if (len <= KORE_MEM_BLOCK_SIZE_MAX) {
154 idx = memblock_index(len);
155 kore_pool_put(&blocks[idx].pool, addr);
156 } else {
157 free(addr);
158 }
122159 }
123160
124161 char *
129166
130167 len = strlen(str) + 1;
131168 nstr = kore_malloc(len);
132 kore_strlcpy(nstr, str, len);
169 (void)kore_strlcpy(nstr, str, len);
133170
134171 return (nstr);
135172 }
136173
137 #if defined(KORE_PEDANTIC_MALLOC)
138 void
139 explicit_bzero(void *addr, size_t len)
174 static size_t
175 memblock_index(size_t len)
140176 {
141 bzero(addr, len);
177 size_t mlen, idx;
178
179 idx = 0;
180 mlen = 8;
181 while (mlen < len) {
182 idx++;
183 mlen = mlen << 1;
184 }
185
186 if (idx > (KORE_MEM_BLOCKS - 1))
187 fatal("kore_malloc: idx too high");
188
189 return (idx);
142190 }
143 #endif
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
2525 kore_module_init(void)
2626 {
2727 TAILQ_INIT(&modules);
28 TAILQ_INIT(&domains);
28 }
29
30 void
31 kore_module_cleanup(void)
32 {
33 struct kore_module *module, *next;
34
35 for (module = TAILQ_FIRST(&modules); module != NULL; module = next) {
36 next = TAILQ_NEXT(module, list);
37 TAILQ_REMOVE(&modules, module, list);
38
39 kore_free(module->path);
40 (void)dlclose(module->handle);
41 kore_free(module);
42 }
2943 }
3044
3145 void
3246 kore_module_load(const char *path, const char *onload)
3347 {
48 #if !defined(KORE_SINGLE_BINARY)
3449 struct stat st;
50 #endif
3551 struct kore_module *module;
3652
3753 kore_debug("kore_module_load(%s, %s)", path, onload);
3854
55 module = kore_malloc(sizeof(struct kore_module));
56 module->onload = NULL;
57 module->ocb = NULL;
58
59 #if !defined(KORE_SINGLE_BINARY)
3960 if (stat(path, &st) == -1)
4061 fatal("stat(%s): %s", path, errno_s);
4162
42 module = kore_malloc(sizeof(struct kore_module));
4363 module->path = kore_strdup(path);
4464 module->mtime = st.st_mtime;
45 module->onload = NULL;
46 module->ocb = NULL;
65 #else
66 module->path = NULL;
67 module->mtime = 0;
68 #endif
4769
4870 module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL);
4971 if (module->handle == NULL)
5173
5274 if (onload != NULL) {
5375 module->onload = kore_strdup(onload);
54 module->ocb = dlsym(module->handle, onload);
76 *(void **)&(module->ocb) = dlsym(module->handle, onload);
5577 if (module->ocb == NULL)
5678 fatal("%s: onload '%s' not present", path, onload);
5779 }
6284 void
6385 kore_module_onload(void)
6486 {
87 #if !defined(KORE_SINGLE_BINARY)
6588 struct kore_module *module;
6689
6790 TAILQ_FOREACH(module, &modules, list) {
7093
7194 (void)module->ocb(KORE_MODULE_LOAD);
7295 }
96 #endif
7397 }
7498
7599 void
76100 kore_module_reload(int cbs)
77101 {
102 #if !defined(KORE_SINGLE_BINARY)
78103 struct stat st;
79104 struct kore_domain *dom;
80105 struct kore_module_handle *hdlr;
107132 fatal("kore_module_reload(): %s", dlerror());
108133
109134 if (module->onload != NULL) {
110 module->ocb = dlsym(module->handle, module->onload);
135 *(void **)&(module->ocb) =
136 dlsym(module->handle, module->onload);
111137 if (module->ocb == NULL) {
112138 fatal("%s: onload '%s' not present",
113139 module->path, module->onload);
129155 }
130156 }
131157
158 #if !defined(KORE_NO_HTTP)
132159 kore_validator_reload();
160 #endif
161 #endif
133162 }
134163
135164 int
141170 return (1);
142171 }
143172
173 #if !defined(KORE_NO_HTTP)
144174 int
145175 kore_module_handler_new(const char *path, const char *domain,
146176 const char *func, const char *auth, int type)
182212 if (hdlr->type == HANDLER_TYPE_DYNAMIC) {
183213 if (regcomp(&(hdlr->rctx), hdlr->path,
184214 REG_EXTENDED | REG_NOSUB)) {
185 kore_mem_free(hdlr->func);
186 kore_mem_free(hdlr->path);
187 kore_mem_free(hdlr);
215 kore_module_handler_free(hdlr);
188216 kore_debug("regcomp() on %s failed", path);
189217 return (KORE_RESULT_ERROR);
190218 }
192220
193221 TAILQ_INSERT_TAIL(&(dom->handlers), hdlr, list);
194222 return (KORE_RESULT_OK);
223 }
224
225 void
226 kore_module_handler_free(struct kore_module_handle *hdlr)
227 {
228 struct kore_handler_params *param;
229
230 if (hdlr == NULL)
231 return;
232
233 if (hdlr->func != NULL)
234 kore_free(hdlr->func);
235 if (hdlr->path != NULL)
236 kore_free(hdlr->path);
237 if (hdlr->type == HANDLER_TYPE_DYNAMIC)
238 regfree(&(hdlr->rctx));
239
240 /* Drop all validators associated with this handler */
241 while ((param = TAILQ_FIRST(&(hdlr->params))) != NULL) {
242 TAILQ_REMOVE(&(hdlr->params), param, list);
243 if (param->name != NULL)
244 kore_free(param->name);
245 kore_free(param);
246 }
247
248 kore_free(hdlr);
195249 }
196250
197251 struct kore_module_handle *
216270 return (NULL);
217271 }
218272
273 #endif /* !KORE_NO_HTTP */
274
219275 void *
220276 kore_module_getsym(const char *symbol)
221277 {
0 /*
1 * Copyright (c) 2016 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #include <sys/socket.h>
17
18 #include <signal.h>
19
20 #include "kore.h"
21 #include "http.h"
22
23 struct msg_type {
24 u_int8_t id;
25 void (*cb)(struct kore_msg *, const void *);
26 TAILQ_ENTRY(msg_type) list;
27 };
28
29 TAILQ_HEAD(, msg_type) msg_types;
30
31 static struct msg_type *msg_type_lookup(u_int8_t);
32 static int msg_recv_packet(struct netbuf *);
33 static int msg_recv_data(struct netbuf *);
34 static void msg_disconnected_parent(struct connection *);
35 static void msg_disconnected_worker(struct connection *);
36
37 #if !defined(KORE_NO_HTTP)
38 static void msg_type_accesslog(struct kore_msg *, const void *);
39 static void msg_type_websocket(struct kore_msg *, const void *);
40 #endif
41
42 void
43 kore_msg_init(void)
44 {
45 TAILQ_INIT(&msg_types);
46 }
47
48 void
49 kore_msg_parent_init(void)
50 {
51 u_int8_t i;
52 struct kore_worker *kw;
53
54 for (i = 0; i < worker_count; i++) {
55 kw = kore_worker_data(i);
56 kore_msg_parent_add(kw);
57 }
58
59 #if !defined(KORE_NO_HTTP)
60 kore_msg_register(KORE_MSG_ACCESSLOG, msg_type_accesslog);
61 #endif
62 }
63
64 void
65 kore_msg_parent_add(struct kore_worker *kw)
66 {
67 kw->msg[0] = kore_connection_new(NULL);
68 kw->msg[0]->fd = kw->pipe[0];
69 kw->msg[0]->read = net_read;
70 kw->msg[0]->write = net_write;
71 kw->msg[0]->proto = CONN_PROTO_MSG;
72 kw->msg[0]->state = CONN_STATE_ESTABLISHED;
73 kw->msg[0]->hdlr_extra = &kw->id;
74 kw->msg[0]->disconnect = msg_disconnected_worker;
75 kw->msg[0]->handle = kore_connection_handle;
76
77 TAILQ_INSERT_TAIL(&connections, kw->msg[0], list);
78 kore_platform_event_all(kw->msg[0]->fd, kw->msg[0]);
79
80 net_recv_queue(kw->msg[0], sizeof(struct kore_msg), 0, msg_recv_packet);
81 }
82
83 void
84 kore_msg_parent_remove(struct kore_worker *kw)
85 {
86 kore_connection_disconnect(kw->msg[0]);
87 kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
88 (void)close(kw->pipe[1]);
89 }
90
91 void
92 kore_msg_worker_init(void)
93 {
94 #if !defined(KORE_NO_HTTP)
95 kore_msg_register(KORE_MSG_WEBSOCKET, msg_type_websocket);
96 #endif
97
98 worker->msg[1] = kore_connection_new(NULL);
99 worker->msg[1]->fd = worker->pipe[1];
100 worker->msg[1]->read = net_read;
101 worker->msg[1]->write = net_write;
102 worker->msg[1]->proto = CONN_PROTO_MSG;
103 worker->msg[1]->state = CONN_STATE_ESTABLISHED;
104 worker->msg[1]->disconnect = msg_disconnected_parent;
105 worker->msg[1]->handle = kore_connection_handle;
106
107 TAILQ_INSERT_TAIL(&connections, worker->msg[1], list);
108 kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
109
110 net_recv_queue(worker->msg[1],
111 sizeof(struct kore_msg), 0, msg_recv_packet);
112 }
113
114 int
115 kore_msg_register(u_int8_t id, void (*cb)(struct kore_msg *, const void *))
116 {
117 struct msg_type *type;
118
119 if ((type = msg_type_lookup(id)) != NULL)
120 return (KORE_RESULT_ERROR);
121
122 type = kore_malloc(sizeof(*type));
123 type->id = id;
124 type->cb = cb;
125 TAILQ_INSERT_TAIL(&msg_types, type, list);
126
127 return (KORE_RESULT_OK);
128 }
129
130 void
131 kore_msg_send(u_int16_t dst, u_int8_t id, const void *data, u_int32_t len)
132 {
133 struct kore_msg m;
134
135 m.id = id;
136 m.dst = dst;
137 m.length = len;
138 m.src = worker->id;
139
140 net_send_queue(worker->msg[1], &m, sizeof(m));
141 net_send_queue(worker->msg[1], data, len);
142 net_send_flush(worker->msg[1]);
143 }
144
145 static int
146 msg_recv_packet(struct netbuf *nb)
147 {
148 struct kore_msg *msg = (struct kore_msg *)nb->buf;
149
150 net_recv_expand(nb->owner, msg->length, msg_recv_data);
151 return (KORE_RESULT_OK);
152 }
153
154 static int
155 msg_recv_data(struct netbuf *nb)
156 {
157 struct connection *c;
158 struct msg_type *type;
159 u_int16_t destination;
160 struct kore_msg *msg = (struct kore_msg *)nb->buf;
161
162 if ((type = msg_type_lookup(msg->id)) != NULL) {
163 if (worker == NULL && msg->dst != KORE_MSG_PARENT)
164 fatal("received parent msg for non parent dst");
165 if (worker != NULL && msg->dst != worker->id)
166 fatal("received message for incorrect worker");
167
168 type->cb(msg, nb->buf + sizeof(*msg));
169 }
170
171 if (worker == NULL && type == NULL) {
172 destination = msg->dst;
173 TAILQ_FOREACH(c, &connections, list) {
174 if (c == nb->owner)
175 continue;
176 if (c->proto != CONN_PROTO_MSG || c->hdlr_extra == NULL)
177 continue;
178
179 if (destination != KORE_MSG_WORKER_ALL &&
180 *(u_int8_t *)c->hdlr_extra != destination)
181 continue;
182
183 /* This allows the worker to receive the correct id. */
184 msg->dst = *(u_int8_t *)c->hdlr_extra;
185
186 net_send_queue(c, nb->buf, nb->s_off);
187 net_send_flush(c);
188 }
189 }
190
191 net_recv_reset(nb->owner, sizeof(struct kore_msg), msg_recv_packet);
192 return (KORE_RESULT_OK);
193 }
194
195 static void
196 msg_disconnected_parent(struct connection *c)
197 {
198 kore_log(LOG_ERR, "parent gone, shutting down");
199 if (kill(worker->pid, SIGQUIT) == -1)
200 kore_log(LOG_ERR, "failed to send SIGQUIT: %s", errno_s);
201 }
202
203 static void
204 msg_disconnected_worker(struct connection *c)
205 {
206 c->hdlr_extra = NULL;
207 }
208
209 #if !defined(KORE_NO_HTTP)
210 static void
211 msg_type_accesslog(struct kore_msg *msg, const void *data)
212 {
213 if (kore_accesslog_write(data, msg->length) == -1)
214 kore_log(LOG_WARNING, "failed to write to accesslog");
215 }
216
217 static void
218 msg_type_websocket(struct kore_msg *msg, const void *data)
219 {
220 struct connection *c;
221
222 TAILQ_FOREACH(c, &connections, list) {
223 if (c->proto == CONN_PROTO_WEBSOCKET) {
224 net_send_queue(c, data, msg->length);
225 net_send_flush(c);
226 }
227 }
228 }
229 #endif
230
231 static struct msg_type *
232 msg_type_lookup(u_int8_t id)
233 {
234 struct msg_type *type;
235
236 TAILQ_FOREACH(type, &msg_types, list) {
237 if (type->id == id)
238 return (type);
239 }
240
241 return (NULL);
242 }
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
3636 }
3737
3838 void
39 net_send_queue(struct connection *c, void *data, u_int32_t len,
40 struct spdy_stream *s, int before)
41 {
42 u_int8_t *d;
39 net_cleanup(void)
40 {
41 kore_debug("net_cleanup()");
42 kore_pool_cleanup(&nb_pool);
43 }
44
45 void
46 net_send_queue(struct connection *c, const void *data, size_t len)
47 {
48 const u_int8_t *d;
4349 struct netbuf *nb;
44 u_int32_t avail;
45
46 kore_debug("net_send_queue(%p, %p, %d, %p, %d)",
47 c, data, len, s, before);
50 size_t avail;
51
52 kore_debug("net_send_queue(%p, %p, %zu)", c, data, len);
4853
4954 d = data;
50 if (before == NETBUF_LAST_CHAIN) {
51 nb = TAILQ_LAST(&(c->send_queue), netbuf_head);
52 if (nb != NULL && !(nb->flags & NETBUF_IS_STREAM) &&
53 nb->stream == s && nb->b_len < nb->m_len) {
54 avail = nb->m_len - nb->b_len;
55 if (len < avail) {
56 memcpy(nb->buf + nb->b_len, d, len);
57 nb->b_len += len;
55 nb = TAILQ_LAST(&(c->send_queue), netbuf_head);
56 if (nb != NULL && !(nb->flags & NETBUF_IS_STREAM) &&
57 nb->b_len < nb->m_len) {
58 avail = nb->m_len - nb->b_len;
59 if (len < avail) {
60 memcpy(nb->buf + nb->b_len, d, len);
61 nb->b_len += len;
62 return;
63 } else {
64 memcpy(nb->buf + nb->b_len, d, avail);
65 nb->b_len += avail;
66
67 len -= avail;
68 d += avail;
69 if (len == 0)
5870 return;
59 } else if (len > avail) {
60 memcpy(nb->buf + nb->b_len, d, avail);
61 nb->b_len += avail;
62
63 len -= avail;
64 d += avail;
65 if (len == 0)
66 return;
67 }
6871 }
6972 }
7073
7376 nb->cb = NULL;
7477 nb->owner = c;
7578 nb->s_off = 0;
76 nb->stream = s;
7779 nb->b_len = len;
7880 nb->type = NETBUF_SEND;
7981
8688 if (len > 0)
8789 memcpy(nb->buf, d, nb->b_len);
8890
89 if (before == NETBUF_BEFORE_CHAIN) {
90 TAILQ_INSERT_BEFORE(c->snb, nb, list);
91 } else {
92 TAILQ_INSERT_TAIL(&(c->send_queue), nb, list);
93 }
94 }
95
96 void
97 net_send_stream(struct connection *c, void *data, u_int32_t len,
98 struct spdy_stream *s, int (*cb)(struct netbuf *), struct netbuf **out)
91 TAILQ_INSERT_TAIL(&(c->send_queue), nb, list);
92 }
93
94 void
95 net_send_stream(struct connection *c, void *data, size_t len,
96 int (*cb)(struct netbuf *), struct netbuf **out)
9997 {
10098 struct netbuf *nb;
10199
102 kore_debug("net_send_stream(%p, %p, %d, %p)", c, data, len, s);
100 kore_debug("net_send_stream(%p, %p, %zu)", c, data, len);
103101
104102 nb = kore_pool_get(&nb_pool);
105103 nb->cb = cb;
106104 nb->owner = c;
107105 nb->s_off = 0;
108106 nb->buf = data;
109 nb->stream = s;
110107 nb->b_len = len;
111108 nb->m_len = nb->b_len;
112109 nb->type = NETBUF_SEND;
118115 }
119116
120117 void
121 net_recv_reset(struct connection *c, u_int32_t len, int (*cb)(struct netbuf *))
122 {
123 kore_debug("net_recv_reset(): %p %d", c, len);
118 net_recv_reset(struct connection *c, size_t len, int (*cb)(struct netbuf *))
119 {
120 kore_debug("net_recv_reset(): %p %zu", c, len);
124121
125122 if (c->rnb->type != NETBUF_RECV)
126123 fatal("net_recv_reset(): wrong netbuf type");
133130 c->rnb->m_len < (NETBUF_SEND_PAYLOAD_MAX / 2))
134131 return;
135132
136 kore_mem_free(c->rnb->buf);
133 kore_free(c->rnb->buf);
137134 c->rnb->m_len = len;
138135 c->rnb->buf = kore_malloc(c->rnb->m_len);
139136 }
140137
141138 void
142 net_recv_queue(struct connection *c, u_int32_t len, int flags,
139 net_recv_queue(struct connection *c, size_t len, int flags,
143140 int (*cb)(struct netbuf *))
144141 {
145 kore_debug("net_recv_queue(): %p %d %d", c, len, flags);
142 kore_debug("net_recv_queue(): %p %zu %d", c, len, flags);
146143
147144 if (c->rnb != NULL)
148145 fatal("net_recv_queue(): called incorrectly for %p", c);
154151 c->rnb->b_len = len;
155152 c->rnb->m_len = len;
156153 c->rnb->extra = NULL;
157 c->rnb->stream = NULL;
158154 c->rnb->flags = flags;
159155 c->rnb->type = NETBUF_RECV;
160156 c->rnb->buf = kore_malloc(c->rnb->b_len);
161157 }
162158
163159 void
164 net_recv_expand(struct connection *c, u_int32_t len, int (*cb)(struct netbuf *))
160 net_recv_expand(struct connection *c, size_t len, int (*cb)(struct netbuf *))
165161 {
166162 kore_debug("net_recv_expand(): %p %d", c, len);
167163
182178
183179 c->snb = TAILQ_FIRST(&(c->send_queue));
184180 if (c->snb->b_len != 0) {
185 if (c->snb->stream != NULL &&
186 (c->snb->stream->flags & SPDY_DATAFRAME_PRELUDE)) {
187 if (!spdy_dataframe_begin(c)) {
188 c->snb = NULL;
189 return (KORE_RESULT_OK);
190 }
191
192 c->snb = TAILQ_FIRST(&(c->send_queue));
193 }
194
195181 smin = c->snb->b_len - c->snb->s_off;
196 if (c->snb->stream != NULL &&
197 c->snb->stream->frame_size > 0) {
198 smin = MIN(smin, c->snb->stream->frame_size);
199 }
200
201182 len = MIN(NETBUF_SEND_PAYLOAD_MAX, smin);
202183
203184 if (!c->write(c, len, &r))
210191
211192 c->snb->s_off += (size_t)r;
212193 c->snb->flags &= ~NETBUF_MUST_RESEND;
213 if (c->snb->stream != NULL)
214 spdy_update_wsize(c, c->snb->stream, r);
215194 }
216195
217196 if (c->snb->s_off == c->snb->b_len ||
248227 kore_debug("net_recv_flush(%p)", c);
249228
250229 if (c->rnb == NULL)
251 fatal("net_recv_flush(): c->rnb == NULL");
230 return (KORE_RESULT_OK);
252231
253232 while (c->flags & CONN_READ_POSSIBLE) {
254233 if (!c->read(c, &r))
274253 void
275254 net_remove_netbuf(struct netbuf_head *list, struct netbuf *nb)
276255 {
277 kore_debug("net_remove_netbuf(%p, %p, %p)", list, nb, nb->stream);
256 kore_debug("net_remove_netbuf(%p, %p)", list, nb);
278257
279258 if (nb->type == NETBUF_RECV)
280259 fatal("net_remove_netbuf(): cannot remove recv netbuf");
281260
282 nb->stream = NULL;
283261 if (nb->flags & NETBUF_MUST_RESEND) {
284262 kore_debug("retaining %p (MUST_RESEND)", nb);
285263 nb->flags |= NETBUF_FORCE_REMOVE;
287265 }
288266
289267 if (!(nb->flags & NETBUF_IS_STREAM)) {
290 kore_mem_free(nb->buf);
268 kore_free(nb->buf);
291269 } else if (nb->cb != NULL) {
292270 (void)nb->cb(nb);
293271 }
296274 kore_pool_put(&nb_pool, nb);
297275 }
298276
299 #if !defined(KORE_BENCHMARK)
277 #if !defined(KORE_NO_TLS)
300278 int
301279 net_write_ssl(struct connection *c, int len, int *written)
302280 {
314292 c->snb->flags |= NETBUF_MUST_RESEND;
315293 c->flags &= ~CONN_WRITE_POSSIBLE;
316294 return (KORE_RESULT_OK);
295 case SSL_ERROR_SYSCALL:
296 switch (errno) {
297 case EINTR:
298 *written = 0;
299 return (KORE_RESULT_OK);
300 case EAGAIN:
301 c->snb->flags |= NETBUF_MUST_RESEND;
302 c->flags &= ~CONN_WRITE_POSSIBLE;
303 return (KORE_RESULT_OK);
304 default:
305 break;
306 }
307 /* FALLTHROUGH */
317308 default:
318309 kore_debug("SSL_write(): %s", ssl_errno_s);
319310 return (KORE_RESULT_ERROR);
342333 case SSL_ERROR_WANT_WRITE:
343334 c->flags &= ~CONN_READ_POSSIBLE;
344335 return (KORE_RESULT_OK);
336 case SSL_ERROR_SYSCALL:
337 switch (errno) {
338 case EINTR:
339 *bytes = 0;
340 return (KORE_RESULT_OK);
341 case EAGAIN:
342 c->snb->flags |= NETBUF_MUST_RESEND;
343 c->flags &= ~CONN_WRITE_POSSIBLE;
344 return (KORE_RESULT_OK);
345 default:
346 break;
347 }
348 /* FALLTHROUGH */
345349 default:
346350 kore_debug("SSL_read(): %s", ssl_errno_s);
347351 return (KORE_RESULT_ERROR);
362366 if (r <= -1) {
363367 switch (errno) {
364368 case EINTR:
369 *written = 0;
370 return (KORE_RESULT_OK);
365371 case EAGAIN:
366372 c->flags &= ~CONN_WRITE_POSSIBLE;
367373 return (KORE_RESULT_OK);
385391 if (r <= 0) {
386392 switch (errno) {
387393 case EINTR:
394 *bytes = 0;
395 return (KORE_RESULT_OK);
388396 case EAGAIN:
389397 c->flags &= ~CONN_READ_POSSIBLE;
390398 return (KORE_RESULT_OK);
00 /*
1 * Copyright (c) 2014 Joris Vink <joris@coders.se>
1 * Copyright (c) 2014-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
2424 #include "pgsql.h"
2525
2626 struct pgsql_job {
27 char *query;
2827 struct http_request *req;
2928 struct kore_pgsql *pgsql;
3029
3635 TAILQ_ENTRY(pgsql_wait) list;
3736 };
3837
39 #define PGSQL_IS_BLOCKING 0
40 #define PGSQL_IS_ASYNC 1
41
4238 #define PGSQL_CONN_MAX 2
4339 #define PGSQL_CONN_FREE 0x01
40 #define PGSQL_LIST_INSERTED 0x0100
4441
4542 static void pgsql_queue_wakeup(void);
46 static int pgsql_conn_create(struct kore_pgsql *);
43 static void pgsql_set_error(struct kore_pgsql *, const char *);
4744 static void pgsql_queue_add(struct http_request *);
4845 static void pgsql_conn_release(struct kore_pgsql *);
4946 static void pgsql_conn_cleanup(struct pgsql_conn *);
50 static void pgsql_read_result(struct kore_pgsql *, int);
51 static void pgsql_schedule(struct kore_pgsql *, struct http_request *);
52 static int pgsql_prepare(struct kore_pgsql *, struct http_request *,
53 const char *);
47 static void pgsql_read_result(struct kore_pgsql *);
48 static void pgsql_schedule(struct kore_pgsql *);
49
50 static struct pgsql_conn *pgsql_conn_create(struct kore_pgsql *,
51 struct pgsql_db *);
52 static struct pgsql_conn *pgsql_conn_next(struct kore_pgsql *,
53 struct pgsql_db *,
54 struct http_request *);
5455
5556 static struct kore_pool pgsql_job_pool;
5657 static struct kore_pool pgsql_wait_pool;
5758 static TAILQ_HEAD(, pgsql_conn) pgsql_conn_free;
5859 static TAILQ_HEAD(, pgsql_wait) pgsql_wait_queue;
60 static LIST_HEAD(, pgsql_db) pgsql_db_conn_strings;
5961 static u_int16_t pgsql_conn_count;
60 char *pgsql_conn_string = NULL;
6162 u_int16_t pgsql_conn_max = PGSQL_CONN_MAX;
6263
6364 void
6667 pgsql_conn_count = 0;
6768 TAILQ_INIT(&pgsql_conn_free);
6869 TAILQ_INIT(&pgsql_wait_queue);
70 LIST_INIT(&pgsql_db_conn_strings);
6971
7072 kore_pool_init(&pgsql_job_pool, "pgsql_job_pool",
7173 sizeof(struct pgsql_job), 100);
7476 }
7577
7678 int
77 kore_pgsql_query(struct kore_pgsql *pgsql, struct http_request *req,
78 const char *query)
79 {
80 if (!pgsql_prepare(pgsql, req, query))
79 kore_pgsql_query_init(struct kore_pgsql *pgsql, struct http_request *req,
80 const char *dbname, int flags)
81 {
82 struct pgsql_db *db;
83
84 memset(pgsql, 0, sizeof(*pgsql));
85 pgsql->flags = flags;
86 pgsql->state = KORE_PGSQL_STATE_INIT;
87
88 if ((req == NULL && (flags & KORE_PGSQL_ASYNC)) ||
89 ((flags & KORE_PGSQL_ASYNC) && (flags & KORE_PGSQL_SYNC))) {
90 pgsql_set_error(pgsql, "invalid query init parameters");
8191 return (KORE_RESULT_ERROR);
82
83 if (!PQsendQuery(pgsql->conn->db, query)) {
84 pgsql_conn_cleanup(pgsql->conn);
92 }
93
94 db = NULL;
95 LIST_FOREACH(db, &pgsql_db_conn_strings, rlist) {
96 if (!strcmp(db->name, dbname))
97 break;
98 }
99
100 if (db == NULL) {
101 pgsql_set_error(pgsql, "no database found");
85102 return (KORE_RESULT_ERROR);
86103 }
87104
88 pgsql_schedule(pgsql, req);
105 if ((pgsql->conn = pgsql_conn_next(pgsql, db, req)) == NULL)
106 return (KORE_RESULT_ERROR);
107
108 if (pgsql->flags & KORE_PGSQL_ASYNC) {
109 pgsql->conn->job = kore_pool_get(&pgsql_job_pool);
110 pgsql->conn->job->req = req;
111 pgsql->conn->job->pgsql = pgsql;
112
113 http_request_sleep(req);
114 pgsql->flags |= PGSQL_LIST_INSERTED;
115 LIST_INSERT_HEAD(&(req->pgsqls), pgsql, rlist);
116 }
117
89118 return (KORE_RESULT_OK);
90119 }
91120
92121 int
93 kore_pgsql_query_params(struct kore_pgsql *pgsql, struct http_request *req,
94 const char *query, int result, u_int8_t count, ...)
122 kore_pgsql_query(struct kore_pgsql *pgsql, const char *query)
123 {
124 if (pgsql->conn == NULL) {
125 pgsql_set_error(pgsql, "no connection was set before query");
126 return (KORE_RESULT_ERROR);
127 }
128
129 if (pgsql->flags & KORE_PGSQL_SYNC) {
130 pgsql->result = PQexec(pgsql->conn->db, query);
131
132 if ((PQresultStatus(pgsql->result) != PGRES_TUPLES_OK) &&
133 (PQresultStatus(pgsql->result) != PGRES_COMMAND_OK)) {
134 pgsql_set_error(pgsql, PQerrorMessage(pgsql->conn->db));
135 return (KORE_RESULT_ERROR);
136 }
137
138 pgsql->state = KORE_PGSQL_STATE_DONE;
139 } else {
140 if (!PQsendQuery(pgsql->conn->db, query)) {
141 pgsql_set_error(pgsql, PQerrorMessage(pgsql->conn->db));
142 return (KORE_RESULT_ERROR);
143 }
144
145 pgsql_schedule(pgsql);
146 }
147
148 return (KORE_RESULT_OK);
149 }
150
151 int
152 kore_pgsql_v_query_params(struct kore_pgsql *pgsql,
153 const char *query, int result, u_int8_t count, va_list args)
95154 {
96155 u_int8_t i;
97 va_list args;
98156 char **values;
99 int *lengths, *formats;
100
101 if (!pgsql_prepare(pgsql, req, query))
157 int *lengths, *formats, ret;
158
159 if (pgsql->conn == NULL) {
160 pgsql_set_error(pgsql, "no connection was set before query");
102161 return (KORE_RESULT_ERROR);
162 }
103163
104164 if (count > 0) {
105 va_start(args, count);
106
107165 lengths = kore_calloc(count, sizeof(int));
108166 formats = kore_calloc(count, sizeof(int));
109167 values = kore_calloc(count, sizeof(char *));
119177 values = NULL;
120178 }
121179
122 if (!PQsendQueryParams(pgsql->conn->db, query, count, NULL,
123 (const char * const *)values, lengths, formats, result)) {
124 kore_mem_free(values);
125 kore_mem_free(lengths);
126 kore_mem_free(formats);
127 pgsql_conn_cleanup(pgsql->conn);
128 return (KORE_RESULT_ERROR);
129 }
130
131 kore_mem_free(values);
132 kore_mem_free(lengths);
133 kore_mem_free(formats);
134
135 pgsql_schedule(pgsql, req);
180 ret = KORE_RESULT_ERROR;
181
182 if (pgsql->flags & KORE_PGSQL_SYNC) {
183 pgsql->result = PQexecParams(pgsql->conn->db, query, count,
184 NULL, (const char * const *)values, lengths, formats,
185 result);
186
187 if ((PQresultStatus(pgsql->result) != PGRES_TUPLES_OK) &&
188 (PQresultStatus(pgsql->result) != PGRES_COMMAND_OK)) {
189 pgsql_set_error(pgsql, PQerrorMessage(pgsql->conn->db));
190 goto cleanup;
191 }
192
193 pgsql->state = KORE_PGSQL_STATE_DONE;
194 } else {
195 if (!PQsendQueryParams(pgsql->conn->db, query, count, NULL,
196 (const char * const *)values, lengths, formats, result)) {
197 pgsql_set_error(pgsql, PQerrorMessage(pgsql->conn->db));
198 goto cleanup;
199 }
200
201 pgsql_schedule(pgsql);
202 }
203
204 ret = KORE_RESULT_OK;
205
206 cleanup:
207 kore_free(values);
208 kore_free(lengths);
209 kore_free(formats);
210
211 return (ret);
212 }
213
214 int
215 kore_pgsql_query_params(struct kore_pgsql *pgsql,
216 const char *query, int result, u_int8_t count, ...)
217 {
218 int ret;
219 va_list args;
220
221 if (count > 0)
222 va_start(args, count);
223
224 ret = kore_pgsql_v_query_params(pgsql, query, result, count, args);
225
226 if (count > 0)
227 va_end(args);
228
229 return (ret);
230 }
231
232 int
233 kore_pgsql_register(const char *dbname, const char *connstring)
234 {
235 struct pgsql_db *pgsqldb;
236
237 LIST_FOREACH(pgsqldb, &pgsql_db_conn_strings, rlist) {
238 if (!strcmp(pgsqldb->name, dbname))
239 return (KORE_RESULT_ERROR);
240 }
241
242 pgsqldb = kore_malloc(sizeof(*pgsqldb));
243 pgsqldb->name = kore_strdup(dbname);
244 pgsqldb->conn_string = kore_strdup(connstring);
245 LIST_INSERT_HEAD(&pgsql_db_conn_strings, pgsqldb, rlist);
246
136247 return (KORE_RESULT_OK);
137248 }
138249
156267 pgsql->state = KORE_PGSQL_STATE_ERROR;
157268 pgsql->error = kore_strdup(PQerrorMessage(conn->db));
158269 } else {
159 pgsql_read_result(pgsql, PGSQL_IS_ASYNC);
270 pgsql_read_result(pgsql);
160271 }
161272
162273 if (pgsql->state == KORE_PGSQL_STATE_WAIT) {
173284 req->owner, req, pgsql->state);
174285
175286 if (pgsql->error) {
176 kore_mem_free(pgsql->error);
287 kore_free(pgsql->error);
177288 pgsql->error = NULL;
178289 }
179290
208319 PQclear(pgsql->result);
209320
210321 if (pgsql->error != NULL)
211 kore_mem_free(pgsql->error);
322 kore_free(pgsql->error);
212323
213324 if (pgsql->conn != NULL)
214325 pgsql_conn_release(pgsql);
217328 pgsql->error = NULL;
218329 pgsql->conn = NULL;
219330
220 LIST_REMOVE(pgsql, rlist);
331 if (pgsql->flags & PGSQL_LIST_INSERTED) {
332 LIST_REMOVE(pgsql, rlist);
333 pgsql->flags &= ~PGSQL_LIST_INSERTED;
334 }
221335 }
222336
223337 void
261375 }
262376 }
263377
264 static int
265 pgsql_prepare(struct kore_pgsql *pgsql, struct http_request *req,
266 const char *query)
378 static struct pgsql_conn *
379 pgsql_conn_next(struct kore_pgsql *pgsql, struct pgsql_db *db,
380 struct http_request *req)
267381 {
268382 struct pgsql_conn *conn;
269383
270 pgsql->state = KORE_PGSQL_STATE_INIT;
271 pgsql->result = NULL;
272 pgsql->error = NULL;
273 pgsql->conn = NULL;
274
275 if (TAILQ_EMPTY(&pgsql_conn_free)) {
384 conn = NULL;
385
386 TAILQ_FOREACH(conn, &pgsql_conn_free, list) {
387 if (!(conn->flags & PGSQL_CONN_FREE))
388 fatal("got a pgsql connection that was not free?");
389 if (!strcmp(conn->name, db->name))
390 break;
391 }
392
393 if (conn == NULL) {
276394 if (pgsql_conn_count >= pgsql_conn_max) {
277 pgsql_queue_add(req);
278 return (KORE_RESULT_ERROR);
279 }
280
281 if (!pgsql_conn_create(pgsql))
282 return (KORE_RESULT_ERROR);
283 }
284
285 http_request_sleep(req);
286 conn = TAILQ_FIRST(&pgsql_conn_free);
287 if (!(conn->flags & PGSQL_CONN_FREE))
288 fatal("received a pgsql conn that was not free?");
395 if (pgsql->flags & KORE_PGSQL_ASYNC) {
396 pgsql_queue_add(req);
397 } else {
398 pgsql_set_error(pgsql,
399 "no available connection");
400 }
401
402 return (NULL);
403 }
404
405 if ((conn = pgsql_conn_create(pgsql, db)) == NULL)
406 return (NULL);
407 }
289408
290409 conn->flags &= ~PGSQL_CONN_FREE;
291410 TAILQ_REMOVE(&pgsql_conn_free, conn, list);
292411
293 pgsql->conn = conn;
294 conn->job = kore_pool_get(&pgsql_job_pool);
295 conn->job->query = kore_strdup(query);
296 conn->job->pgsql = pgsql;
297 conn->job->req = req;
298
299 LIST_INSERT_HEAD(&(req->pgsqls), pgsql, rlist);
300 return (KORE_RESULT_OK);
301 }
302
303 static void
304 pgsql_schedule(struct kore_pgsql *pgsql, struct http_request *req)
412 return (conn);
413 }
414
415 static void
416 pgsql_set_error(struct kore_pgsql *pgsql, const char *msg)
417 {
418 if (pgsql->error != NULL)
419 kore_free(pgsql->error);
420
421 pgsql->error = kore_strdup(msg);
422 pgsql->state = KORE_PGSQL_STATE_ERROR;
423 }
424
425 static void
426 pgsql_schedule(struct kore_pgsql *pgsql)
305427 {
306428 int fd;
307429
346468 }
347469 }
348470
349 static int
350 pgsql_conn_create(struct kore_pgsql *pgsql)
471 static struct pgsql_conn *
472 pgsql_conn_create(struct kore_pgsql *pgsql, struct pgsql_db *db)
351473 {
352474 struct pgsql_conn *conn;
353475
354 if (pgsql_conn_string == NULL)
476 if (db == NULL || db->conn_string == NULL)
355477 fatal("pgsql_conn_create: no connection string");
356478
357479 pgsql_conn_count++;
358480 conn = kore_malloc(sizeof(*conn));
359481 kore_debug("pgsql_conn_create(): %p", conn);
360 memset(conn, 0, sizeof(*conn));
361
362 conn->db = PQconnectdb(pgsql_conn_string);
482
483 conn->db = PQconnectdb(db->conn_string);
363484 if (conn->db == NULL || (PQstatus(conn->db) != CONNECTION_OK)) {
364 pgsql->state = KORE_PGSQL_STATE_ERROR;
365 pgsql->error = kore_strdup(PQerrorMessage(conn->db));
485 pgsql_set_error(pgsql, PQerrorMessage(conn->db));
366486 pgsql_conn_cleanup(conn);
367 return (KORE_RESULT_ERROR);
487 return (NULL);
368488 }
369489
370490 conn->job = NULL;
371491 conn->flags = PGSQL_CONN_FREE;
372492 conn->type = KORE_TYPE_PGSQL_CONN;
493 conn->name = kore_strdup(db->name);
373494 TAILQ_INSERT_TAIL(&pgsql_conn_free, conn, list);
374495
375 return (KORE_RESULT_OK);
496 return (conn);
376497 }
377498
378499 static void
383504 if (pgsql->conn == NULL)
384505 return;
385506
386 kore_mem_free(pgsql->conn->job->query);
387 kore_pool_put(&pgsql_job_pool, pgsql->conn->job);
507 /* Async query cleanup */
508 if (pgsql->flags & KORE_PGSQL_ASYNC) {
509 if (pgsql->conn != NULL) {
510 fd = PQsocket(pgsql->conn->db);
511 kore_platform_disable_read(fd);
512 kore_pool_put(&pgsql_job_pool, pgsql->conn->job);
513 }
514 }
388515
389516 /* Drain just in case. */
390517 while (PQgetResult(pgsql->conn->db) != NULL)
393520 pgsql->conn->job = NULL;
394521 pgsql->conn->flags |= PGSQL_CONN_FREE;
395522 TAILQ_INSERT_TAIL(&pgsql_conn_free, pgsql->conn, list);
396
397 fd = PQsocket(pgsql->conn->db);
398 kore_platform_disable_read(fd);
399523
400524 pgsql->conn = NULL;
401525 pgsql->state = KORE_PGSQL_STATE_COMPLETE;
420544 http_request_wakeup(req);
421545
422546 pgsql->conn = NULL;
423 pgsql->state = KORE_PGSQL_STATE_ERROR;
424 pgsql->error = kore_strdup(PQerrorMessage(conn->db));
425
426 kore_mem_free(conn->job->query);
547 pgsql_set_error(pgsql, PQerrorMessage(conn->db));
548
427549 kore_pool_put(&pgsql_job_pool, conn->job);
428550 conn->job = NULL;
429551 }
432554 PQfinish(conn->db);
433555
434556 pgsql_conn_count--;
435 kore_mem_free(conn);
436 }
437
438 static void
439 pgsql_read_result(struct kore_pgsql *pgsql, int async)
440 {
441 if (async) {
442 if (PQisBusy(pgsql->conn->db)) {
443 pgsql->state = KORE_PGSQL_STATE_WAIT;
444 return;
445 }
557 kore_free(conn->name);
558 kore_free(conn);
559 }
560
561 static void
562 pgsql_read_result(struct kore_pgsql *pgsql)
563 {
564 if (PQisBusy(pgsql->conn->db)) {
565 pgsql->state = KORE_PGSQL_STATE_WAIT;
566 return;
446567 }
447568
448569 pgsql->result = PQgetResult(pgsql->conn->db);
469590 case PGRES_EMPTY_QUERY:
470591 case PGRES_BAD_RESPONSE:
471592 case PGRES_FATAL_ERROR:
472 pgsql->state = KORE_PGSQL_STATE_ERROR;
473 pgsql->error = kore_strdup(PQresultErrorMessage(pgsql->result));
474 break;
475 }
476 }
593 pgsql_set_error(pgsql, PQresultErrorMessage(pgsql->result));
594 break;
595 }
596 }
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1313 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414 */
1515
16 #include <sys/mman.h>
1617 #include <sys/queue.h>
18
19 #include <stdint.h>
1720
1821 #include "kore.h"
1922
2023 #define POOL_ELEMENT_BUSY 0
2124 #define POOL_ELEMENT_FREE 1
2225
23 static void pool_region_create(struct kore_pool *, u_int32_t);
26 #if defined(KORE_USE_TASKS)
27 static void pool_lock(struct kore_pool *);
28 static void pool_unlock(struct kore_pool *);
29 #endif
30
31 static void pool_region_create(struct kore_pool *, size_t);
32 static void pool_region_destroy(struct kore_pool *);
2433
2534 void
2635 kore_pool_init(struct kore_pool *pool, const char *name,
27 u_int32_t len, u_int32_t elm)
28 {
29 kore_debug("kore_pool_init(%p, %s, %d, %d)", pool, name, len, elm);
30
36 size_t len, size_t elm)
37 {
38 kore_debug("kore_pool_init(%p, %s, %zu, %zu)", pool, name, len, elm);
39
40 if ((pool->name = strdup(name)) == NULL)
41 fatal("kore_pool_init: strdup %s", errno_s);
42
43 pool->lock = 0;
3144 pool->elms = 0;
3245 pool->inuse = 0;
3346 pool->elen = len;
34 pool->name = kore_strdup(name);
3547 pool->slen = pool->elen + sizeof(struct kore_pool_entry);
3648
3749 LIST_INIT(&(pool->regions));
4052 pool_region_create(pool, elm);
4153 }
4254
55 void
56 kore_pool_cleanup(struct kore_pool *pool)
57 {
58 pool->lock = 0;
59 pool->elms = 0;
60 pool->inuse = 0;
61 pool->elen = 0;
62 pool->slen = 0;
63
64 if (pool->name != NULL) {
65 free(pool->name);
66 pool->name = NULL;
67 }
68
69 pool_region_destroy(pool);
70 }
71
4372 void *
4473 kore_pool_get(struct kore_pool *pool)
4574 {
4675 u_int8_t *ptr;
4776 struct kore_pool_entry *entry;
77
78 #if defined(KORE_USE_TASKS)
79 pool_lock(pool);
80 #endif
4881
4982 if (LIST_EMPTY(&(pool->freelist))) {
5083 kore_log(LOG_NOTICE, "pool %s is exhausted (%d/%d)",
5184 pool->name, pool->inuse, pool->elms);
52
5385 pool_region_create(pool, pool->elms);
5486 }
5587
6395
6496 pool->inuse++;
6597
66 #if defined(KORE_PEDANTIC_MALLOC)
67 explicit_bzero(ptr, pool->elen);
98 #if defined(KORE_USE_TASKS)
99 pool_unlock(pool);
68100 #endif
69101
70102 return (ptr);
75107 {
76108 struct kore_pool_entry *entry;
77109
78 #if defined(KORE_PEDANTIC_MALLOC)
79 explicit_bzero(ptr, pool->elen);
110 #if defined(KORE_USE_TASKS)
111 pool_lock(pool);
80112 #endif
81113
82114 entry = (struct kore_pool_entry *)
89121 LIST_INSERT_HEAD(&(pool->freelist), entry, list);
90122
91123 pool->inuse--;
92 }
93
94 static void
95 pool_region_create(struct kore_pool *pool, u_int32_t elms)
96 {
97 u_int32_t i;
124
125 #if defined(KORE_USE_TASKS)
126 pool_unlock(pool);
127 #endif
128 }
129
130 static void
131 pool_region_create(struct kore_pool *pool, size_t elms)
132 {
133 size_t i;
98134 u_int8_t *p;
99135 struct kore_pool_region *reg;
100136 struct kore_pool_entry *entry;
101137
102138 kore_debug("pool_region_create(%p, %d)", pool, elms);
103139
104 reg = kore_malloc(sizeof(struct kore_pool_region));
140 if ((reg = calloc(1, sizeof(struct kore_pool_region))) == NULL)
141 fatal("pool_region_create: calloc: %s", errno_s);
142
105143 LIST_INSERT_HEAD(&(pool->regions), reg, list);
106144
107 reg->start = kore_malloc(elms * pool->slen);
145 if (SIZE_MAX / elms < pool->slen)
146 fatal("pool_region_create: overflow");
147
148 reg->length = elms * pool->slen;
149 reg->start = mmap(NULL, reg->length, PROT_READ | PROT_WRITE,
150 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
151 if (reg->start == NULL)
152 fatal("mmap: %s", errno_s);
153
108154 p = (u_int8_t *)reg->start;
109155
110156 for (i = 0; i < elms; i++) {
118164
119165 pool->elms += elms;
120166 }
167
168 static void
169 pool_region_destroy(struct kore_pool *pool)
170 {
171 struct kore_pool_region *reg;
172
173 kore_debug("pool_region_destroy(%p)", pool);
174
175 /* Take care iterating when modifying list contents */
176 while (!LIST_EMPTY(&pool->regions)) {
177 reg = LIST_FIRST(&pool->regions);
178 LIST_REMOVE(reg, list);
179 (void)munmap(reg->start, reg->length);
180 free(reg);
181 }
182
183 /* Freelist references into the regions memory allocations */
184 LIST_INIT(&pool->freelist);
185 pool->elms = 0;
186 }
187
188 #if defined(KORE_USE_TASKS)
189 static void
190 pool_lock(struct kore_pool *pool)
191 {
192 for (;;) {
193 if (__sync_bool_compare_and_swap(&pool->lock, 0, 1))
194 break;
195 }
196 }
197
198 static void
199 pool_unlock(struct kore_pool *pool)
200 {
201 if (!__sync_bool_compare_and_swap(&pool->lock, 1, 0))
202 fatal("pool_unlock: failed to release %s", pool->name);
203 }
204 #endif
+0
-1025
src/spdy.c less more
0 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 #include <sys/param.h>
17
18 #include <limits.h>
19
20 #include "spdy.h"
21 #include "kore.h"
22 #include "http.h"
23
24 static int spdy_ctrl_frame_syn_stream(struct netbuf *);
25 static int spdy_ctrl_frame_rst_stream(struct netbuf *);
26 static int spdy_ctrl_frame_settings(struct netbuf *);
27 static int spdy_ctrl_frame_ping(struct netbuf *);
28 static int spdy_ctrl_frame_window(struct netbuf *);
29 static int spdy_ctrl_frame_goaway(struct netbuf *);
30 static int spdy_data_frame_recv(struct netbuf *);
31
32 static void spdy_block_write(struct connection *);
33 static void spdy_enable_write(struct connection *);
34
35 static int spdy_zlib_inflate(struct connection *, u_int8_t *,
36 size_t, u_int8_t **, u_int32_t *);
37 static int spdy_zlib_deflate(struct connection *, u_int8_t *,
38 size_t, u_int8_t **, u_int32_t *);
39
40 u_int64_t spdy_idle_time = 120000;
41 u_int32_t spdy_recv_wsize = SPDY_INIT_WSIZE;
42
43 int
44 spdy_frame_recv(struct netbuf *nb)
45 {
46 struct spdy_stream *s;
47 struct spdy_ctrl_frame ctrl;
48 struct spdy_data_frame data;
49 int (*cb)(struct netbuf *), r;
50 struct connection *c = (struct connection *)nb->owner;
51
52 kore_debug("spdy_frame_recv(%p)", nb);
53
54 if (SPDY_CONTROL_FRAME(net_read32(nb->buf))) {
55 ctrl.version = net_read16(nb->buf) & 0x7fff;
56 ctrl.type = net_read16(nb->buf + 2);
57 ctrl.flags = *(u_int8_t *)(nb->buf + 4);
58 ctrl.length = net_read32(nb->buf + 4) & 0xffffff;
59
60 kore_debug("received control frame %d", ctrl.type);
61
62 if ((int)ctrl.length < 0) {
63 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
64 return (KORE_RESULT_OK);
65 }
66
67 if (ctrl.version != 3) {
68 kore_debug("protocol mismatch (recv version %u)",
69 ctrl.version);
70
71 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
72 return (KORE_RESULT_OK);
73 }
74
75 switch (ctrl.type) {
76 case SPDY_CTRL_FRAME_SYN_STREAM:
77 cb = spdy_ctrl_frame_syn_stream;
78 break;
79 case SPDY_CTRL_FRAME_RST_STREAM:
80 cb = spdy_ctrl_frame_rst_stream;
81 break;
82 case SPDY_CTRL_FRAME_SETTINGS:
83 cb = spdy_ctrl_frame_settings;
84 break;
85 case SPDY_CTRL_FRAME_PING:
86 cb = spdy_ctrl_frame_ping;
87 break;
88 case SPDY_CTRL_FRAME_WINDOW:
89 cb = spdy_ctrl_frame_window;
90 break;
91 case SPDY_CTRL_FRAME_GOAWAY:
92 cb = spdy_ctrl_frame_goaway;
93 break;
94 default:
95 cb = NULL;
96 break;
97 }
98
99 r = KORE_RESULT_OK;
100
101 if (cb != NULL) {
102 net_recv_expand(c, ctrl.length, cb);
103 } else {
104 kore_debug("no callback for type %u", ctrl.type);
105 }
106 } else {
107 data.stream_id = net_read32(nb->buf) & ~(1 << 31);
108 if ((s = spdy_stream_lookup(c, data.stream_id)) == NULL) {
109 if (!(c->flags & SPDY_CONN_GOAWAY)) {
110 kore_debug("recv dataframe for bad stream: %u",
111 data.stream_id);
112 r = KORE_RESULT_ERROR;
113 } else {
114 r = KORE_RESULT_OK;
115 }
116 } else if (s->flags & FLAG_FIN) {
117 kore_debug("received data frame but FLAG_FIN was set");
118 r = KORE_RESULT_ERROR;
119 } else {
120 data.flags = *(u_int8_t *)(nb->buf + 4);
121 data.length = net_read32(nb->buf + 4) & 0xffffff;
122 if ((int)data.length < 0) {
123 r = KORE_RESULT_ERROR;
124 } else {
125 r = KORE_RESULT_OK;
126 net_recv_expand(c, data.length,
127 spdy_data_frame_recv);
128 }
129 }
130 }
131
132 if (r != KORE_RESULT_OK) {
133 r = KORE_RESULT_OK;
134 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
135 }
136
137 return (r);
138 }
139
140 int
141 spdy_dataframe_begin(struct connection *c)
142 {
143 struct spdy_stream *s = c->snb->stream;
144
145 kore_debug("spdy_dataframe_begin(%p): s:%u fz:%d sz:%d wz:%d cwz:%d",
146 c, s->stream_id, s->frame_size, s->send_size, s->send_wsize,
147 c->spdy_send_wsize);
148
149 if (s->frame_size != 0 || s->send_size == 0) {
150 fatal("spdy_dataframe_begin(): s:%u fz:%d - sz:%d",
151 s->stream_id, s->frame_size, s->send_size);
152 }
153
154 if ((int)s->send_wsize <= 0 || (int)c->spdy_send_wsize <= 0) {
155 kore_debug("no space for new dataframe right now");
156 spdy_block_write(c);
157 return (KORE_RESULT_ERROR);
158 }
159
160 s->frame_size = MIN(NETBUF_SEND_PAYLOAD_MAX, s->send_size);
161
162 kore_debug("spdy_dataframe_begin(): %u: fz:%d wz:%d cwz:%d",
163 s->stream_id, s->frame_size, s->send_size, c->spdy_send_wsize);
164
165 s->flags &= ~SPDY_DATAFRAME_PRELUDE;
166 spdy_frame_send(c, SPDY_DATA_FRAME, 0, s->frame_size, s, 0);
167
168 return (KORE_RESULT_OK);
169 }
170
171 void
172 spdy_frame_send(struct connection *c, u_int16_t type, u_int8_t flags,
173 u_int32_t len, struct spdy_stream *s, u_int32_t misc)
174 {
175 u_int8_t nb[16];
176 u_int32_t length;
177
178 kore_debug("spdy_frame_send(%p, %u, %u, %u, %p, %u)",
179 c, type, flags, len, s, misc);
180
181 switch (type) {
182 case SPDY_CTRL_FRAME_SYN_REPLY:
183 case SPDY_DATA_FRAME:
184 if (s == NULL)
185 fatal("spdy_frame_send(): stream is NULL for %d", type);
186 break;
187 }
188
189 length = 0;
190 memset(nb, 0, sizeof(nb));
191 switch (type) {
192 case SPDY_CTRL_FRAME_PING:
193 case SPDY_CTRL_FRAME_SYN_REPLY:
194 net_write16(&nb[0], 3);
195 nb[0] |= (1 << 7);
196 net_write16(&nb[2], type);
197
198 if (type != SPDY_CTRL_FRAME_PING) {
199 net_write32(&nb[4], len + 4);
200 nb[4] = flags;
201 net_write32(&nb[8], s->stream_id);
202 } else {
203 net_write32(&nb[4], len);
204 nb[4] = flags;
205 net_write32(&nb[8], misc);
206 }
207
208 length = 12;
209 break;
210 case SPDY_CTRL_FRAME_GOAWAY:
211 net_write16(&nb[0], 3);
212 nb[0] |= (1 << 7);
213 net_write16(&nb[2], type);
214 net_write32(&nb[4], len);
215 nb[4] = flags;
216 length = 8;
217 break;
218 case SPDY_CTRL_FRAME_WINDOW:
219 net_write16(&nb[0], 3);
220 nb[0] |= (1 << 7);
221 net_write16(&nb[2], type);
222 net_write32(&nb[4], len);
223 nb[4] = flags;
224 net_write32(&nb[8], (s != NULL) ? s->stream_id : 0);
225 net_write32(&nb[12], misc);
226 length = 16;
227 break;
228 case SPDY_DATA_FRAME:
229 net_write32(&nb[0], s->stream_id);
230 nb[0] &= ~(1 << 7);
231 net_write32(&nb[4], len);
232 nb[4] = flags;
233 length = 8;
234 break;
235 }
236
237 if (type == SPDY_DATA_FRAME && !(flags & FLAG_FIN)) {
238 net_send_queue(c, nb, length, NULL, NETBUF_BEFORE_CHAIN);
239 } else {
240 net_send_queue(c, nb, length, NULL, NETBUF_LAST_CHAIN);
241 }
242 }
243
244 struct spdy_stream *
245 spdy_stream_lookup(struct connection *c, u_int32_t id)
246 {
247 struct spdy_stream *s;
248
249 TAILQ_FOREACH(s, &(c->spdy_streams), list) {
250 if (s->stream_id == id)
251 return (s);
252 }
253
254 return (NULL);
255 }
256
257 struct spdy_header_block *
258 spdy_header_block_create(int delayed_alloc)
259 {
260 struct spdy_header_block *hblock;
261
262 kore_debug("spdy_header_block_create()");
263
264 hblock = kore_malloc(sizeof(*hblock));
265 if (delayed_alloc == SPDY_HBLOCK_NORMAL) {
266 hblock->header_block = kore_malloc(128);
267 hblock->header_block_len = 128;
268 hblock->header_offset = 4;
269 } else {
270 hblock->header_block = NULL;
271 hblock->header_block_len = 0;
272 hblock->header_offset = 0;
273 }
274
275 hblock->header_pairs = 0;
276
277 return (hblock);
278 }
279
280 void
281 spdy_header_block_add(struct spdy_header_block *hblock, char *name, char *value)
282 {
283 u_int8_t *p;
284 u_int32_t nlen, vlen, tlen;
285
286 kore_debug("spdy_header_block_add(%p, %s, %s)", hblock, name, value);
287
288 nlen = strlen(name);
289 vlen = strlen(value);
290
291 tlen = nlen + 4 + vlen + 4;
292 if ((tlen + hblock->header_offset) > hblock->header_block_len) {
293 hblock->header_block_len += nlen + vlen + 128;
294 hblock->header_block = kore_realloc(hblock->header_block,
295 hblock->header_block_len);
296 }
297
298 p = hblock->header_block + hblock->header_offset;
299 net_write32(p, nlen);
300 memcpy((p + 4), (u_int8_t *)name, nlen);
301 hblock->header_offset += 4 + nlen;
302
303 p = hblock->header_block + hblock->header_offset;
304 net_write32(p, vlen);
305 memcpy((p + 4), (u_int8_t *)value, vlen);
306 hblock->header_offset += 4 + vlen;
307
308 hblock->header_pairs++;
309 }
310
311 u_int8_t *
312 spdy_header_block_release(struct connection *c,
313 struct spdy_header_block *hblock, u_int32_t *len)
314 {
315 u_int8_t *deflated;
316
317 kore_debug("spdy_header_block_release(%p, %p)", hblock, len);
318
319 net_write32(hblock->header_block, hblock->header_pairs);
320 if (!spdy_zlib_deflate(c, hblock->header_block, hblock->header_offset,
321 &deflated, len)) {
322 kore_mem_free(hblock->header_block);
323 kore_mem_free(hblock);
324 return (NULL);
325 }
326
327 kore_mem_free(hblock->header_block);
328 kore_mem_free(hblock);
329
330 return (deflated);
331 }
332
333 int
334 spdy_stream_get_header(struct spdy_header_block *s,
335 const char *header, char **out)
336 {
337 char *cmp;
338 u_int8_t *p, *end;
339 u_int32_t i, nlen, vlen;
340
341 kore_debug("spdy_stream_get_header(%p, %s) <%d>", s, header,
342 s->header_pairs);
343
344 p = s->header_block + 4;
345 end = s->header_block + s->header_block_len;
346
347 if (p >= end) {
348 kore_debug("p >= end when looking for headers");
349 return (KORE_RESULT_ERROR);
350 }
351
352 for (i = 0; i < s->header_pairs; i++) {
353 nlen = net_read32(p);
354 if ((int)nlen < 0 || (p + nlen + 4) > end) {
355 kore_debug("nlen out of bounds on %u (%u)", i, nlen);
356 return (KORE_RESULT_ERROR);
357 }
358
359 vlen = net_read32(p + nlen + 4);
360 if ((int)vlen < 0 || (p + nlen + vlen + 8) > end) {
361 kore_debug("vlen out of bounds on %u (%u)", i, vlen);
362 return (KORE_RESULT_ERROR);
363 }
364
365 cmp = (char *)(p + 4);
366 if (!strncasecmp(cmp, header, nlen)) {
367 cmp = (char *)(p + nlen + 8);
368 *out = kore_malloc(vlen + 1);
369 kore_strlcpy(*out, cmp, vlen + 1);
370 return (KORE_RESULT_OK);
371 }
372
373 p += nlen + vlen + 8;
374 }
375
376 return (KORE_RESULT_ERROR);
377 }
378
379 void
380 spdy_session_teardown(struct connection *c, u_int8_t err)
381 {
382 u_int8_t d[8];
383
384 kore_debug("spdy_session_teardown(%p, %u)", c, err);
385
386 net_write32((u_int8_t *)&d[0], c->client_stream_id);
387 net_write32((u_int8_t *)&d[4], err);
388
389 spdy_frame_send(c, SPDY_CTRL_FRAME_GOAWAY, 0, 8, NULL, 0);
390 net_send_queue(c, d, sizeof(d), NULL, NETBUF_LAST_CHAIN);
391
392 c->flags &= ~CONN_READ_POSSIBLE;
393 c->flags |= CONN_READ_BLOCK;
394
395 net_send_flush(c);
396 kore_connection_disconnect(c);
397 }
398
399 void
400 spdy_update_wsize(struct connection *c, struct spdy_stream *s, u_int32_t len)
401 {
402 s->send_size -= len;
403 s->frame_size -= len;
404 s->send_wsize -= len;
405 c->spdy_send_wsize -= len;
406
407 kore_debug("spdy_update_wsize(): s:%u fz:%d sz:%d wz:%d cwz:%d",
408 s->stream_id, s->frame_size, s->send_size,
409 s->send_wsize, c->spdy_send_wsize);
410
411 if (s->frame_size == 0 && s->send_size > 0) {
412 kore_debug("spdy_update_wsize(): starting new data frame");
413 s->flags |= SPDY_DATAFRAME_PRELUDE;
414 }
415
416 if (s->send_size == 0 && !(s->flags & SPDY_NO_CLOSE)) {
417 if (!(s->flags & SPDY_KORE_FIN)) {
418 s->flags |= SPDY_KORE_FIN;
419 kore_debug("sending final frame %u", s->stream_id);
420 spdy_frame_send(c, SPDY_DATA_FRAME, FLAG_FIN, 0, s, 0);
421 }
422
423 if (s->flags & (SPDY_KORE_FIN | FLAG_FIN)) {
424 spdy_stream_close(c, s, SPDY_KEEP_NETBUFS);
425 return;
426 }
427
428 kore_debug("%u remains half open\n", s->stream_id);
429 }
430
431 if ((int)s->send_wsize <= 0 || (int)c->spdy_send_wsize <= 0) {
432 kore_debug("flow control kicked in for %p:%p", c, s);
433 spdy_block_write(c);
434 }
435 }
436
437 void
438 spdy_stream_close(struct connection *c, struct spdy_stream *s, int rb)
439 {
440 struct http_request *req;
441 struct netbuf *nb, *nt;
442
443 kore_debug("spdy_stream_close(%p, %p) <%d>", c, s, s->stream_id);
444
445 if (s->onclose != NULL)
446 s->onclose(c, s);
447
448 if (rb) {
449 for (nb = TAILQ_FIRST(&(c->send_queue)); nb != NULL; nb = nt) {
450 nt = TAILQ_NEXT(nb, list);
451 if (nb->stream == s) {
452 kore_debug("spdy_stream_close: killing %p", nb);
453 net_remove_netbuf(&(c->send_queue), nb);
454 }
455 }
456 }
457
458 TAILQ_REMOVE(&(c->spdy_streams), s, list);
459 if (s->hblock != NULL) {
460 if (s->hblock->header_block != NULL)
461 kore_mem_free(s->hblock->header_block);
462 kore_mem_free(s->hblock);
463 }
464
465 if (s->httpreq != NULL) {
466 req = s->httpreq;
467 req->stream = NULL;
468 req->flags |= HTTP_REQUEST_DELETE;
469 }
470
471 kore_mem_free(s);
472 }
473
474 static int
475 spdy_ctrl_frame_syn_stream(struct netbuf *nb)
476 {
477 struct spdy_stream *s;
478 struct spdy_syn_stream syn;
479 struct spdy_ctrl_frame ctrl;
480 u_int8_t *src;
481 char *host, *method, *path, *version;
482 struct connection *c = (struct connection *)nb->owner;
483
484 ctrl.version = net_read16(nb->buf) & 0x7fff;
485 ctrl.type = net_read16(nb->buf + 2);
486 ctrl.flags = *(u_int8_t *)(nb->buf + 4);
487 ctrl.length = net_read32(nb->buf + 4) & 0xffffff;
488
489 syn.stream_id = net_read32(nb->buf + 8);
490 syn.assoc_stream_id = net_read32(nb->buf + 12);
491 syn.prio = net_read16(nb->buf + 16) & 0xe000;
492 syn.slot = net_read16(nb->buf + 16) & 0x7;
493
494 kore_debug("spdy_ctrl_frame_syn_stream()");
495 kore_debug("stream_id: %u", syn.stream_id);
496 kore_debug("length : %u", ctrl.length);
497
498 if (c->spdy_send_wsize > 0 && (c->flags & CONN_WRITE_BLOCK))
499 spdy_enable_write(c);
500
501 if ((int)ctrl.length < 0) {
502 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
503 return (KORE_RESULT_OK);
504 }
505
506 if ((syn.stream_id % 2) == 0 || syn.stream_id == 0) {
507 kore_debug("client sent incorrect id for SPDY_SYN_STREAM (%u)",
508 syn.stream_id);
509 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
510 return (KORE_RESULT_OK);
511 }
512
513 if (syn.stream_id < c->client_stream_id) {
514 kore_debug("client sent incorrect id SPDY_SYN_STREAM (%u < %u)",
515 syn.stream_id, c->client_stream_id);
516 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
517 return (KORE_RESULT_OK);
518 }
519
520 if ((s = spdy_stream_lookup(c, syn.stream_id)) != NULL) {
521 kore_debug("duplicate SPDY_SYN_STREAM (%u)", syn.stream_id);
522 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
523 return (KORE_RESULT_OK);
524 }
525
526 s = kore_malloc(sizeof(*s));
527 s->send_size = 0;
528 s->frame_size = 0;
529 s->httpreq = NULL;
530 s->onclose = NULL;
531 s->prio = syn.prio;
532 s->flags = ctrl.flags;
533 s->recv_wsize = spdy_recv_wsize;
534 s->send_wsize = c->wsize_initial;
535 s->stream_id = syn.stream_id;
536 s->hblock = spdy_header_block_create(SPDY_HBLOCK_DELAYED_ALLOC);
537
538 src = (nb->buf + SPDY_FRAME_SIZE + SPDY_SYNFRAME_SIZE);
539 kore_debug("compressed headers are %u bytes long", ctrl.length - 10);
540 if (!spdy_zlib_inflate(c, src, (ctrl.length - SPDY_SYNFRAME_SIZE),
541 &(s->hblock->header_block), &(s->hblock->header_block_len))) {
542 kore_mem_free(s->hblock->header_block);
543 kore_mem_free(s->hblock);
544 kore_mem_free(s);
545 spdy_session_teardown(c, SPDY_SESSION_ERROR_INTERNAL);
546 return (KORE_RESULT_OK);
547 }
548
549 s->hblock->header_pairs = net_read32(s->hblock->header_block);
550 if ((int)s->hblock->header_pairs < 0) {
551 kore_mem_free(s->hblock->header_block);
552 kore_mem_free(s->hblock);
553 kore_mem_free(s);
554 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
555 return (KORE_RESULT_OK);
556 }
557
558 kore_debug("got %u headers", s->hblock->header_pairs);
559
560 path = NULL;
561 host = NULL;
562 method = NULL;
563 version = NULL;
564
565 #define GET_HEADER(n, r) \
566 if (!spdy_stream_get_header(s->hblock, n, r)) { \
567 kore_mem_free(s->hblock->header_block); \
568 kore_mem_free(s->hblock); \
569 kore_mem_free(s); \
570 kore_debug("no such header: %s", n); \
571 if (path != NULL) \
572 kore_mem_free(path); \
573 if (host != NULL) \
574 kore_mem_free(host); \
575 if (method != NULL) \
576 kore_mem_free(method); \
577 if (version != NULL) \
578 kore_mem_free(version); \
579 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL); \
580 return (KORE_RESULT_OK); \
581 }
582
583 GET_HEADER(":path", &path);
584 GET_HEADER(":method", &method);
585 GET_HEADER(":host", &host);
586 GET_HEADER(":version", &version);
587
588 c->client_stream_id = s->stream_id;
589 TAILQ_INSERT_TAIL(&(c->spdy_streams), s, list);
590
591 /*
592 * We don't care so much for what http_request_new() tells us here,
593 * we just have to clean up after passing our stuff to it.
594 */
595 (void)http_request_new(c, s, host, method, path, version,
596 (struct http_request **)&(s->httpreq));
597
598 kore_mem_free(path);
599 kore_mem_free(method);
600 kore_mem_free(host);
601 kore_mem_free(version);
602 net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
603
604 kore_debug("SPDY_SYN_STREAM: %u:%u:%u", s->stream_id,
605 s->flags, s->prio);
606
607 return (KORE_RESULT_OK);
608 }
609
610 static int
611 spdy_ctrl_frame_rst_stream(struct netbuf *nb)
612 {
613 struct spdy_stream *s;
614 u_int32_t stream_id;
615 struct connection *c = (struct connection *)nb->owner;
616
617 stream_id = net_read32(nb->buf + SPDY_FRAME_SIZE);
618 if ((stream_id % 2) == 0) {
619 kore_debug("received RST for non-client stream %u", stream_id);
620 return (KORE_RESULT_ERROR);
621 }
622
623 if ((s = spdy_stream_lookup(c, stream_id)) == NULL) {
624 kore_debug("received RST for unknown stream %u", stream_id);
625 return (KORE_RESULT_ERROR);
626 }
627
628 spdy_stream_close(c, s, SPDY_REMOVE_NETBUFS);
629 net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
630
631 return (KORE_RESULT_OK);
632 }
633
634 static int
635 spdy_ctrl_frame_settings(struct netbuf *nb)
636 {
637 struct spdy_stream *s;
638 u_int8_t *buf;
639 u_int32_t ecount, i, id, val, length, diff;
640 struct connection *c = (struct connection *)nb->owner;
641
642 ecount = net_read32(nb->buf + SPDY_FRAME_SIZE);
643 length = net_read32(nb->buf + 4) & 0xffffff;
644 if ((int)ecount < 0 || (int)length < 0) {
645 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
646 return (KORE_RESULT_OK);
647 }
648
649 kore_debug("SPDY_SETTINGS: %u settings present", ecount);
650
651 if (length != ((ecount * 8) + 4)) {
652 kore_debug("ecount is not correct (%u != %u)", length,
653 (ecount * 8) + 4);
654 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
655 return (KORE_RESULT_OK);
656 }
657
658 buf = nb->buf + SPDY_FRAME_SIZE + 4;
659 for (i = 0; i < ecount; i++) {
660 id = net_read32(buf) & 0xffffff;
661 val = net_read32(buf + 4);
662
663 if ((int)val < 0) {
664 buf += 8;
665 continue;
666 }
667
668 switch (id) {
669 case SETTINGS_INITIAL_WINDOW_SIZE:
670 diff = val - c->wsize_initial;
671 c->wsize_initial = val;
672 TAILQ_FOREACH(s, &(c->spdy_streams), list)
673 s->send_wsize += diff;
674 kore_debug("updated wsize with %d", diff);
675 break;
676 default:
677 kore_debug("no handling for setting %u:%u", id, val);
678 break;
679 }
680
681 buf += 8;
682 }
683
684 net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
685
686 return (KORE_RESULT_OK);
687 }
688
689 static int
690 spdy_ctrl_frame_ping(struct netbuf *nb)
691 {
692 u_int32_t id;
693 struct connection *c = (struct connection *)nb->owner;
694
695 id = ntohl(*(u_int32_t *)(nb->buf + SPDY_FRAME_SIZE));
696 kore_debug("SPDY_PING: %u", id);
697
698 /* XXX todo - check if we sent the ping. */
699 if ((id % 2) == 0) {
700 kore_debug("received malformed client PING (%u)", id);
701 spdy_session_teardown(c, SPDY_SESSION_ERROR_PROTOCOL);
702 return (KORE_RESULT_OK);
703 }
704
705 spdy_frame_send(c, SPDY_CTRL_FRAME_PING, 0, 4, NULL, id);
706 net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
707
708 return (KORE_RESULT_OK);
709 }
710
711 static int
712 spdy_ctrl_frame_window(struct netbuf *nb)
713 {
714 int r;
715 struct spdy_stream *s;
716 u_int32_t stream_id, window_size;
717 struct connection *c = (struct connection *)nb->owner;
718
719 stream_id = net_read32(nb->buf + SPDY_FRAME_SIZE);
720 window_size = net_read32(nb->buf + SPDY_FRAME_SIZE + 4);
721 kore_debug("window_update: %u for %u", window_size, stream_id);
722
723 r = KORE_RESULT_OK;
724 if ((s = spdy_stream_lookup(c, stream_id)) != NULL) {
725 s->send_wsize += window_size;
726 if ((u_int64_t)s->send_wsize > SPDY_FLOW_WINDOW_MAX) {
727 kore_debug("window_update: size too large");
728 return (KORE_RESULT_ERROR);
729 }
730
731 if (c->flags & CONN_WRITE_BLOCK &&
732 s->send_wsize > 0 && c->spdy_send_wsize > 0) {
733 kore_debug("stream %u no longer blocked", s->stream_id);
734 spdy_enable_write(c);
735 r = net_send_flush(c);
736 }
737 } else {
738 c->spdy_send_wsize += window_size;
739 if ((u_int64_t)c->spdy_send_wsize > SPDY_FLOW_WINDOW_MAX) {
740 kore_debug("window_update: size too large");
741 return (KORE_RESULT_ERROR);
742 }
743
744 if (c->flags & CONN_WRITE_BLOCK && c->spdy_send_wsize > 0) {
745 kore_debug("session %p no longer blocked", c);
746 spdy_enable_write(c);
747 r = net_send_flush(c);
748 }
749 }
750
751 net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
752
753 return (r);
754 }
755
756 static int
757 spdy_ctrl_frame_goaway(struct netbuf *nb)
758 {
759 struct connection *c = (struct connection *)nb->owner;
760
761 kore_debug("spdy_ctrl_frame_goaway(%p)", c);
762
763 c->flags |= SPDY_CONN_GOAWAY;
764 kore_connection_disconnect(c);
765
766 return (KORE_RESULT_OK);
767 }
768
769 static int
770 spdy_data_frame_recv(struct netbuf *nb)
771 {
772 struct spdy_stream *s;
773 int err;
774 struct http_request *req;
775 struct spdy_data_frame data;
776 char *content;
777 struct connection *c = (struct connection *)nb->owner;
778
779 data.stream_id = net_read32(nb->buf) & ~(1 << 31);
780 data.flags = *(u_int8_t *)(nb->buf + 4);
781 data.length = net_read32(nb->buf + 4) & 0xffffff;
782 kore_debug("SPDY_SESSION_DATA: %u:%u:%u", data.stream_id,
783 data.flags, data.length);
784
785 if ((int)data.length < 0)
786 return (KORE_RESULT_ERROR);
787
788 if ((s = spdy_stream_lookup(c, data.stream_id)) == NULL) {
789 kore_debug("session data for non-existant stream");
790 /* stream error */
791 return (KORE_RESULT_ERROR);
792 }
793
794 req = (struct http_request *)s->httpreq;
795 if (req == NULL || !(req->flags & HTTP_REQUEST_EXPECT_BODY)) {
796 kore_debug("data frame for non post received");
797 /* stream error */
798 return (KORE_RESULT_ERROR);
799 }
800
801 if (req->http_body == NULL) {
802 if (!spdy_stream_get_header(s->hblock,
803 "content-length", &content)) {
804 kore_debug("no content-length found for body");
805 return (KORE_RESULT_ERROR);
806 }
807
808 s->post_size = kore_strtonum(content, 10, 0, LLONG_MAX, &err);
809 if (err == KORE_RESULT_ERROR) {
810 kore_debug("bad content-length: %s", content);
811 kore_mem_free(content);
812 return (KORE_RESULT_ERROR);
813 }
814
815 kore_mem_free(content);
816
817 if (s->post_size == 0) {
818 req->flags |= HTTP_REQUEST_COMPLETE;
819 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
820 net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
821 return (KORE_RESULT_OK);
822 }
823
824 if (s->post_size > http_body_max) {
825 kore_log(LOG_NOTICE, "body data too large (%ld > %ld)",
826 s->post_size, http_body_max);
827 return (KORE_RESULT_ERROR);
828 }
829
830 req->http_body = kore_buf_create(s->post_size);
831 }
832
833 if ((req->http_body->offset + data.length) > s->post_size) {
834 kore_debug("POST would grow too large");
835 return (KORE_RESULT_ERROR);
836 }
837
838 kore_buf_append(req->http_body, (nb->buf + SPDY_FRAME_SIZE),
839 data.length);
840
841 if (data.flags & FLAG_FIN || req->http_body->offset == s->post_size) {
842 if (req->http_body->offset != s->post_size) {
843 kore_debug("FLAG_FIN before all POST data received");
844 return (KORE_RESULT_ERROR);
845 }
846
847 s->post_size = 0;
848 s->flags |= FLAG_FIN;
849 req->flags |= HTTP_REQUEST_COMPLETE;
850 req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
851 }
852
853 net_recv_reset(c, SPDY_FRAME_SIZE, spdy_frame_recv);
854
855 /*
856 * XXX - This can be implemented better so we can stagger
857 * window updates a bit and not constantly hit flow control.
858 */
859 s->recv_wsize -= data.length;
860 spdy_frame_send(c, SPDY_CTRL_FRAME_WINDOW, 0, 8, s, data.length);
861 s->recv_wsize += data.length;
862
863 c->spdy_recv_wsize -= data.length;
864 spdy_frame_send(c, SPDY_CTRL_FRAME_WINDOW, 0, 8, NULL, data.length);
865 c->spdy_recv_wsize += data.length;
866
867 kore_debug("data frame recv: wz:%d cwz:%d", s->recv_wsize,
868 c->spdy_recv_wsize);
869
870 return (KORE_RESULT_OK);
871 }
872
873 static void
874 spdy_block_write(struct connection *c)
875 {
876 kore_debug("spdy_block_write(%p)", c);
877
878 c->flags |= CONN_WRITE_BLOCK;
879 c->flags &= ~CONN_WRITE_POSSIBLE;
880 }
881
882 static void
883 spdy_enable_write(struct connection *c)
884 {
885 kore_debug("spdy_enable_write(%p)", c);
886
887 c->flags &= ~CONN_WRITE_BLOCK;
888 c->flags |= CONN_WRITE_POSSIBLE;
889 }
890
891 static int
892 spdy_zlib_inflate(struct connection *c, u_int8_t *src, size_t len,
893 u_int8_t **dst, u_int32_t *olen)
894 {
895 size_t have;
896 int r, ret;
897 u_char inflate_buffer[SPDY_ZLIB_CHUNK];
898
899 kore_debug("spdy_zlib_inflate(%p, %p, %d)", c, src, len);
900
901 if (c->inflate_started == 0) {
902 c->z_inflate.avail_in = 0;
903 c->z_inflate.next_in = Z_NULL;
904 c->z_inflate.zalloc = Z_NULL;
905 c->z_inflate.zfree = Z_NULL;
906 if ((r = inflateInit(&(c->z_inflate))) != Z_OK) {
907 kore_debug("inflateInit() failed: %d", r);
908 return (KORE_RESULT_ERROR);
909 }
910
911 c->inflate_started = 1;
912 }
913
914 *olen = 0;
915 *dst = NULL;
916
917 ret = -1;
918 c->z_inflate.avail_in = len;
919 c->z_inflate.next_in = src;
920 while (ret == -1) {
921 c->z_inflate.avail_out = SPDY_ZLIB_CHUNK;
922 c->z_inflate.next_out = inflate_buffer;
923
924 r = inflate(&(c->z_inflate), Z_SYNC_FLUSH);
925 switch (r) {
926 case Z_NEED_DICT:
927 r = inflateSetDictionary(&(c->z_inflate),
928 SPDY_dictionary_txt, SPDY_ZLIB_DICT_SIZE);
929 if (r != Z_OK) {
930 inflateEnd(&(c->z_inflate));
931 kore_debug("inflateSetDictionary(): %d", r);
932 return (KORE_RESULT_ERROR);
933 }
934
935 continue;
936 case Z_BUF_ERROR:
937 case Z_DATA_ERROR:
938 case Z_MEM_ERROR:
939 ret = KORE_RESULT_ERROR;
940 kore_debug("inflate(): %d", r);
941 break;
942 case Z_OK:
943 have = SPDY_ZLIB_CHUNK - c->z_inflate.avail_out;
944 *olen += have;
945 *dst = kore_realloc(*dst, *olen);
946 memcpy((*dst) + (*olen - have), inflate_buffer, have);
947
948 if (c->z_inflate.avail_in != 0 ||
949 c->z_inflate.avail_out == 0)
950 break;
951 /* FALLTHROUGH */
952 case Z_STREAM_END:
953 ret = KORE_RESULT_OK;
954 break;
955 }
956 }
957
958 return (ret);
959 }
960
961 static int
962 spdy_zlib_deflate(struct connection *c, u_int8_t *src, size_t len,
963 u_int8_t **dst, u_int32_t *olen)
964 {
965 size_t have;
966 int r, ret;
967 u_char deflate_buffer[SPDY_ZLIB_CHUNK];
968
969 kore_debug("spdy_zlib_deflate(%p, %p, %d)", c, src, len);
970
971 if (c->deflate_started == 0) {
972 c->z_deflate.avail_in = 0;
973 c->z_deflate.next_in = Z_NULL;
974 c->z_deflate.zalloc = Z_NULL;
975 c->z_deflate.zfree = Z_NULL;
976 if ((r = deflateInit(&(c->z_deflate), -1)) != Z_OK) {
977 kore_debug("deflateInit() failed: %d", r);
978 return (KORE_RESULT_ERROR);
979 }
980
981 r = deflateSetDictionary(&(c->z_deflate), SPDY_dictionary_txt,
982 SPDY_ZLIB_DICT_SIZE);
983 if (r != Z_OK) {
984 deflateEnd(&(c->z_deflate));
985 kore_debug("deflateSetDictionary(): %d", r);
986 return (KORE_RESULT_ERROR);
987 }
988
989 c->deflate_started = 1;
990 }
991
992 *olen = 0;
993 *dst = NULL;
994
995 ret = -1;
996 c->z_deflate.avail_in = len;
997 c->z_deflate.next_in = src;
998 while (ret == -1) {
999 c->z_deflate.avail_out = SPDY_ZLIB_CHUNK;
1000 c->z_deflate.next_out = deflate_buffer;
1001
1002 r = deflate(&(c->z_deflate), Z_SYNC_FLUSH);
1003 switch (r) {
1004 case Z_BUF_ERROR:
1005 case Z_DATA_ERROR:
1006 case Z_MEM_ERROR:
1007 ret = KORE_RESULT_ERROR;
1008 kore_debug("deflate(): %d", r);
1009 break;
1010 case Z_OK:
1011 have = SPDY_ZLIB_CHUNK - c->z_deflate.avail_out;
1012 *olen += have;
1013 *dst = kore_realloc(*dst, *olen);
1014 memcpy((*dst) + (*olen - have), deflate_buffer, have);
1015
1016 if (c->z_deflate.avail_in == 0 &&
1017 c->z_deflate.avail_out != 0)
1018 ret = KORE_RESULT_OK;
1019 break;
1020 }
1021 }
1022
1023 return (ret);
1024 }
2626 #include "tasks.h"
2727
2828 static u_int8_t threads;
29 static pthread_mutex_t task_thread_lock;
30
3129 static TAILQ_HEAD(, kore_task_thread) task_threads;
30
31 u_int16_t kore_task_threads = KORE_TASK_THREADS;
3232
3333 static void *task_thread(void *);
3434 static void task_channel_read(int, void *, u_int32_t);
4747 void
4848 kore_task_init(void)
4949 {
50 int r;
51
5250 threads = 0;
53
5451 TAILQ_INIT(&task_threads);
55 if ((r = pthread_mutex_init(&task_thread_lock, NULL)) != 0)
56 fatal("kore_task_init: pthread_mutex_init: %d", r);
5752 }
5853
5954 void
6055 kore_task_create(struct kore_task *t, int (*entry)(struct kore_task *))
6156 {
57 t->cb = NULL;
58 #if !defined(KORE_NO_HTTP)
6259 t->req = NULL;
60 #endif
6361 t->entry = entry;
6462 t->type = KORE_TYPE_TASK;
6563 t->state = KORE_TASK_STATE_CREATED;
7573 struct kore_task_thread *tt;
7674
7775 kore_platform_schedule_read(t->fds[0], t);
78
79 pthread_mutex_lock(&task_thread_lock);
80 if (TAILQ_EMPTY(&task_threads))
76 if (threads < kore_task_threads) {
77 /* task_thread_spawn() will lock tt->lock for us. */
8178 task_thread_spawn(&tt);
82 else
83 tt = TAILQ_FIRST(&task_threads);
84
85 pthread_mutex_unlock(&task_thread_lock);
86 pthread_mutex_lock(&(tt->lock));
79 } else {
80 /* Cycle task around. */
81 if ((tt = TAILQ_FIRST(&task_threads)) == NULL)
82 fatal("no available tasks threads?");
83 pthread_mutex_lock(&(tt->lock));
84 TAILQ_REMOVE(&task_threads, tt, list);
85 TAILQ_INSERT_TAIL(&task_threads, tt, list);
86 }
8787
8888 t->thread = tt;
8989 TAILQ_INSERT_TAIL(&(tt->tasks), t, list);
9292 pthread_cond_signal(&(tt->cond));
9393 }
9494
95 #if !defined(KORE_NO_HTTP)
9596 void
9697 kore_task_bind_request(struct kore_task *t, struct http_request *req)
9798 {
9899 kore_debug("kore_task_bind_request: %p bound to %p", req, t);
100
101 if (t->cb != NULL)
102 fatal("cannot bind cbs and requests at the same time");
99103
100104 t->req = req;
101105 LIST_INSERT_HEAD(&(req->tasks), t, rlist);
102106
103107 http_request_sleep(req);
104108 }
109 #endif
110
111 void
112 kore_task_bind_callback(struct kore_task *t, void (*cb)(struct kore_task *))
113 {
114 #if !defined(KORE_NO_HTTP)
115 if (t->req != NULL)
116 fatal("cannot bind requests and cbs at the same time");
117 #endif
118 t->cb = cb;
119 }
105120
106121 void
107122 kore_task_destroy(struct kore_task *t)
108123 {
109124 kore_debug("kore_task_destroy: %p", t);
110125
126 #if !defined(KORE_NO_HTTP)
111127 if (t->req != NULL) {
112128 t->req = NULL;
113129 LIST_REMOVE(t, rlist);
114130 }
131 #endif
115132
116133 pthread_rwlock_wrlock(&(t->lock));
117134
187204 {
188205 kore_debug("kore_task_handle: %p, %d", t, finished);
189206
207 #if !defined(KORE_NO_HTTP)
190208 if (t->req != NULL)
191209 http_request_wakeup(t->req);
210 #endif
192211
193212 if (finished) {
194213 kore_platform_disable_read(t->fds[0]);
195214 kore_task_set_state(t, KORE_TASK_STATE_FINISHED);
215 #if !defined(KORE_NO_HTTP)
196216 if (t->req != NULL) {
197217 if (t->req->flags & HTTP_REQUEST_DELETE)
198218 kore_task_destroy(t);
199219 }
200 }
220 #endif
221 }
222
223 if (t->cb != NULL)
224 t->cb(t);
201225 }
202226
203227 int
292316 TAILQ_INIT(&(tt->tasks));
293317 pthread_cond_init(&(tt->cond), NULL);
294318 pthread_mutex_init(&(tt->lock), NULL);
319 pthread_mutex_lock(&(tt->lock));
320 TAILQ_INSERT_TAIL(&task_threads, tt, list);
295321
296322 if (pthread_create(&(tt->tid), NULL, task_thread, tt) != 0)
297323 fatal("pthread_create: %s", errno_s);
308334 kore_debug("task_thread: #%d starting", tt->idx);
309335
310336 pthread_mutex_lock(&(tt->lock));
311
312 pthread_mutex_lock(&task_thread_lock);
313 TAILQ_INSERT_TAIL(&task_threads, tt, list);
314 pthread_mutex_unlock(&task_thread_lock);
315337
316338 for (;;) {
317339 if (TAILQ_EMPTY(&(tt->tasks)))
323345 TAILQ_REMOVE(&(tt->tasks), t, list);
324346 pthread_mutex_unlock(&(tt->lock));
325347
326 pthread_mutex_lock(&task_thread_lock);
327 TAILQ_REMOVE(&task_threads, tt, list);
328 pthread_mutex_unlock(&task_thread_lock);
329
330348 kore_debug("task_thread#%d: executing %p", tt->idx, t);
331349
332350 kore_task_set_state(t, KORE_TASK_STATE_RUNNING);
333351 kore_task_set_result(t, t->entry(t));
334352 kore_task_finish(t);
335353
336 pthread_mutex_lock(&task_thread_lock);
337 TAILQ_INSERT_HEAD(&task_threads, tt, list);
338 pthread_mutex_unlock(&task_thread_lock);
339
340354 pthread_mutex_lock(&(tt->lock));
341355 }
342356
00 /*
1 * Copyright (c) 2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
2727 }
2828
2929 struct kore_timer *
30 kore_timer_add(void (*cb)(void *, u_int64_t, u_int64_t), u_int64_t interval,
30 kore_timer_add(void (*cb)(void *, u_int64_t), u_int64_t interval,
3131 void *arg, int flags)
3232 {
3333 struct kore_timer *timer, *t;
5555 kore_timer_remove(struct kore_timer *timer)
5656 {
5757 TAILQ_REMOVE(&kore_timers, timer, list);
58 kore_mem_free(timer);
58 kore_free(timer);
5959 }
6060
6161 u_int64_t
6262 kore_timer_run(u_int64_t now)
6363 {
6464 struct kore_timer *timer, *t;
65 u_int64_t next_timer, delta;
65 u_int64_t next_timer;
6666
6767 next_timer = 100;
6868
7373 }
7474
7575 TAILQ_REMOVE(&kore_timers, timer, list);
76 delta = now - timer->nextrun;
77 timer->cb(timer->arg, now, delta);
76 timer->cb(timer->arg, now);
7877
7978 if (timer->flags & KORE_TIMER_ONESHOT) {
80 kore_mem_free(timer);
79 kore_free(timer);
8180 } else {
82 timer->nextrun += timer->interval - delta;
81 timer->nextrun = now + timer->interval;
8382 TAILQ_FOREACH(t, &kore_timers, list) {
8483 if (t->nextrun > timer->nextrun) {
8584 TAILQ_INSERT_BEFORE(t, timer, list);
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1515
1616 #include <sys/time.h>
1717
18 #include <ctype.h>
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <time.h>
1824 #include <limits.h>
1925
2026 #include "kore.h"
5662 void
5763 kore_log_init(void)
5864 {
65 #if defined(KORE_SINGLE_BINARY)
66 extern const char *__progname;
67 const char *name = __progname;
68 #else
69 const char *name = "kore";
70 #endif
71
5972 if (!foreground)
60 openlog("kore", LOG_NDELAY | LOG_PID, LOG_DAEMON);
73 openlog(name, LOG_NDELAY | LOG_PID, LOG_DAEMON);
6174 }
6275
6376 void
6477 kore_log(int prio, const char *fmt, ...)
6578 {
6679 va_list args;
67 char buf[2048];
80 char buf[2048], tmp[32];
6881
6982 va_start(args, fmt);
7083 (void)vsnprintf(buf, sizeof(buf), fmt, args);
7184 va_end(args);
7285
7386 if (worker != NULL) {
87 (void)snprintf(tmp, sizeof(tmp), "wrk %d", worker->id);
88 #if !defined(KORE_NO_TLS)
89 if (worker->id == KORE_WORKER_KEYMGR)
90 (void)kore_strlcpy(tmp, "keymgr", sizeof(tmp));
91 #endif
7492 if (foreground)
75 printf("[wrk %d]: %s\n", worker->id, buf);
93 printf("[%s]: %s\n", tmp, buf);
7694 else
77 syslog(prio, "[wrk %d]: %s", worker->id, buf);
95 syslog(prio, "[%s]: %s", tmp, buf);
7896 } else {
7997 if (foreground)
8098 printf("[parent]: %s\n", buf);
83101 }
84102 }
85103
86 void
87 kore_strlcpy(char *dst, const char *src, size_t len)
104 size_t
105 kore_strlcpy(char *dst, const char *src, const size_t len)
88106 {
89107 char *d = dst;
90108 const char *s = src;
91109 const char *end = dst + len - 1;
110
111 if (len == 0)
112 fatal("kore_strlcpy: len == 0");
92113
93114 while ((*d = *s) != '\0') {
94115 if (d == end) {
99120 d++;
100121 s++;
101122 }
123
124 while (*s != '\0')
125 s++;
126
127 return (s - src);
102128 }
103129
104130 int
202228 int count;
203229 char **ap;
204230
231 if (ele == 0)
232 return (0);
233
205234 count = 0;
206235 for (ap = out; ap < &out[ele - 1] &&
207236 (*ap = strsep(&input, delim)) != NULL;) {
216245 }
217246
218247 void
219 kore_strip_chars(char *in, char strip, char **out)
248 kore_strip_chars(char *in, const char strip, char **out)
220249 {
221250 u_int32_t len;
222251 char *s, *p;
311340 }
312341
313342 out:
314 kore_mem_free(sdup);
343 kore_free(sdup);
315344 return (t);
316345 }
317346
347376 }
348377
349378 int
350 kore_base64_encode(u_int8_t *data, u_int32_t len, char **out)
351 {
379 kore_base64_encode(u_int8_t *data, size_t len, char **out)
380 {
381 u_int32_t b;
352382 struct kore_buf *res;
383 size_t plen, idx;
353384 u_int8_t n, *pdata;
354385 int i, padding;
355 u_int32_t idx, b, plen;
356386
357387 if ((len % 3) != 0) {
358388 padding = 3 - (len % 3);
359389 plen = len + padding;
390 if (plen < len)
391 fatal("plen wrapped");
392
360393 pdata = kore_malloc(plen);
361
362394 memcpy(pdata, data, len);
363395 memset(pdata + len, 0, padding);
364396 } else {
367399 pdata = data;
368400 }
369401
370 res = kore_buf_create(plen);
402 res = kore_buf_alloc(plen);
371403
372404 i = 2;
373405 b = 0;
397429 kore_buf_append(res, (u_int8_t *)"=", 1);
398430
399431 if (pdata != data)
400 kore_mem_free(pdata);
432 kore_free(pdata);
401433
402434 pdata = kore_buf_release(res, &plen);
435 if ((plen + 1) < plen)
436 fatal("plen wrapped");
437
403438 *out = kore_malloc(plen + 1);
404 kore_strlcpy(*out, (char *)pdata, plen + 1);
405 kore_mem_free(pdata);
439 (void)kore_strlcpy(*out, (char *)pdata, plen + 1);
440 kore_free(pdata);
406441
407442 return (KORE_RESULT_OK);
408443 }
409444
410445 int
411 kore_base64_decode(char *in, u_int8_t **out, u_int32_t *olen)
446 kore_base64_decode(char *in, u_int8_t **out, size_t *olen)
412447 {
413448 int i, c;
414449 struct kore_buf *res;
420455 d = 0;
421456 c = 0;
422457 len = strlen(in);
423 res = kore_buf_create(len);
458 res = kore_buf_alloc(len);
424459
425460 for (idx = 0; idx < len; idx++) {
426461 c = in[idx];
472507 }
473508
474509 void *
475 kore_mem_find(void *src, size_t slen, void *needle, u_int32_t len)
476 {
477 u_int8_t *p, *end;
478
479 end = (u_int8_t *)src + slen;
480 for (p = src; p < end; p++) {
481 if (*p != *(u_int8_t *)needle)
510 kore_mem_find(void *src, size_t slen, void *needle, size_t len)
511 {
512 size_t pos;
513
514 for (pos = 0; pos < slen; pos++) {
515 if ( *((u_int8_t *)src + pos) != *(u_int8_t *)needle)
482516 continue;
483517
484 if ((end - p) < len)
518 if ((slen - pos) < len)
485519 return (NULL);
486520
487 if (!memcmp(p, needle, len))
488 return (p);
521 if (!memcmp((u_int8_t *)src + pos, needle, len))
522 return ((u_int8_t *)src + pos);
489523 }
490524
491525 return (NULL);
526 }
527
528 char *
529 kore_text_trim(char *string, size_t len)
530 {
531 char *end;
532
533 if (len == 0)
534 return (string);
535
536 end = (string + len) - 1;
537 while (isspace(*string) && string < end)
538 string++;
539
540 while (isspace(*end) && end > string)
541 *(end)-- = '\0';
542
543 return (string);
544 }
545
546 char *
547 kore_read_line(FILE *fp, char *in, size_t len)
548 {
549 char *p, *t;
550
551 if (fgets(in, len, fp) == NULL)
552 return (NULL);
553
554 p = in;
555 in[strcspn(in, "\n")] = '\0';
556
557 while (isspace(*p))
558 p++;
559
560 if (p[0] == '#' || p[0] == '\0') {
561 p[0] = '\0';
562 return (p);
563 }
564
565 for (t = p; *t != '\0'; t++) {
566 if (*t == '\t')
567 *t = ' ';
568 }
569
570 return (p);
492571 }
493572
494573 void
495574 fatal(const char *fmt, ...)
496575 {
497 va_list args;
498 char buf[2048];
576 va_list args;
577 char buf[2048];
578 extern const char *__progname;
499579
500580 va_start(args, fmt);
501581 (void)vsnprintf(buf, sizeof(buf), fmt, args);
504584 if (!foreground)
505585 kore_log(LOG_ERR, "%s", buf);
506586
507 printf("kore: %s\n", buf);
587 #if !defined(KORE_NO_TLS)
588 if (worker != NULL && worker->id == KORE_WORKER_KEYMGR)
589 kore_keymgr_cleanup();
590 #endif
591
592 printf("%s: %s\n", __progname, buf);
508593 exit(1);
509594 }
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
3434 switch (val->type) {
3535 case KORE_VALIDATOR_TYPE_REGEX:
3636 if (regcomp(&(val->rctx), arg, REG_EXTENDED | REG_NOSUB)) {
37 kore_mem_free(val);
37 kore_free(val);
3838 kore_log(LOG_NOTICE,
3939 "validator %s has bad regex %s", name, arg);
4040 return (KORE_RESULT_ERROR);
4141 }
4242 break;
4343 case KORE_VALIDATOR_TYPE_FUNCTION:
44 if ((val->func = kore_module_getsym(arg)) == NULL) {
45 kore_mem_free(val);
44 *(void **)(&val->func) = kore_module_getsym(arg);
45 if (val->func == NULL) {
46 kore_free(val);
4647 kore_log(LOG_NOTICE,
4748 "validator %s has undefined callback %s",
4849 name, arg);
5051 }
5152 break;
5253 default:
53 kore_mem_free(val);
54 kore_free(val);
5455 return (KORE_RESULT_ERROR);
5556 }
5657
111112 if (val->type != KORE_VALIDATOR_TYPE_FUNCTION)
112113 continue;
113114
114 if ((val->func = kore_module_getsym(val->arg)) == NULL)
115 *(void **)&(val->func) = kore_module_getsym(val->arg);
116 if (val->func == NULL)
115117 fatal("no function for validator %s found", val->name);
116118 }
117119 }
1515
1616 #include <sys/param.h>
1717
18 #include <openssl/sha.h>
19
1820 #include <limits.h>
21 #include <string.h>
1922
2023 #include "kore.h"
2124 #include "http.h"
3437
3538 #define WEBSOCKET_SERVER_RESPONSE "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
3639
37 struct websocket_data {
38 u_int8_t op;
39 void *data;
40 size_t len;
41 };
4240
4341 u_int64_t kore_websocket_timeout = 120000;
4442 u_int64_t kore_websocket_maxframe = 16384;
4644 static int websocket_recv_frame(struct netbuf *);
4745 static int websocket_recv_opcode(struct netbuf *);
4846 static void websocket_disconnect(struct connection *);
49 static void websocket_send_single(struct connection *, void *);
50 void websocket_send(struct connection *, u_int8_t, void *, size_t);
47 static void websocket_frame_build(struct kore_buf *, u_int8_t,
48 const void *, size_t);
5149
5250 void
5351 kore_websocket_handshake(struct http_request *req, struct kore_wscbs *wscbs)
6361 }
6462
6563 if (!http_request_header(req, "sec-websocket-version", &version)) {
66 kore_mem_free(key);
6764 http_response_header(req, "sec-websocket-version", "13");
6865 http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
6966 return;
7067 }
7168
7269 if (strcmp(version, "13")) {
73 kore_mem_free(key);
74 kore_mem_free(version);
7570 http_response_header(req, "sec-websocket-version", "13");
7671 http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
7772 return;
7873 }
7974
80 kore_mem_free(version);
81
82 buf = kore_buf_create(128);
75 buf = kore_buf_alloc(128);
8376 kore_buf_appendf(buf, "%s%s", key, WEBSOCKET_SERVER_RESPONSE);
84 kore_mem_free(key);
8577
8678 (void)SHA1_Init(&sctx);
8779 (void)SHA1_Update(&sctx, buf->data, buf->offset);
9890 http_response_header(req, "upgrade", "websocket");
9991 http_response_header(req, "connection", "upgrade");
10092 http_response_header(req, "sec-websocket-accept", base64);
101 kore_mem_free(base64);
93 kore_free(base64);
10294
10395 kore_debug("%p: new websocket connection", req->owner);
10496
97 req->owner->proto = CONN_PROTO_WEBSOCKET;
10598 http_response(req, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL, 0);
10699 net_recv_reset(req->owner, WEBSOCKET_FRAME_HDR, websocket_recv_opcode);
107100
108101 req->owner->disconnect = websocket_disconnect;
109102 req->owner->rnb->flags &= ~NETBUF_CALL_CB_ALWAYS;
110 req->owner->proto = CONN_PROTO_WEBSOCKET;
111103
112104 req->owner->wscbs = wscbs;
113105 req->owner->idle_timer.start = kore_time_ms();
118110 }
119111
120112 void
121 kore_websocket_send(struct connection *c, u_int8_t op, void *data, size_t len)
113 kore_websocket_send(struct connection *c, u_int8_t op, const void *data,
114 size_t len)
115 {
116 struct kore_buf *frame;
117
118 frame = kore_buf_alloc(len);
119 websocket_frame_build(frame, op, data, len);
120 net_send_queue(c, frame->data, frame->offset);
121 kore_buf_free(frame);
122 }
123
124 void
125 kore_websocket_broadcast(struct connection *src, u_int8_t op, const void *data,
126 size_t len, int scope)
127 {
128 struct connection *c;
129 struct kore_buf *frame;
130
131 frame = kore_buf_alloc(len);
132 websocket_frame_build(frame, op, data, len);
133
134 TAILQ_FOREACH(c, &connections, list) {
135 if (c != src && c->proto == CONN_PROTO_WEBSOCKET) {
136 net_send_queue(c, frame->data, frame->offset);
137 net_send_flush(c);
138 }
139 }
140
141 if (scope == WEBSOCKET_BROADCAST_GLOBAL) {
142 kore_msg_send(KORE_MSG_WORKER_ALL,
143 KORE_MSG_WEBSOCKET, frame->data, frame->offset);
144 }
145
146 kore_buf_free(frame);
147 }
148
149 static void
150 websocket_frame_build(struct kore_buf *frame, u_int8_t op, const void *data,
151 size_t len)
122152 {
123153 u_int8_t len_1;
124154 u_int16_t len16;
125155 u_int64_t len64;
126 struct kore_buf *frame;
127
128 if (c->proto != CONN_PROTO_WEBSOCKET)
129 fatal("kore_websocket_send(): to non websocket connection");
130
131 kore_debug("%p: sending %ld bytes", c, len);
132156
133157 if (len > WEBSOCKET_PAYLOAD_SINGLE) {
134158 if (len < USHRT_MAX)
139163 len_1 = len;
140164 }
141165
142 frame = kore_buf_create(len);
143
144166 op |= (1 << 7);
145167 kore_buf_append(frame, &op, sizeof(op));
146168
147169 len_1 &= ~(1 << 7);
148170 kore_buf_append(frame, &len_1, sizeof(len_1));
149171
150 if (len_1 != len) {
172 if (len_1 > WEBSOCKET_PAYLOAD_SINGLE) {
151173 switch (len_1) {
152174 case WEBSOCKET_PAYLOAD_EXTEND_1:
153175 net_write16((u_int8_t *)&len16, len);
161183 }
162184
163185 kore_buf_append(frame, data, len);
164 net_send_queue(c, frame->data, frame->offset, NULL, NETBUF_LAST_CHAIN);
165 kore_buf_free(frame);
166 }
167
168 void
169 kore_websocket_broadcast(struct connection *c, u_int8_t op, void *data,
170 size_t len, int scope)
171 {
172 struct websocket_data arg;
173
174 arg.op = op;
175 arg.len = len;
176 arg.data = data;
177 kore_worker_websocket_broadcast(c, websocket_send_single, &arg);
178
179 if (scope == WEBSOCKET_BROADCAST_GLOBAL)
180 fatal("kore_websocket_broadcast: no global scope yet");
181 }
182
183 static void
184 websocket_send_single(struct connection *c, void *args)
185 {
186 struct websocket_data *arg = args;
187
188 kore_websocket_send(c, arg->op, arg->data, arg->len);
189 net_send_flush(c);
190186 }
191187
192188 static int
00 /*
1 * Copyright (c) 2013-2015 Joris Vink <joris@coders.se>
1 * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
22 *
33 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
1313 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414 */
1515
16 #include <sys/types.h>
16 #include <sys/param.h>
1717 #include <sys/shm.h>
1818 #include <sys/wait.h>
1919 #include <sys/time.h>
2020 #include <sys/resource.h>
21 #include <sys/socket.h>
2122
2223 #include <fcntl.h>
2324 #include <grp.h>
2526 #include <signal.h>
2627
2728 #include "kore.h"
29
30 #if !defined(KORE_NO_HTTP)
2831 #include "http.h"
32 #endif
2933
3034 #if defined(KORE_USE_PGSQL)
3135 #include "pgsql.h"
4145 #define worker_debug(fmt, ...)
4246 #endif
4347
48 #if !defined(WAIT_ANY)
49 #define WAIT_ANY (-1)
50 #endif
51
4452 #define KORE_SHM_KEY 15000
4553 #define WORKER_LOCK_TIMEOUT 500
4654
5967 static inline int kore_worker_acceptlock_obtain(void);
6068 static inline void kore_worker_acceptlock_release(void);
6169
62 static struct connection_list disconnected;
6370 static struct kore_worker *kore_workers;
6471 static int shm_accept_key;
6572 static struct wlock *accept_lock;
6673
6774 extern volatile sig_atomic_t sig_recv;
6875 struct kore_worker *worker = NULL;
69 struct connection_list worker_clients;
7076 u_int8_t worker_set_affinity = 1;
7177 u_int32_t worker_accept_threshold = 0;
7278 u_int32_t worker_rlimit_nofiles = 1024;
8288 if (worker_count == 0)
8389 worker_count = 1;
8490
91 #if !defined(KORE_NO_TLS)
92 /* account for the key manager. */
93 worker_count += 1;
94 #endif
95
8596 len = sizeof(*accept_lock) +
8697 (sizeof(struct kore_worker) * worker_count);
8798
102113 kore_debug("kore_worker_init(): starting %d workers", worker_count);
103114
104115 if (worker_count > cpu_count) {
105 kore_debug("kore_worker_init(): more workers then cpu's");
116 kore_debug("kore_worker_init(): more workers than cpu's");
106117 }
107118
108119 cpu = 0;
124135 kw->has_lock = 0;
125136 kw->active_hdlr = NULL;
126137
138 if (socketpair(AF_UNIX, SOCK_STREAM, 0, kw->pipe) == -1)
139 fatal("socketpair(): %s", errno_s);
140
141 if (!kore_connection_nonblock(kw->pipe[0], 0) ||
142 !kore_connection_nonblock(kw->pipe[1], 0))
143 fatal("could not set pipe fds to nonblocking: %s", errno_s);
144
127145 kw->pid = fork();
128146 if (kw->pid == -1)
129147 fatal("could not spawn worker child: %s", errno_s);
133151 kore_worker_entry(kw);
134152 /* NOTREACHED */
135153 }
154 }
155
156 struct kore_worker *
157 kore_worker_data(u_int8_t id)
158 {
159 if (id >= worker_count)
160 fatal("id %u too large for worker count", id);
161
162 return (WORKER(id));
136163 }
137164
138165 void
177204 }
178205
179206 void
180 kore_worker_entry(struct kore_worker *kw)
181 {
182 size_t fd;
207 kore_worker_privdrop(void)
208 {
209 rlim_t fd;
183210 struct rlimit rl;
184 char buf[16];
185 struct connection *c, *cnext;
186 int quit, had_lock, r;
187 u_int64_t now, idle_check, next_lock, netwait;
188211 struct passwd *pw = NULL;
189
190 worker = kw;
191212
192213 /* Must happen before chroot. */
193214 if (skip_runas == 0) {
227248
228249 if (skip_runas == 0) {
229250 if (setgroups(1, &pw->pw_gid) ||
230 #ifdef __MACH__
251 #if defined(__MACH__) || defined(NetBSD)
231252 setgid(pw->pw_gid) || setegid(pw->pw_gid) ||
232253 setuid(pw->pw_uid) || seteuid(pw->pw_uid))
233254 #else
236257 #endif
237258 fatal("cannot drop privileges");
238259 }
260 }
261
262 void
263 kore_worker_entry(struct kore_worker *kw)
264 {
265 char buf[16];
266 int quit, had_lock, r;
267 u_int64_t now, idle_check, next_lock, netwait;
268 #if defined(KORE_SINGLE_BINARY)
269 void (*onload)(void);
270 #endif
271
272 worker = kw;
239273
240274 (void)snprintf(buf, sizeof(buf), "kore [wrk %d]", kw->id);
275 #if !defined(KORE_NO_TLS)
276 if (kw->id == KORE_WORKER_KEYMGR)
277 (void)snprintf(buf, sizeof(buf), "kore [keymgr]");
278 #endif
241279 kore_platform_proctitle(buf);
242280
243281 if (worker_set_affinity == 1)
248286 sig_recv = 0;
249287 signal(SIGHUP, kore_signal);
250288 signal(SIGQUIT, kore_signal);
289 signal(SIGTERM, kore_signal);
251290 signal(SIGPIPE, SIG_IGN);
252291
253292 if (foreground)
255294 else
256295 signal(SIGINT, SIG_IGN);
257296
297 #if !defined(KORE_NO_TLS)
298 if (kw->id == KORE_WORKER_KEYMGR) {
299 kore_keymgr_run();
300 exit(0);
301 }
302 #endif
303
304 kore_worker_privdrop();
305
258306 net_init();
307 #if !defined(KORE_NO_HTTP)
259308 http_init();
309 kore_accesslog_worker_init();
310 #endif
260311 kore_timer_init();
261312 kore_connection_init();
262313 kore_domain_load_crl();
263 TAILQ_INIT(&disconnected);
264 TAILQ_INIT(&worker_clients);
314 kore_domain_keymgr_init();
265315
266316 quit = 0;
267317 had_lock = 0;
268318 next_lock = 0;
269319 idle_check = 0;
270320 kore_platform_event_init();
271 kore_accesslog_worker_init();
321 kore_msg_worker_init();
272322
273323 #if defined(KORE_USE_PGSQL)
274324 kore_pgsql_init();
279329 #endif
280330
281331 kore_log(LOG_NOTICE, "worker %d started (cpu#%d)", kw->id, kw->cpu);
332
333 #if defined(KORE_SINGLE_BINARY)
334 *(void **)&(onload) = kore_module_getsym("kore_onload");
335 if (onload != NULL)
336 onload();
337 #else
282338 kore_module_onload();
339 #endif
283340
284341 for (;;) {
285342 if (sig_recv != 0) {
286 if (sig_recv == SIGHUP)
343 switch (sig_recv) {
344 case SIGHUP:
345 #if !defined(KORE_SINGLE_BINARY)
287346 kore_module_reload(1);
288 else if (sig_recv == SIGQUIT || sig_recv == SIGINT)
347 #endif
348 break;
349 case SIGQUIT:
350 case SIGINT:
351 case SIGTERM:
289352 quit = 1;
353 break;
354 default:
355 break;
356 }
290357
291358 sig_recv = 0;
292359 }
316383 next_lock = now + WORKER_LOCK_TIMEOUT;
317384 }
318385
386 #if !defined(KORE_NO_HTTP)
319387 http_process();
388 #endif
320389
321390 if ((now - idle_check) >= 10000) {
322391 idle_check = now;
323 now = kore_time_ms();
324 TAILQ_FOREACH(c, &worker_clients, list) {
325 if (c->proto == CONN_PROTO_SPDY &&
326 c->idle_timer.length == 0 &&
327 !(c->flags & CONN_WRITE_BLOCK) &&
328 !(c->flags & CONN_READ_BLOCK))
329 continue;
330 if (!(c->flags & CONN_IDLE_TIMER_ACT))
331 continue;
332 kore_connection_check_idletimer(now, c);
333 }
334 }
335
336 for (c = TAILQ_FIRST(&disconnected); c != NULL; c = cnext) {
337 cnext = TAILQ_NEXT(c, list);
338 TAILQ_REMOVE(&disconnected, c, list);
339 kore_connection_remove(c);
340 }
341
342 if (quit && http_request_count == 0)
392 kore_connection_check_timeout();
393 }
394
395 kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
396
397 if (quit)
343398 break;
344399 }
345400
346 for (c = TAILQ_FIRST(&worker_clients); c != NULL; c = cnext) {
347 cnext = TAILQ_NEXT(c, list);
348 net_send_flush(c);
349 kore_connection_disconnect(c);
350 }
351
352 for (c = TAILQ_FIRST(&disconnected); c != NULL; c = cnext) {
353 cnext = TAILQ_NEXT(c, list);
354 net_send_flush(c);
355 TAILQ_REMOVE(&disconnected, c, list);
356 kore_connection_remove(c);
357 }
401 kore_platform_event_cleanup();
402 kore_connection_cleanup();
403 kore_domain_cleanup();
404 kore_module_cleanup();
405 #if !defined(KORE_NO_HTTP)
406 http_cleanup();
407 #endif
408 net_cleanup();
358409
359410 kore_debug("worker %d shutting down", kw->id);
360411 exit(0);
361 }
362
363 void
364 kore_worker_connection_add(struct connection *c)
365 {
366 TAILQ_INSERT_TAIL(&worker_clients, c, list);
367 worker_active_connections++;
368 }
369
370 void
371 kore_worker_connection_move(struct connection *c)
372 {
373 TAILQ_REMOVE(&worker_clients, c, list);
374 TAILQ_INSERT_TAIL(&disconnected, c, list);
375 }
376
377 void
378 kore_worker_connection_remove(struct connection *c)
379 {
380 worker_active_connections--;
381 }
382
383 void
384 kore_worker_websocket_broadcast(struct connection *src,
385 void (*cb)(struct connection *, void *), void *args)
386 {
387 struct connection *c;
388
389 TAILQ_FOREACH(c, &worker_clients, list) {
390 if (c != src && c->proto == CONN_PROTO_WEBSOCKET)
391 cb(c, args);
392 }
393412 }
394413
395414 void
434453 (kw->active_hdlr != NULL) ? kw->active_hdlr->func :
435454 "none");
436455
456 #if !defined(KORE_NO_TLS)
457 if (id == KORE_WORKER_KEYMGR) {
458 kore_log(LOG_CRIT, "keymgr gone, stopping");
459 kw->pid = 0;
460 if (raise(SIGTERM) != 0) {
461 kore_log(LOG_WARNING,
462 "failed to raise SIGTERM signal");
463 }
464 break;
465 }
466 #endif
467
437468 if (kw->pid == accept_lock->current)
438469 worker_unlock();
439470
446477 }
447478
448479 kore_log(LOG_NOTICE, "restarting worker %d", kw->id);
480 kore_msg_parent_remove(kw);
449481 kore_worker_spawn(kw->id, kw->cpu);
482 kore_msg_parent_add(kw);
450483 } else {
451484 kore_log(LOG_NOTICE,
452485 "worker %d (pid: %d) signaled us (%d)",
+0
-196
src/zlib_dict.c less more
0 /*
1 * Copyright (c) 2013 Joris Vink <joris@coders.se>
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16 const unsigned char SPDY_dictionary_txt[] = {
17 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // - - - - o p t i
18 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // o n s - - - - h
19 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // e a d - - - - p
20 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // o s t - - - - p
21 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // u t - - - - d e
22 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // l e t e - - - -
23 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // t r a c e - - -
24 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // - a c c e p t -
25 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p
26 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t - c h a r s e
27 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t - - - - a c c
28 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e p t - e n c o
29 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // d i n g - - - -
30 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // a c c e p t - l
31 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // a n g u a g e -
32 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // - - - a c c e p
33 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t - r a n g e s
34 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // - - - - a g e -
35 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // - - - a l l o w
36 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // - - - - a u t h
37 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // o r i z a t i o
38 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n - - - - c a c
39 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // h e - c o n t r
40 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // o l - - - - c o
41 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // n n e c t i o n
42 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t
43 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // e n t - b a s e
44 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t
45 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // e n t - e n c o
46 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // d i n g - - - -
47 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // c o n t e n t -
48 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // l a n g u a g e
49 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // - - - - c o n t
50 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // e n t - l e n g
51 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // t h - - - - c o
52 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // n t e n t - l o
53 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // c a t i o n - -
54 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n
55 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t - m d 5 - - -
56 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // - c o n t e n t
57 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // - r a n g e - -
58 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // - - c o n t e n
59 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t - t y p e - -
60 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // - - d a t e - -
61 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // - - e t a g - -
62 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // - - e x p e c t
63 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // - - - - e x p i
64 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // r e s - - - - f
65 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // r o m - - - - h
66 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // o s t - - - - i
67 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f - m a t c h -
68 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // - - - i f - m o
69 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // d i f i e d - s
70 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // i n c e - - - -
71 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // i f - n o n e -
72 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // m a t c h - - -
73 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // - i f - r a n g
74 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e - - - - i f -
75 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // u n m o d i f i
76 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // e d - s i n c e
77 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // - - - - l a s t
78 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // - m o d i f i e
79 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d - - - - l o c
80 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // a t i o n - - -
81 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // - m a x - f o r
82 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // w a r d s - - -
83 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // - p r a g m a -
84 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // - - - p r o x y
85 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // - a u t h e n t
86 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // i c a t e - - -
87 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // - p r o x y - a
88 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // u t h o r i z a
89 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // t i o n - - - -
90 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // r a n g e - - -
91 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // - r e f e r e r
92 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // - - - - r e t r
93 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y - a f t e r -
94 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // - - - s e r v e
95 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r - - - - t e -
96 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // - - - t r a i l
97 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // e r - - - - t r
98 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // a n s f e r - e
99 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // n c o d i n g -
100 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // - - - u p g r a
101 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // d e - - - - u s
102 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // e r - a g e n t
103 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // - - - - v a r y
104 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // - - - - v i a -
105 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // - - - w a r n i
106 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // n g - - - - w w
107 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w - a u t h e n
108 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // t i c a t e - -
109 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // - - m e t h o d
110 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // - - - - g e t -
111 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // - - - s t a t u
112 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s - - - - 2 0 0
113 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // - O K - - - - v
114 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // e r s i o n - -
115 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // - - H T T P - 1
116 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // - 1 - - - - u r
117 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l - - - - p u b
118 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // l i c - - - - s
119 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // e t - c o o k i
120 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e - - - - k e e
121 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p - a l i v e -
122 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // - - - o r i g i
123 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n 1 0 0 1 0 1 2
124 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 0 1 2 0 2 2 0 5
125 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 2 0 6 3 0 0 3 0
126 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 2 3 0 3 3 0 4 3
127 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 0 5 3 0 6 3 0 7
128 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 4 0 2 4 0 5 4 0
129 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 6 4 0 7 4 0 8 4
130 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 0 9 4 1 0 4 1 1
131 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 4 1 2 4 1 3 4 1
132 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 4 4 1 5 4 1 6 4
133 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 1 7 5 0 2 5 0 4
134 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 5 0 5 2 0 3 - N
135 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // o n - A u t h o
136 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // r i t a t i v e
137 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // - I n f o r m a
138 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // t i o n 2 0 4 -
139 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // N o - C o n t e
140 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // n t 3 0 1 - M o
141 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // v e d - P e r m
142 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // a n e n t l y 4
143 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 0 0 - B a d - R
144 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // e q u e s t 4 0
145 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1 - U n a u t h
146 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // o r i z e d 4 0
147 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3 - F o r b i d
148 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // d e n 4 0 4 - N
149 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // o t - F o u n d
150 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 5 0 0 - I n t e
151 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // r n a l - S e r
152 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // v e r - E r r o
153 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r 5 0 1 - N o t
154 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // - I m p l e m e
155 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // n t e d 5 0 3 -
156 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // S e r v i c e -
157 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // U n a v a i l a
158 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // b l e J a n - F
159 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // e b - M a r - A
160 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // p r - M a y - J
161 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // u n - J u l - A
162 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // u g - S e p t -
163 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // O c t - N o v -
164 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // D e c - 0 0 - 0
165 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0 - 0 0 - M o n
166 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // - - T u e - - W
167 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // e d - - T h u -
168 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // - F r i - - S a
169 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t - - S u n - -
170 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // G M T c h u n k
171 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // e d - t e x t -
172 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // h t m l - i m a
173 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // g e - p n g - i
174 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // m a g e - j p g
175 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // - i m a g e - g
176 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // i f - a p p l i
177 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x
178 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // m l - a p p l i
179 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // c a t i o n - x
180 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // h t m l - x m l
181 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // - t e x t - p l
182 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // a i n - t e x t
183 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // - j a v a s c r
184 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // i p t - p u b l
185 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // i c p r i v a t
186 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // e m a x - a g e
187 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // - g z i p - d e
188 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // f l a t e - s d
189 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // c h c h a r s e
190 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t - u t f - 8 c
191 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // h a r s e t - i
192 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // s o - 8 8 5 9 -
193 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1 - u t f - - -
194 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // - e n q - 0 -
195 };