kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit e6833a4892f048c147bccf4928f2ef11578dccb0
parent 548068d2a050cf3f0a9c7674657beda7b9d03930
Author: Joris Vink <joris@coders.se>
Date:   Fri, 30 Mar 2018 13:45:29 +0200

Move header files to include/kore.

Mimics how the header files are installed on a system
as PREFIX/include/kore.

This is required for getting kodev to use the headers from the
kore_source option instead of requiring the kore headers to be
installed on the system even when building as a single_binary.

Diffstat:
Makefile | 2+-
include/kore/http.h | 347+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/kore/jsonrpc.h | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/kore/kore.h | 716+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/kore/pgsql.h | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/kore/python_api.h | 35+++++++++++++++++++++++++++++++++++
include/kore/python_methods.h | 229+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/kore/tasks.h | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
includes/http.h | 347-------------------------------------------------------------------------------
includes/jsonrpc.h | 87-------------------------------------------------------------------------------
includes/kore.h | 716-------------------------------------------------------------------------------
includes/pgsql.h | 103-------------------------------------------------------------------------------
includes/python_api.h | 35-----------------------------------
includes/python_methods.h | 229-------------------------------------------------------------------------------
includes/tasks.h | 98-------------------------------------------------------------------------------
15 files changed, 1616 insertions(+), 1616 deletions(-)

diff --git a/Makefile b/Makefile @@ -19,7 +19,7 @@ FEATURES_INC= CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual -CFLAGS+=-Wsign-compare -Iincludes -std=c99 -pedantic +CFLAGS+=-Wsign-compare -Iinclude/kore -std=c99 -pedantic CFLAGS+=-DPREFIX='"$(PREFIX)"' -fstack-protector-all LDFLAGS=-rdynamic -lssl -lcrypto diff --git a/include/kore/http.h b/include/kore/http.h @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2013 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if !defined(KORE_NO_HTTP) + +#ifndef __H_HTTP_H +#define __H_HTTP_H + +#include <sys/types.h> +#include <sys/queue.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Keep the http_populate_get symbol around. */ +#define http_populate_get http_populate_qs + +#define HTTP_KEEPALIVE_TIME 20 +#define HTTP_HSTS_ENABLE 31536000 +#define HTTP_HEADER_MAX_LEN 4096 +#define HTTP_BODY_MAX_LEN 1024000 +#define HTTP_URI_LEN 2000 +#define HTTP_USERAGENT_LEN 256 +#define HTTP_REQ_HEADER_MAX 25 +#define HTTP_MAX_QUERY_ARGS 20 +#define HTTP_MAX_COOKIES 10 +#define HTTP_MAX_COOKIENAME 255 +#define HTTP_HEADER_BUFSIZE 1024 +#define HTTP_COOKIE_BUFSIZE 1024 +#define HTTP_DATE_MAXSIZE 255 +#define HTTP_REQUEST_LIMIT 1000 +#define HTTP_REQUEST_MS 10 +#define HTTP_BODY_DISK_PATH "tmp_files" +#define HTTP_BODY_DISK_OFFLOAD 0 +#define HTTP_BODY_PATH_MAX 256 +#define HTTP_BOUNDARY_MAX 80 + +#define HTTP_ARG_TYPE_RAW 0 +#define HTTP_ARG_TYPE_BYTE 1 +#define HTTP_ARG_TYPE_INT16 2 +#define HTTP_ARG_TYPE_UINT16 3 +#define HTTP_ARG_TYPE_INT32 4 +#define HTTP_ARG_TYPE_UINT32 5 +#define HTTP_ARG_TYPE_STRING 6 +#define HTTP_ARG_TYPE_INT64 7 +#define HTTP_ARG_TYPE_UINT64 8 + +#define HTTP_STATE_ERROR 0 +#define HTTP_STATE_CONTINUE 1 +#define HTTP_STATE_COMPLETE 2 +#define HTTP_STATE_RETRY 3 + +struct http_header { + char *header; + char *value; + + TAILQ_ENTRY(http_header) list; +}; + +#define HTTP_COOKIE_HTTPONLY 0x0001 +#define HTTP_COOKIE_SECURE 0x0002 + +struct http_cookie { + char *name; + char *value; + char *path; + char *domain; + u_int32_t maxage; + time_t expires; + u_int16_t flags; + + TAILQ_ENTRY(http_cookie) list; +}; + +struct http_arg { + char *name; + char *s_value; + + TAILQ_ENTRY(http_arg) list; +}; + +#define COPY_ARG_TYPE(v, t) \ + do { \ + *(t *)nout = v; \ + } while (0) + +#define COPY_ARG_INT64(type, sign) \ + do { \ + int err; \ + type nval; \ + nval = (type)kore_strtonum64(q->s_value, sign, &err); \ + if (err != KORE_RESULT_OK) \ + return (KORE_RESULT_ERROR); \ + COPY_ARG_TYPE(nval, type); \ + } while (0) + +#define COPY_ARG_INT(min, max, type) \ + do { \ + int err; \ + int64_t nval; \ + nval = kore_strtonum(q->s_value, 10, min, max, &err); \ + if (err != KORE_RESULT_OK) \ + return (KORE_RESULT_ERROR); \ + COPY_ARG_TYPE(nval, type); \ + } while (0) + +#define COPY_AS_INTTYPE_64(type, sign) \ + do { \ + if (nout == NULL) \ + return (KORE_RESULT_ERROR); \ + COPY_ARG_INT64(type, sign); \ + } while (0) + +#define COPY_AS_INTTYPE(min, max, type) \ + do { \ + if (nout == NULL) \ + return (KORE_RESULT_ERROR); \ + COPY_ARG_INT(min, max, type); \ + } while (0) + +#define http_argument_type(r, n, so, no, t) \ + http_argument_get(r, n, so, no, t) + +#define http_argument_get_string(r, n, o) \ + http_argument_type(r, n, (void **)o, NULL, HTTP_ARG_TYPE_STRING) + +#define http_argument_get_byte(r, n, o) \ + http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_BYTE) + +#define http_argument_get_uint16(r, n, o) \ + http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT16) + +#define http_argument_get_int16(r, n, o) \ + http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT16) + +#define http_argument_get_uint32(r, n, o) \ + http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT32) + +#define http_argument_get_int32(r, n, o) \ + http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT32) + +#define http_argument_get_uint64(r, n, o) \ + http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT64) + +#define http_argument_get_int64(r, n, o) \ + http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT64) + + +struct http_file { + char *name; + char *filename; + size_t position; + size_t offset; + size_t length; + struct http_request *req; + TAILQ_ENTRY(http_file) list; +}; + +#define HTTP_METHOD_GET 0 +#define HTTP_METHOD_POST 1 +#define HTTP_METHOD_PUT 2 +#define HTTP_METHOD_DELETE 3 +#define HTTP_METHOD_HEAD 4 +#define HTTP_METHOD_OPTIONS 5 +#define HTTP_METHOD_PATCH 6 + +#define HTTP_REQUEST_COMPLETE 0x0001 +#define HTTP_REQUEST_DELETE 0x0002 +#define HTTP_REQUEST_SLEEPING 0x0004 +#define HTTP_REQUEST_EXPECT_BODY 0x0020 +#define HTTP_REQUEST_RETAIN_EXTRA 0x0040 +#define HTTP_REQUEST_NO_CONTENT_LENGTH 0x0080 +#define HTTP_REQUEST_AUTHED 0x0100 + +#define HTTP_VALIDATOR_IS_REQUEST 0x8000 + +struct kore_task; + +struct http_request { + u_int8_t method; + u_int8_t fsm_state; + u_int16_t flags; + u_int16_t status; + u_int64_t ms; + u_int64_t start; + u_int64_t end; + u_int64_t total; + const char *path; + const char *host; + const char *agent; + struct connection *owner; + u_int8_t *headers; + struct kore_buf *http_body; + int http_body_fd; + char *http_body_path; + size_t http_body_length; + size_t http_body_offset; + size_t content_length; + void *hdlr_extra; + size_t state_len; + char *query_string; + struct kore_module_handle *hdlr; + +#if defined(KORE_USE_PYTHON) + void *py_coro; +#endif + + LIST_HEAD(, kore_task) tasks; + LIST_HEAD(, kore_pgsql) pgsqls; + + TAILQ_HEAD(, http_cookie) req_cookies; + TAILQ_HEAD(, http_cookie) resp_cookies; + TAILQ_HEAD(, http_header) req_headers; + TAILQ_HEAD(, http_header) resp_headers; + TAILQ_HEAD(, http_arg) arguments; + TAILQ_HEAD(, http_file) files; + TAILQ_ENTRY(http_request) list; + TAILQ_ENTRY(http_request) olist; +}; + +struct http_state { + const char *name; + int (*cb)(struct http_request *); +}; + +extern size_t http_body_max; +extern u_int16_t http_header_max; +extern u_int32_t http_request_ms; +extern u_int64_t http_hsts_enable; +extern u_int16_t http_keepalive_time; +extern u_int32_t http_request_limit; +extern u_int32_t http_request_count; +extern u_int64_t http_body_disk_offload; +extern char *http_body_disk_path; + +void kore_accesslog(struct http_request *); + +void http_init(void); +void http_cleanup(void); +void http_server_version(const char *); +void http_process(void); +const char *http_status_text(int); +const char *http_method_text(int); +time_t http_date_to_time(char *); +void http_request_free(struct http_request *); +void http_request_sleep(struct http_request *); +void http_request_wakeup(struct http_request *); +void http_process_request(struct http_request *); +int http_body_rewind(struct http_request *); +ssize_t http_body_read(struct http_request *, void *, size_t); +void http_response(struct http_request *, int, const void *, size_t); +void http_serveable(struct http_request *, const void *, + size_t, const char *, const char *); +void http_response_stream(struct http_request *, int, void *, + size_t, int (*cb)(struct netbuf *), void *); +int http_request_header(struct http_request *, + const char *, const char **); +void http_response_header(struct http_request *, + const char *, const char *); +int http_state_run(struct http_state *, u_int8_t, + struct http_request *); +int http_request_cookie(struct http_request *, + const char *, char **); +void http_response_cookie(struct http_request *, const char *, + const char *, const char *, time_t, u_int32_t, + struct http_cookie **); + +void *http_state_get(struct http_request *); +int http_state_exists(struct http_request *); +void http_state_cleanup(struct http_request *); +void *http_state_create(struct http_request *, size_t); + +int http_argument_urldecode(char *); +int http_header_recv(struct netbuf *); +void http_populate_qs(struct http_request *); +void http_populate_post(struct http_request *); +void http_populate_multipart_form(struct http_request *); +void http_populate_cookies(struct http_request *); +int http_argument_get(struct http_request *, + const char *, void **, void *, int); + +void http_file_rewind(struct http_file *); +ssize_t http_file_read(struct http_file *, void *, size_t); +struct http_file *http_file_lookup(struct http_request *, const char *); + +enum http_status_code { + HTTP_STATUS_CONTINUE = 100, + HTTP_STATUS_SWITCHING_PROTOCOLS = 101, + HTTP_STATUS_OK = 200, + HTTP_STATUS_CREATED = 201, + HTTP_STATUS_ACCEPTED = 202, + HTTP_STATUS_NON_AUTHORITATIVE = 203, + HTTP_STATUS_NO_CONTENT = 204, + HTTP_STATUS_RESET_CONTENT = 205, + HTTP_STATUS_PARTIAL_CONTENT = 206, + HTTP_STATUS_MULTIPLE_CHOICES = 300, + HTTP_STATUS_MOVED_PERMANENTLY = 301, + HTTP_STATUS_FOUND = 302, + HTTP_STATUS_SEE_OTHER = 303, + HTTP_STATUS_NOT_MODIFIED = 304, + HTTP_STATUS_USE_PROXY = 305, + HTTP_STATUS_TEMPORARY_REDIRECT = 307, + HTTP_STATUS_BAD_REQUEST = 400, + HTTP_STATUS_UNAUTHORIZED = 401, + HTTP_STATUS_PAYMENT_REQUIRED = 402, + HTTP_STATUS_FORBIDDEN = 403, + HTTP_STATUS_NOT_FOUND = 404, + HTTP_STATUS_METHOD_NOT_ALLOWED = 405, + HTTP_STATUS_NOT_ACCEPTABLE = 406, + HTTP_STATUS_PROXY_AUTH_REQUIRED = 407, + HTTP_STATUS_REQUEST_TIMEOUT = 408, + HTTP_STATUS_CONFLICT = 409, + HTTP_STATUS_GONE = 410, + HTTP_STATUS_LENGTH_REQUIRED = 411, + HTTP_STATUS_PRECONDITION_FAILED = 412, + HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413, + HTTP_STATUS_REQUEST_URI_TOO_LARGE = 414, + HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, + HTTP_STATUS_REQUEST_RANGE_INVALID = 416, + HTTP_STATUS_EXPECTATION_FAILED = 417, + HTTP_STATUS_INTERNAL_ERROR = 500, + HTTP_STATUS_NOT_IMPLEMENTED = 501, + HTTP_STATUS_BAD_GATEWAY = 502, + HTTP_STATUS_SERVICE_UNAVAILABLE = 503, + HTTP_STATUS_GATEWAY_TIMEOUT = 504, + HTTP_STATUS_BAD_VERSION = 505 +}; +#if defined(__cplusplus) +} +#endif +#endif /* !__H_HTTP_H */ + +#endif /* ! KORE_NO_HTTP */ diff --git a/include/kore/jsonrpc.h b/include/kore/jsonrpc.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 Raphaël Monrouzeau <raphael.monrouzeau@gmail.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if !defined(KORE_NO_HTTP) + +#ifndef __H_JSONRPC_H +#define __H_JSONRPC_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* JSON RPC request handling log entry. */ +struct jsonrpc_log +{ + char *msg; + struct jsonrpc_log *next, *prev; + int lvl; +}; + +/* JSON RPC request. */ +struct jsonrpc_request +{ + struct jsonrpc_log log; + struct kore_buf buf; + struct http_request *http; + yajl_gen gen; + yajl_val json; + yajl_val id; + char *method; + yajl_val params; + unsigned int flags; + int log_levels; +}; + +#define YAJL_GEN_CONST_STRING(CTX, STR) \ + yajl_gen_string((CTX), (unsigned char *)(STR), sizeof (STR) - 1) + +#define YAJL_GEN_CONST_NUMBER(CTX, STR) \ + yajl_gen_number((CTX), (unsigned char *)(STR), sizeof (STR) - 1) + +#define YAJL_GEN_KO(OPERATION) \ + ((OPERATION) != yajl_gen_status_ok) + +enum jsonrpc_error_code +{ +#define JSONRPC_PARSE_ERROR_MSG "Parse error" + JSONRPC_PARSE_ERROR = -32700, +#define JSONRPC_INVALID_REQUEST_MSG "Invalid Request" + JSONRPC_INVALID_REQUEST = -32600, +#define JSONRPC_METHOD_NOT_FOUND_MSG "Method not found" + JSONRPC_METHOD_NOT_FOUND = -32601, +#define JSONRPC_INVALID_PARAMS_MSG "Invalid params" + JSONRPC_INVALID_PARAMS = -32602, +#define JSONRPC_INTERNAL_ERROR_MSG "Internal error" + JSONRPC_INTERNAL_ERROR = -32603, +#define JSONRPC_SERVER_ERROR_MSG "Server error" + JSONRPC_SERVER_ERROR = -32000, +#define JSONRPC_LIMIT_REACHED_MSG "Limit reached" + JSONRPC_LIMIT_REACHED = -31997 +}; + +void jsonrpc_log(struct jsonrpc_request *, int, const char *, ...); +int jsonrpc_read_request(struct http_request *, struct jsonrpc_request *); +void jsonrpc_destroy_request(struct jsonrpc_request *); +int jsonrpc_error(struct jsonrpc_request *, int, const char *); +int jsonrpc_result(struct jsonrpc_request *, + int (*)(struct jsonrpc_request *, void *), void *); +#if defined(__cplusplus) +} +#endif +#endif /* !__H_JSONRPC_H */ + +#endif /* ! KORE_NO_HTTP */ diff --git a/include/kore/kore.h b/include/kore/kore.h @@ -0,0 +1,716 @@ +/* + * Copyright (c) 2013-2018 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __H_KORE_H +#define __H_KORE_H + +#if defined(__APPLE__) +#define daemon portability_is_king +#endif + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/queue.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#if !defined(KORE_NO_TLS) +#include <openssl/err.h> +#include <openssl/dh.h> +#include <openssl/ssl.h> +#endif + +#include <errno.h> +#include <regex.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include <stdarg.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(__APPLE__) +#undef daemon +extern int daemon(int, int); +#endif + +#define KORE_RESULT_ERROR 0 +#define KORE_RESULT_OK 1 +#define KORE_RESULT_RETRY 2 + +#define KORE_VERSION_MAJOR 2 +#define KORE_VERSION_MINOR 1 +#define KORE_VERSION_PATCH 0 +#define KORE_VERSION_STATE "devel" + +#define KORE_TLS_VERSION_1_2 0 +#define KORE_TLS_VERSION_1_0 1 +#define KORE_TLS_VERSION_BOTH 2 + +#define KORE_RESEED_TIME (1800 * 1000) + +#define errno_s strerror(errno) +#define ssl_errno_s ERR_error_string(ERR_get_error(), NULL) + +#define KORE_DOMAINNAME_LEN 255 +#define KORE_PIDFILE_DEFAULT "kore.pid" +#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" + +#if defined(KORE_DEBUG) +#define kore_debug(...) \ + if (kore_debug) \ + kore_debug_internal(__FILE__, __LINE__, __VA_ARGS__) +#else +#define kore_debug(...) +#endif + +#define NETBUF_RECV 0 +#define NETBUF_SEND 1 +#define NETBUF_SEND_PAYLOAD_MAX 8192 + +#define NETBUF_LAST_CHAIN 0 +#define NETBUF_BEFORE_CHAIN 1 + +#define NETBUF_CALL_CB_ALWAYS 0x01 +#define NETBUF_FORCE_REMOVE 0x02 +#define NETBUF_MUST_RESEND 0x04 +#define NETBUF_IS_STREAM 0x10 + +#define X509_GET_CN(c, o, l) \ + X509_NAME_get_text_by_NID(X509_get_subject_name(c), \ + NID_commonName, o, l) + +#define X509_CN_LENGTH (ub_common_name + 1) + +/* XXX hackish. */ +#if !defined(KORE_NO_HTTP) +struct http_request; +#endif + +struct netbuf { + u_int8_t *buf; + size_t s_off; + size_t b_len; + size_t m_len; + u_int8_t type; + u_int8_t flags; + + void *owner; + + void *extra; + int (*cb)(struct netbuf *); + + TAILQ_ENTRY(netbuf) list; +}; + +TAILQ_HEAD(netbuf_head, netbuf); + +#define KORE_TYPE_LISTENER 1 +#define KORE_TYPE_CONNECTION 2 +#define KORE_TYPE_PGSQL_CONN 3 +#define KORE_TYPE_TASK 4 + +#define CONN_STATE_UNKNOWN 0 +#define CONN_STATE_TLS_SHAKE 1 +#define CONN_STATE_ESTABLISHED 2 +#define CONN_STATE_DISCONNECTING 3 + +#define CONN_PROTO_UNKNOWN 0 +#define CONN_PROTO_HTTP 1 +#define CONN_PROTO_WEBSOCKET 2 +#define CONN_PROTO_MSG 3 + +#define CONN_READ_POSSIBLE 0x01 +#define CONN_WRITE_POSSIBLE 0x02 +#define CONN_WRITE_BLOCK 0x04 +#define CONN_IDLE_TIMER_ACT 0x10 +#define CONN_READ_BLOCK 0x20 +#define CONN_CLOSE_EMPTY 0x40 +#define CONN_WS_CLOSE_SENT 0x80 + +#define KORE_IDLE_TIMER_MAX 5000 + +#define WEBSOCKET_OP_CONT 0x00 +#define WEBSOCKET_OP_TEXT 0x01 +#define WEBSOCKET_OP_BINARY 0x02 +#define WEBSOCKET_OP_CLOSE 0x08 +#define WEBSOCKET_OP_PING 0x09 +#define WEBSOCKET_OP_PONG 0x0a + +#define WEBSOCKET_BROADCAST_LOCAL 1 +#define WEBSOCKET_BROADCAST_GLOBAL 2 + +#define KORE_TIMER_ONESHOT 0x01 + +#define KORE_CONNECTION_PRUNE_DISCONNECT 0 +#define KORE_CONNECTION_PRUNE_ALL 1 + +struct connection { + u_int8_t type; + int fd; + u_int8_t state; + u_int8_t proto; + void *owner; +#if !defined(KORE_NO_TLS) + X509 *cert; + SSL *ssl; + int tls_reneg; +#endif + u_int8_t flags; + void *hdlr_extra; + + int (*handle)(struct connection *); + void (*disconnect)(struct connection *); + int (*read)(struct connection *, size_t *); + int (*write)(struct connection *, size_t, size_t *); + + u_int8_t addrtype; + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } addr; + + struct { + u_int64_t length; + u_int64_t start; + } idle_timer; + + struct netbuf_head send_queue; + struct netbuf *snb; + struct netbuf *rnb; + +#if !defined(KORE_NO_HTTP) + struct kore_runtime_call *ws_connect; + struct kore_runtime_call *ws_message; + struct kore_runtime_call *ws_disconnect; + TAILQ_HEAD(, http_request) http_requests; +#endif + + TAILQ_ENTRY(connection) list; +}; + +TAILQ_HEAD(connection_list, connection); +extern struct connection_list connections; +extern struct connection_list disconnected; + +#define KORE_RUNTIME_NATIVE 0 +#define KORE_RUNTIME_PYTHON 1 + +struct kore_runtime { + int type; +#if !defined(KORE_NO_HTTP) + int (*http_request)(void *, struct http_request *); + int (*validator)(void *, struct http_request *, const void *); + void (*wsconnect)(void *, struct connection *); + void (*wsdisconnect)(void *, struct connection *); + void (*wsmessage)(void *, struct connection *, + u_int8_t, const void *, size_t); +#endif + void (*execute)(void *); + int (*onload)(void *, int); + void (*connect)(void *, struct connection *); +}; + +struct kore_runtime_call { + void *addr; + struct kore_runtime *runtime; +}; + +extern struct kore_runtime kore_native_runtime; + +struct listener { + u_int8_t type; + u_int8_t addrtype; + int fd; + struct kore_runtime_call *connect; + + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } addr; + + LIST_ENTRY(listener) list; +}; + +LIST_HEAD(listener_head, listener); + +#if !defined(KORE_NO_HTTP) + +#define KORE_PARAMS_QUERY_STRING 0x0001 + +struct kore_handler_params { + char *name; + int flags; + u_int8_t method; + struct kore_validator *validator; + + TAILQ_ENTRY(kore_handler_params) list; +}; + +#define KORE_AUTH_TYPE_COOKIE 1 +#define KORE_AUTH_TYPE_HEADER 2 +#define KORE_AUTH_TYPE_REQUEST 3 + +struct kore_auth { + u_int8_t type; + char *name; + char *value; + char *redirect; + struct kore_validator *validator; + + TAILQ_ENTRY(kore_auth) list; +}; + +#define HANDLER_TYPE_STATIC 1 +#define HANDLER_TYPE_DYNAMIC 2 + +#endif /* !KORE_NO_HTTP */ + +#define KORE_MODULE_LOAD 1 +#define KORE_MODULE_UNLOAD 2 + +#define KORE_MODULE_NATIVE 0 +#define KORE_MODULE_PYTHON 1 + +struct kore_module; + +struct kore_module_functions { + void (*free)(struct kore_module *); + void (*reload)(struct kore_module *); + int (*callback)(struct kore_module *, int); + void (*load)(struct kore_module *); + void *(*getsym)(struct kore_module *, const char *); +}; + +struct kore_module { + void *handle; + char *path; + char *onload; + int type; + time_t mtime; + struct kore_runtime_call *ocb; + + struct kore_module_functions *fun; + struct kore_runtime *runtime; + + TAILQ_ENTRY(kore_module) list; +}; + +struct kore_module_handle { + char *path; + char *func; + int type; + int errors; + regex_t rctx; + struct kore_domain *dom; + struct kore_runtime_call *rcall; +#if !defined(KORE_NO_HTTP) + struct kore_auth *auth; + TAILQ_HEAD(, kore_handler_params) params; +#endif + TAILQ_ENTRY(kore_module_handle) list; +}; + +struct kore_worker { + u_int8_t id; + u_int8_t cpu; + pid_t pid; + int pipe[2]; + struct connection *msg[2]; + u_int8_t has_lock; + u_int64_t time_locked; + struct kore_module_handle *active_hdlr; +}; + +struct kore_domain { + char *domain; + int accesslog; +#if !defined(KORE_NO_TLS) + char *cafile; + char *crlfile; + char *certfile; + char *certkey; + SSL_CTX *ssl_ctx; +#endif + TAILQ_HEAD(, kore_module_handle) handlers; + TAILQ_ENTRY(kore_domain) list; +}; + +TAILQ_HEAD(kore_domain_h, kore_domain); + +#if !defined(KORE_NO_HTTP) + +#define KORE_VALIDATOR_TYPE_REGEX 1 +#define KORE_VALIDATOR_TYPE_FUNCTION 2 + +struct kore_validator { + u_int8_t type; + char *name; + char *arg; + regex_t rctx; + struct kore_runtime_call *rcall; + + TAILQ_ENTRY(kore_validator) list; +}; +#endif /* !KORE_NO_HTTP */ + +#define KORE_BUF_OWNER_API 0x0001 + +struct kore_buf { + u_int8_t *data; + int flags; + size_t length; + size_t offset; +}; + +struct kore_pool_region { + void *start; + size_t length; + LIST_ENTRY(kore_pool_region) list; +}; + +struct kore_pool_entry { + u_int8_t state; + struct kore_pool_region *region; + LIST_ENTRY(kore_pool_entry) list; +}; + +struct kore_pool { + size_t elen; + size_t slen; + size_t elms; + size_t inuse; + volatile int lock; + char *name; + + LIST_HEAD(, kore_pool_region) regions; + LIST_HEAD(, kore_pool_entry) freelist; +}; + +struct kore_timer { + u_int64_t nextrun; + u_int64_t interval; + int flags; + void *arg; + void (*cb)(void *, u_int64_t); + + TAILQ_ENTRY(kore_timer) list; +}; + +#define KORE_WORKER_KEYMGR 0 + +/* Reserved message ids, registered on workers. */ +#define KORE_MSG_ACCESSLOG 1 +#define KORE_MSG_WEBSOCKET 2 +#define KORE_MSG_KEYMGR_REQ 3 +#define KORE_MSG_KEYMGR_RESP 4 +#define KORE_MSG_SHUTDOWN 5 +#define KORE_MSG_ENTROPY_REQ 6 +#define KORE_MSG_ENTROPY_RESP 7 + +/* Predefined message targets. */ +#define KORE_MSG_PARENT 1000 +#define KORE_MSG_WORKER_ALL 1001 + +struct kore_msg { + u_int8_t id; + u_int16_t src; + u_int16_t dst; + u_int32_t length; +}; + +#if !defined(KORE_NO_TLS) +struct kore_keyreq { + int padding; + char domain[KORE_DOMAINNAME_LEN]; + u_int8_t domain_len; + u_int16_t data_len; + u_int8_t data[]; +}; +#endif + +#if !defined(KORE_SINGLE_BINARY) +extern char *config_file; +#endif + +extern pid_t kore_pid; +extern int foreground; +extern int kore_debug; +extern int skip_chroot; +extern char *chroot_path; +extern int skip_runas; +extern char *runas_user; +extern char *kore_pidfile; +extern char *kore_tls_cipher_list; +extern int tls_version; + +#if !defined(KORE_NO_TLS) +extern DH *tls_dhparam; +extern char *rand_file; +#endif + +extern u_int8_t nlisteners; +extern u_int16_t cpu_count; +extern u_int8_t worker_count; +extern u_int8_t worker_set_affinity; +extern u_int32_t worker_rlimit_nofiles; +extern u_int32_t worker_max_connections; +extern u_int32_t worker_active_connections; +extern u_int32_t worker_accept_threshold; +extern u_int64_t kore_websocket_maxframe; +extern u_int64_t kore_websocket_timeout; +extern u_int32_t kore_socket_backlog; + +extern struct listener_head listeners; +extern struct kore_worker *worker; +extern struct kore_domain_h domains; +extern struct kore_domain *primary_dom; +extern struct kore_pool nb_pool; + +void kore_signal(int); +void kore_worker_wait(int); +void kore_worker_init(void); +void kore_worker_shutdown(void); +void kore_worker_privdrop(void); +void kore_worker_dispatch_signal(int); +void kore_worker_spawn(u_int16_t, u_int16_t); +void kore_worker_entry(struct kore_worker *); + +struct kore_worker *kore_worker_data(u_int8_t); + +void kore_platform_init(void); +void kore_platform_event_init(void); +void kore_platform_event_cleanup(void); +void kore_platform_proctitle(char *); +void kore_platform_disable_read(int); +void kore_platform_enable_accept(void); +void kore_platform_disable_accept(void); +int kore_platform_event_wait(u_int64_t); +void kore_platform_event_all(int, void *); +void kore_platform_schedule_read(int, void *); +void kore_platform_schedule_write(int, void *); +void kore_platform_event_schedule(int, int, int, void *); +void kore_platform_worker_setcpu(struct kore_worker *); + +void kore_accesslog_init(void); +void kore_accesslog_worker_init(void); +int kore_accesslog_write(const void *, u_int32_t); + +#if !defined(KORE_NO_HTTP) +int kore_auth_run(struct http_request *, struct kore_auth *); +void kore_auth_init(void); +int kore_auth_new(const char *); +struct kore_auth *kore_auth_lookup(const char *); +#endif + +void kore_timer_init(void); +u_int64_t kore_timer_run(u_int64_t); +void kore_timer_remove(struct kore_timer *); +struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t), + u_int64_t, void *, int); + +int kore_sockopt(int, int, int); +void kore_listener_cleanup(void); +int kore_server_bind(const char *, const char *, const char *); +#if !defined(KORE_NO_TLS) +int kore_tls_sni_cb(SSL *, int *, void *); +void kore_tls_info_callback(const SSL *, int, int); +#endif + +void kore_connection_init(void); +void kore_connection_cleanup(void); +void kore_connection_prune(int); +struct connection *kore_connection_new(void *); +int kore_connection_nonblock(int, int); +void kore_connection_check_timeout(u_int64_t); +int kore_connection_handle(struct connection *); +void kore_connection_remove(struct connection *); +void kore_connection_disconnect(struct connection *); +void kore_connection_start_idletimer(struct connection *); +void kore_connection_stop_idletimer(struct connection *); +void kore_connection_check_idletimer(u_int64_t, + struct connection *); +int kore_connection_accept(struct listener *, + struct connection **); + +u_int64_t kore_time_ms(void); +void kore_log_init(void); + +void *kore_malloc(size_t); +void kore_parse_config(void); +void *kore_calloc(size_t, size_t); +void *kore_realloc(void *, size_t); +void kore_free(void *); +void kore_mem_init(void); +void kore_mem_cleanup(void); +void kore_mem_untag(void *); +void *kore_mem_lookup(u_int32_t); +void kore_mem_tag(void *, u_int32_t); +void *kore_malloc_tagged(size_t, u_int32_t); + +void *kore_pool_get(struct kore_pool *); +void kore_pool_put(struct kore_pool *, void *); +void kore_pool_init(struct kore_pool *, const char *, + size_t, size_t); +void kore_pool_cleanup(struct kore_pool *); + +time_t kore_date_to_time(char *); +char *kore_time_to_date(time_t); +char *kore_strdup(const char *); +void kore_log(int, const char *, ...) + __attribute__((format (printf, 2, 3))); +u_int64_t kore_strtonum64(const char *, int, int *); +size_t kore_strlcpy(char *, const char *, const size_t); +void kore_server_disconnect(struct connection *); +int kore_split_string(char *, const char *, char **, size_t); +void kore_strip_chars(char *, const char, char **); +int kore_snprintf(char *, size_t, int *, const char *, ...); +long long kore_strtonum(const char *, int, long long, long long, int *); +int kore_base64_encode(const void *, size_t, char **); +int kore_base64_decode(const char *, u_int8_t **, size_t *); +void *kore_mem_find(void *, size_t, void *, size_t); +char *kore_text_trim(char *, size_t); +char *kore_read_line(FILE *, char *, size_t); + +#if !defined(KORE_NO_HTTP) +void kore_websocket_handshake(struct http_request *, + const char *, const char *, const char *); +void kore_websocket_send(struct connection *, + u_int8_t, const void *, size_t); +void kore_websocket_broadcast(struct connection *, + u_int8_t, const void *, size_t, int); +#endif + +void kore_msg_init(void); +void kore_msg_worker_init(void); +void kore_msg_parent_init(void); +void kore_msg_parent_add(struct kore_worker *); +void kore_msg_parent_remove(struct kore_worker *); +void kore_msg_send(u_int16_t, u_int8_t, const void *, u_int32_t); +int kore_msg_register(u_int8_t, + void (*cb)(struct kore_msg *, const void *)); + +void kore_domain_init(void); +void kore_domain_cleanup(void); +int kore_domain_new(char *); +void kore_domain_free(struct kore_domain *); +void kore_module_init(void); +void kore_module_cleanup(void); +void kore_module_reload(int); +void kore_module_onload(void); +int kore_module_loaded(void); +void kore_domain_closelogs(void); +void *kore_module_getsym(const char *, struct kore_runtime **); +void kore_domain_load_crl(void); +void kore_domain_keymgr_init(void); +void kore_domain_tlsinit(struct kore_domain *); +void kore_module_load(const char *, const char *, int); +void kore_domain_callback(void (*cb)(struct kore_domain *)); +int kore_module_handler_new(const char *, const char *, + const char *, const char *, int); +void kore_module_handler_free(struct kore_module_handle *); + +struct kore_runtime_call *kore_runtime_getcall(const char *); + +void kore_runtime_execute(struct kore_runtime_call *); +int kore_runtime_onload(struct kore_runtime_call *, int); +void kore_runtime_connect(struct kore_runtime_call *, struct connection *); +#if !defined(KORE_NO_HTTP) +int kore_runtime_http_request(struct kore_runtime_call *, + struct http_request *); +int kore_runtime_validator(struct kore_runtime_call *, + struct http_request *, const void *); +void kore_runtime_wsconnect(struct kore_runtime_call *, struct connection *); +void kore_runtime_wsdisconnect(struct kore_runtime_call *, + struct connection *); +void kore_runtime_wsmessage(struct kore_runtime_call *, + struct connection *, u_int8_t, const void *, size_t); +#endif + +struct kore_domain *kore_domain_lookup(const char *); +struct kore_module_handle *kore_module_handler_find(const char *, + const char *); + +#if !defined(KORE_NO_HTTP) +void kore_validator_init(void); +void kore_validator_reload(void); +int kore_validator_add(const char *, u_int8_t, const char *); +int kore_validator_run(struct http_request *, const char *, char *); +int kore_validator_check(struct http_request *, + struct kore_validator *, const void *); +struct kore_validator *kore_validator_lookup(const char *); +#endif + +void fatal(const char *, ...) __attribute__((noreturn)); +void kore_debug_internal(char *, int, const char *, ...); + +u_int16_t net_read16(u_int8_t *); +u_int32_t net_read32(u_int8_t *); +u_int64_t net_read64(u_int8_t *); +void net_write16(u_int8_t *, u_int16_t); +void net_write32(u_int8_t *, u_int32_t); +void net_write64(u_int8_t *, u_int64_t); + +void net_init(void); +void net_cleanup(void); +int net_send(struct connection *); +int net_send_flush(struct connection *); +int net_recv_flush(struct connection *); +int net_read(struct connection *, size_t *); +int net_read_tls(struct connection *, size_t *); +int net_write(struct connection *, size_t, size_t *); +int net_write_tls(struct connection *, size_t, size_t *); +void net_recv_reset(struct connection *, size_t, + int (*cb)(struct netbuf *)); +void net_remove_netbuf(struct netbuf_head *, struct netbuf *); +void net_recv_queue(struct connection *, size_t, int, + int (*cb)(struct netbuf *)); +void net_recv_expand(struct connection *c, size_t, + int (*cb)(struct netbuf *)); +void net_send_queue(struct connection *, const void *, size_t); +void net_send_stream(struct connection *, void *, + size_t, int (*cb)(struct netbuf *), struct netbuf **); + +void kore_buf_free(struct kore_buf *); +struct kore_buf *kore_buf_alloc(size_t); +void kore_buf_init(struct kore_buf *, size_t); +void kore_buf_append(struct kore_buf *, const void *, size_t); +u_int8_t *kore_buf_release(struct kore_buf *, size_t *); +void kore_buf_reset(struct kore_buf *); +void kore_buf_cleanup(struct kore_buf *); + +char *kore_buf_stringify(struct kore_buf *, size_t *); +void kore_buf_appendf(struct kore_buf *, const char *, ...); +void kore_buf_appendv(struct kore_buf *, const char *, va_list); +void kore_buf_replace_string(struct kore_buf *, char *, void *, size_t); + +void kore_keymgr_run(void); +void kore_keymgr_cleanup(void); + +void kore_parent_configure(void); +void kore_worker_configure(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* !__H_KORE_H */ diff --git a/include/kore/pgsql.h b/include/kore/pgsql.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014-2018 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _H_KORE_PGSQL +#define _H_KORE_PGSQL + +#include <libpq-fe.h> + +#define KORE_PGSQL_FORMAT_TEXT 0 +#define KORE_PGSQL_FORMAT_BINARY 1 + +#define KORE_PGSQL_SYNC 0x0001 +#define KORE_PGSQL_ASYNC 0x0002 +#define KORE_PGSQL_SCHEDULED 0x0004 + +#if defined(__cplusplus) +extern "C" { +#endif + +struct pgsql_conn { + u_int8_t type; + u_int8_t flags; + char *name; + + PGconn *db; + struct pgsql_job *job; + TAILQ_ENTRY(pgsql_conn) list; +}; + +struct pgsql_db { + char *name; + char *conn_string; + u_int16_t conn_max; + u_int16_t conn_count; + + LIST_ENTRY(pgsql_db) rlist; +}; + +struct kore_pgsql { + u_int8_t state; + int flags; + char *error; + PGresult *result; + struct pgsql_conn *conn; + + struct http_request *req; + void *arg; + void (*cb)(struct kore_pgsql *, void *); + + LIST_ENTRY(kore_pgsql) rlist; +}; + +extern u_int16_t pgsql_conn_max; +extern u_int32_t pgsql_queue_limit; + +void kore_pgsql_sys_init(void); +void kore_pgsql_sys_cleanup(void); +void kore_pgsql_init(struct kore_pgsql *); +void kore_pgsql_bind_request(struct kore_pgsql *, struct http_request *); +void kore_pgsql_bind_callback(struct kore_pgsql *, + void (*cb)(struct kore_pgsql *, void *), void *); +int kore_pgsql_setup(struct kore_pgsql *, const char *, int); +void kore_pgsql_handle(void *, int); +void kore_pgsql_cleanup(struct kore_pgsql *); +void kore_pgsql_continue(struct kore_pgsql *); +int kore_pgsql_query(struct kore_pgsql *, const char *); +int kore_pgsql_query_params(struct kore_pgsql *, + const char *, int, int, ...); +int kore_pgsql_v_query_params(struct kore_pgsql *, + const char *, int, int, va_list); +int kore_pgsql_register(const char *, const char *); +int kore_pgsql_ntuples(struct kore_pgsql *); +int kore_pgsql_nfields(struct kore_pgsql *); +void kore_pgsql_logerror(struct kore_pgsql *); +char *kore_pgsql_fieldname(struct kore_pgsql *, int); +char *kore_pgsql_getvalue(struct kore_pgsql *, int, int); +int kore_pgsql_getlength(struct kore_pgsql *, int, int); + +#if defined(__cplusplus) +} +#endif + +#define KORE_PGSQL_STATE_INIT 1 +#define KORE_PGSQL_STATE_WAIT 2 +#define KORE_PGSQL_STATE_RESULT 3 +#define KORE_PGSQL_STATE_ERROR 4 +#define KORE_PGSQL_STATE_DONE 5 +#define KORE_PGSQL_STATE_COMPLETE 6 + +#endif diff --git a/include/kore/python_api.h b/include/kore/python_api.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016 Stanislav Yudin <stan@endlessinsomnia.com> + * Copyright (c) 2017-2018 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __H_PYTHON_H +#define __H_PYTHON_H + +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE + +#include <Python.h> + +void kore_python_init(void); +void kore_python_cleanup(void); +void kore_python_path(const char *); + +PyObject *kore_python_callable(PyObject *, const char *); + +extern struct kore_module_functions kore_python_module; +extern struct kore_runtime kore_python_runtime; + +#endif diff --git a/include/kore/python_methods.h b/include/kore/python_methods.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2017-2018 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +static PyObject *python_kore_log(PyObject *, PyObject *); +static PyObject *python_kore_fatal(PyObject *, PyObject *); +static PyObject *python_kore_listen(PyObject *, PyObject *); + +#if defined(KORE_USE_PGSQL) +static PyObject *python_kore_pgsql_register(PyObject *, PyObject *); +#endif + +static PyObject *python_websocket_broadcast(PyObject *, PyObject *); + +#define METHOD(n, c, a) { n, (PyCFunction)c, a, NULL } +#define GETTER(n, g) { n, (getter)g, NULL, NULL, NULL } +#define SETTER(n, s) { n, NULL, (setter)g, NULL, NULL } +#define GETSET(n, g, s) { n, (getter)g, (setter)s, NULL, NULL } + +static struct PyMethodDef pykore_methods[] = { + METHOD("log", python_kore_log, METH_VARARGS), + METHOD("fatal", python_kore_fatal, METH_VARARGS), + METHOD("listen", python_kore_listen, METH_VARARGS), + METHOD("websocket_broadcast", python_websocket_broadcast, METH_VARARGS), +#if defined(KORE_USE_PGSQL) + METHOD("register_database", python_kore_pgsql_register, METH_VARARGS), +#endif + { NULL, NULL, 0, NULL } +}; + +static struct PyModuleDef pykore_module = { + PyModuleDef_HEAD_INIT, "kore", NULL, -1, pykore_methods +}; + +struct pyconnection { + PyObject_HEAD + struct connection *c; +}; + +static PyObject *pyconnection_disconnect(struct pyconnection *, PyObject *); +static PyObject *pyconnection_websocket_send(struct pyconnection *, PyObject *); + +static PyMethodDef pyconnection_methods[] = { + METHOD("disconnect", pyconnection_disconnect, METH_NOARGS), + METHOD("websocket_send", pyconnection_websocket_send, METH_VARARGS), + METHOD(NULL, NULL, -1), +}; + +static PyObject *pyconnection_get_fd(struct pyconnection *, void *); +static PyObject *pyconnection_get_addr(struct pyconnection *, void *); + +static PyGetSetDef pyconnection_getset[] = { + GETTER("fd", pyconnection_get_fd), + GETTER("addr", pyconnection_get_addr), + GETTER(NULL, NULL), +}; + +static void pyconnection_dealloc(struct pyconnection *); + +static PyTypeObject pyconnection_type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "kore.connection", + .tp_doc = "struct connection", + .tp_getset = pyconnection_getset, + .tp_methods = pyconnection_methods, + .tp_basicsize = sizeof(struct pyconnection), + .tp_dealloc = (destructor)pyconnection_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +struct pyhttp_request { + PyObject_HEAD + struct http_request *req; + PyObject *data; +}; + +struct pyhttp_file { + PyObject_HEAD + struct http_file *file; +}; + +static void pyhttp_dealloc(struct pyhttp_request *); +static void pyhttp_file_dealloc(struct pyhttp_file *); + +#if defined(KORE_USE_PGSQL) +static PyObject *pyhttp_pgsql(struct pyhttp_request *, PyObject *); +#endif +static PyObject *pyhttp_cookie(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_response(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_argument(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_body_read(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_file_lookup(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_populate_get(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_populate_post(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_populate_multi(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_populate_cookies(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_request_header(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_response_header(struct pyhttp_request *, PyObject *); +static PyObject *pyhttp_websocket_handshake(struct pyhttp_request *, + PyObject *); + +static PyMethodDef pyhttp_request_methods[] = { +#if defined(KORE_USE_PGSQL) + METHOD("pgsql", pyhttp_pgsql, METH_VARARGS), +#endif + METHOD("cookie", pyhttp_cookie, METH_VARARGS), + METHOD("response", pyhttp_response, METH_VARARGS), + METHOD("argument", pyhttp_argument, METH_VARARGS), + METHOD("body_read", pyhttp_body_read, METH_VARARGS), + METHOD("file_lookup", pyhttp_file_lookup, METH_VARARGS), + METHOD("populate_get", pyhttp_populate_get, METH_NOARGS), + METHOD("populate_post", pyhttp_populate_post, METH_NOARGS), + METHOD("populate_multi", pyhttp_populate_multi, METH_NOARGS), + METHOD("populate_cookies", pyhttp_populate_cookies, METH_NOARGS), + METHOD("request_header", pyhttp_request_header, METH_VARARGS), + METHOD("response_header", pyhttp_response_header, METH_VARARGS), + METHOD("websocket_handshake", pyhttp_websocket_handshake, METH_VARARGS), + METHOD(NULL, NULL, -1) +}; + +static PyObject *pyhttp_get_host(struct pyhttp_request *, void *); +static PyObject *pyhttp_get_path(struct pyhttp_request *, void *); +static PyObject *pyhttp_get_body(struct pyhttp_request *, void *); +static PyObject *pyhttp_get_agent(struct pyhttp_request *, void *); +static PyObject *pyhttp_get_method(struct pyhttp_request *, void *); +static PyObject *pyhttp_get_body_path(struct pyhttp_request *, void *); +static PyObject *pyhttp_get_connection(struct pyhttp_request *, void *); + +static PyGetSetDef pyhttp_request_getset[] = { + GETTER("host", pyhttp_get_host), + GETTER("path", pyhttp_get_path), + GETTER("body", pyhttp_get_body), + GETTER("agent", pyhttp_get_agent), + GETTER("method", pyhttp_get_method), + GETTER("body_path", pyhttp_get_body_path), + GETTER("connection", pyhttp_get_connection), + GETTER(NULL, NULL) +}; + +static PyTypeObject pyhttp_request_type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "kore.http_request", + .tp_doc = "struct http_request", + .tp_getset = pyhttp_request_getset, + .tp_methods = pyhttp_request_methods, + .tp_dealloc = (destructor)pyhttp_dealloc, + .tp_basicsize = sizeof(struct pyhttp_request), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +static PyObject *pyhttp_file_read(struct pyhttp_file *, PyObject *); + +static PyMethodDef pyhttp_file_methods[] = { + METHOD("read", pyhttp_file_read, METH_VARARGS), + METHOD(NULL, NULL, -1) +}; + +static PyObject *pyhttp_file_get_name(struct pyhttp_file *, void *); +static PyObject *pyhttp_file_get_filename(struct pyhttp_file *, void *); + +static PyGetSetDef pyhttp_file_getset[] = { + GETTER("name", pyhttp_file_get_name), + GETTER("filename", pyhttp_file_get_filename), + GETTER(NULL, NULL) +}; + +static PyTypeObject pyhttp_file_type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "kore.http_file", + .tp_doc = "struct http_file", + .tp_getset = pyhttp_file_getset, + .tp_methods = pyhttp_file_methods, + .tp_dealloc = (destructor)pyhttp_file_dealloc, + .tp_basicsize = sizeof(struct pyhttp_file), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +#if defined(KORE_USE_PGSQL) + +#define PYKORE_PGSQL_PREINIT 1 +#define PYKORE_PGSQL_INITIALIZE 2 +#define PYKORE_PGSQL_QUERY 3 +#define PYKORE_PGSQL_WAIT 4 + +struct pykore_pgsql { + PyObject_HEAD + int state; + char *db; + char *query; + struct http_request *req; + PyObject *result; + struct kore_pgsql sql; +}; + +static void pykore_pgsql_dealloc(struct pykore_pgsql *); +int pykore_pgsql_result(struct pykore_pgsql *); + +static PyObject *pykore_pgsql_await(PyObject *); +static PyObject *pykore_pgsql_iternext(struct pykore_pgsql *); + +static PyAsyncMethods pykore_pgsql_async = { + (unaryfunc)pykore_pgsql_await, + NULL, + NULL +}; + +static PyTypeObject pykore_pgsql_type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "kore.pgsql", + .tp_doc = "struct kore_pgsql", + .tp_as_async = &pykore_pgsql_async, + .tp_iternext = (iternextfunc)pykore_pgsql_iternext, + .tp_basicsize = sizeof(struct pykore_pgsql), + .tp_dealloc = (destructor)pykore_pgsql_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; +#endif diff --git a/include/kore/tasks.h b/include/kore/tasks.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __H_KORE_TASKS +#define __H_KORE_TASKS + +#include <pthread.h> + +#define KORE_TASK_STATE_CREATED 1 +#define KORE_TASK_STATE_RUNNING 2 +#define KORE_TASK_STATE_FINISHED 3 +#define KORE_TASK_STATE_ABORT 4 + +#define KORE_TASK_THREADS 2 + +#if defined(__cplusplus) +extern "C" { +#endif + +#if !defined(KORE_NO_HTTP) +struct http_request; +#endif + +struct kore_task { + u_int8_t type; + int state; + int result; + pthread_rwlock_t lock; + +#if !defined(KORE_NO_HTTP) + struct http_request *req; +#endif + + int fds[2]; + int (*entry)(struct kore_task *); + void (*cb)(struct kore_task *); + + struct kore_task_thread *thread; + + TAILQ_ENTRY(kore_task) list; + LIST_ENTRY(kore_task) rlist; +}; + +struct kore_task_thread { + u_int8_t idx; + pthread_t tid; + pthread_mutex_t lock; + pthread_cond_t cond; + TAILQ_HEAD(, kore_task) tasks; + + TAILQ_ENTRY(kore_task_thread) list; +}; + +void kore_task_init(void); +void kore_task_run(struct kore_task *); +void kore_task_finish(struct kore_task *); +void kore_task_destroy(struct kore_task *); +int kore_task_finished(struct kore_task *); +void kore_task_handle(struct kore_task *, int); + +#if !defined(KORE_NO_HTTP) +void kore_task_bind_request(struct kore_task *, + struct http_request *); +#endif +void kore_task_bind_callback(struct kore_task *, + void (*cb)(struct kore_task *)); +void kore_task_create(struct kore_task *, + int (*entry)(struct kore_task *)); + +u_int32_t kore_task_channel_read(struct kore_task *, void *, u_int32_t); +void kore_task_channel_write(struct kore_task *, void *, u_int32_t); + +void kore_task_set_state(struct kore_task *, int); +void kore_task_set_result(struct kore_task *, int); + +int kore_task_state(struct kore_task *); +int kore_task_result(struct kore_task *); + +extern u_int16_t kore_task_threads; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/includes/http.h b/includes/http.h @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2013 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#if !defined(KORE_NO_HTTP) - -#ifndef __H_HTTP_H -#define __H_HTTP_H - -#include <sys/types.h> -#include <sys/queue.h> - -#if defined(__cplusplus) -extern "C" { -#endif - -/* Keep the http_populate_get symbol around. */ -#define http_populate_get http_populate_qs - -#define HTTP_KEEPALIVE_TIME 20 -#define HTTP_HSTS_ENABLE 31536000 -#define HTTP_HEADER_MAX_LEN 4096 -#define HTTP_BODY_MAX_LEN 1024000 -#define HTTP_URI_LEN 2000 -#define HTTP_USERAGENT_LEN 256 -#define HTTP_REQ_HEADER_MAX 25 -#define HTTP_MAX_QUERY_ARGS 20 -#define HTTP_MAX_COOKIES 10 -#define HTTP_MAX_COOKIENAME 255 -#define HTTP_HEADER_BUFSIZE 1024 -#define HTTP_COOKIE_BUFSIZE 1024 -#define HTTP_DATE_MAXSIZE 255 -#define HTTP_REQUEST_LIMIT 1000 -#define HTTP_REQUEST_MS 10 -#define HTTP_BODY_DISK_PATH "tmp_files" -#define HTTP_BODY_DISK_OFFLOAD 0 -#define HTTP_BODY_PATH_MAX 256 -#define HTTP_BOUNDARY_MAX 80 - -#define HTTP_ARG_TYPE_RAW 0 -#define HTTP_ARG_TYPE_BYTE 1 -#define HTTP_ARG_TYPE_INT16 2 -#define HTTP_ARG_TYPE_UINT16 3 -#define HTTP_ARG_TYPE_INT32 4 -#define HTTP_ARG_TYPE_UINT32 5 -#define HTTP_ARG_TYPE_STRING 6 -#define HTTP_ARG_TYPE_INT64 7 -#define HTTP_ARG_TYPE_UINT64 8 - -#define HTTP_STATE_ERROR 0 -#define HTTP_STATE_CONTINUE 1 -#define HTTP_STATE_COMPLETE 2 -#define HTTP_STATE_RETRY 3 - -struct http_header { - char *header; - char *value; - - TAILQ_ENTRY(http_header) list; -}; - -#define HTTP_COOKIE_HTTPONLY 0x0001 -#define HTTP_COOKIE_SECURE 0x0002 - -struct http_cookie { - char *name; - char *value; - char *path; - char *domain; - u_int32_t maxage; - time_t expires; - u_int16_t flags; - - TAILQ_ENTRY(http_cookie) list; -}; - -struct http_arg { - char *name; - char *s_value; - - TAILQ_ENTRY(http_arg) list; -}; - -#define COPY_ARG_TYPE(v, t) \ - do { \ - *(t *)nout = v; \ - } while (0) - -#define COPY_ARG_INT64(type, sign) \ - do { \ - int err; \ - type nval; \ - nval = (type)kore_strtonum64(q->s_value, sign, &err); \ - if (err != KORE_RESULT_OK) \ - return (KORE_RESULT_ERROR); \ - COPY_ARG_TYPE(nval, type); \ - } while (0) - -#define COPY_ARG_INT(min, max, type) \ - do { \ - int err; \ - int64_t nval; \ - nval = kore_strtonum(q->s_value, 10, min, max, &err); \ - if (err != KORE_RESULT_OK) \ - return (KORE_RESULT_ERROR); \ - COPY_ARG_TYPE(nval, type); \ - } while (0) - -#define COPY_AS_INTTYPE_64(type, sign) \ - do { \ - if (nout == NULL) \ - return (KORE_RESULT_ERROR); \ - COPY_ARG_INT64(type, sign); \ - } while (0) - -#define COPY_AS_INTTYPE(min, max, type) \ - do { \ - if (nout == NULL) \ - return (KORE_RESULT_ERROR); \ - COPY_ARG_INT(min, max, type); \ - } while (0) - -#define http_argument_type(r, n, so, no, t) \ - http_argument_get(r, n, so, no, t) - -#define http_argument_get_string(r, n, o) \ - http_argument_type(r, n, (void **)o, NULL, HTTP_ARG_TYPE_STRING) - -#define http_argument_get_byte(r, n, o) \ - http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_BYTE) - -#define http_argument_get_uint16(r, n, o) \ - http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT16) - -#define http_argument_get_int16(r, n, o) \ - http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT16) - -#define http_argument_get_uint32(r, n, o) \ - http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT32) - -#define http_argument_get_int32(r, n, o) \ - http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT32) - -#define http_argument_get_uint64(r, n, o) \ - http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_UINT64) - -#define http_argument_get_int64(r, n, o) \ - http_argument_type(r, n, NULL, o, HTTP_ARG_TYPE_INT64) - - -struct http_file { - char *name; - char *filename; - size_t position; - size_t offset; - size_t length; - struct http_request *req; - TAILQ_ENTRY(http_file) list; -}; - -#define HTTP_METHOD_GET 0 -#define HTTP_METHOD_POST 1 -#define HTTP_METHOD_PUT 2 -#define HTTP_METHOD_DELETE 3 -#define HTTP_METHOD_HEAD 4 -#define HTTP_METHOD_OPTIONS 5 -#define HTTP_METHOD_PATCH 6 - -#define HTTP_REQUEST_COMPLETE 0x0001 -#define HTTP_REQUEST_DELETE 0x0002 -#define HTTP_REQUEST_SLEEPING 0x0004 -#define HTTP_REQUEST_EXPECT_BODY 0x0020 -#define HTTP_REQUEST_RETAIN_EXTRA 0x0040 -#define HTTP_REQUEST_NO_CONTENT_LENGTH 0x0080 -#define HTTP_REQUEST_AUTHED 0x0100 - -#define HTTP_VALIDATOR_IS_REQUEST 0x8000 - -struct kore_task; - -struct http_request { - u_int8_t method; - u_int8_t fsm_state; - u_int16_t flags; - u_int16_t status; - u_int64_t ms; - u_int64_t start; - u_int64_t end; - u_int64_t total; - const char *path; - const char *host; - const char *agent; - struct connection *owner; - u_int8_t *headers; - struct kore_buf *http_body; - int http_body_fd; - char *http_body_path; - size_t http_body_length; - size_t http_body_offset; - size_t content_length; - void *hdlr_extra; - size_t state_len; - char *query_string; - struct kore_module_handle *hdlr; - -#if defined(KORE_USE_PYTHON) - void *py_coro; -#endif - - LIST_HEAD(, kore_task) tasks; - LIST_HEAD(, kore_pgsql) pgsqls; - - TAILQ_HEAD(, http_cookie) req_cookies; - TAILQ_HEAD(, http_cookie) resp_cookies; - TAILQ_HEAD(, http_header) req_headers; - TAILQ_HEAD(, http_header) resp_headers; - TAILQ_HEAD(, http_arg) arguments; - TAILQ_HEAD(, http_file) files; - TAILQ_ENTRY(http_request) list; - TAILQ_ENTRY(http_request) olist; -}; - -struct http_state { - const char *name; - int (*cb)(struct http_request *); -}; - -extern size_t http_body_max; -extern u_int16_t http_header_max; -extern u_int32_t http_request_ms; -extern u_int64_t http_hsts_enable; -extern u_int16_t http_keepalive_time; -extern u_int32_t http_request_limit; -extern u_int32_t http_request_count; -extern u_int64_t http_body_disk_offload; -extern char *http_body_disk_path; - -void kore_accesslog(struct http_request *); - -void http_init(void); -void http_cleanup(void); -void http_server_version(const char *); -void http_process(void); -const char *http_status_text(int); -const char *http_method_text(int); -time_t http_date_to_time(char *); -void http_request_free(struct http_request *); -void http_request_sleep(struct http_request *); -void http_request_wakeup(struct http_request *); -void http_process_request(struct http_request *); -int http_body_rewind(struct http_request *); -ssize_t http_body_read(struct http_request *, void *, size_t); -void http_response(struct http_request *, int, const void *, size_t); -void http_serveable(struct http_request *, const void *, - size_t, const char *, const char *); -void http_response_stream(struct http_request *, int, void *, - size_t, int (*cb)(struct netbuf *), void *); -int http_request_header(struct http_request *, - const char *, const char **); -void http_response_header(struct http_request *, - const char *, const char *); -int http_state_run(struct http_state *, u_int8_t, - struct http_request *); -int http_request_cookie(struct http_request *, - const char *, char **); -void http_response_cookie(struct http_request *, const char *, - const char *, const char *, time_t, u_int32_t, - struct http_cookie **); - -void *http_state_get(struct http_request *); -int http_state_exists(struct http_request *); -void http_state_cleanup(struct http_request *); -void *http_state_create(struct http_request *, size_t); - -int http_argument_urldecode(char *); -int http_header_recv(struct netbuf *); -void http_populate_qs(struct http_request *); -void http_populate_post(struct http_request *); -void http_populate_multipart_form(struct http_request *); -void http_populate_cookies(struct http_request *); -int http_argument_get(struct http_request *, - const char *, void **, void *, int); - -void http_file_rewind(struct http_file *); -ssize_t http_file_read(struct http_file *, void *, size_t); -struct http_file *http_file_lookup(struct http_request *, const char *); - -enum http_status_code { - HTTP_STATUS_CONTINUE = 100, - HTTP_STATUS_SWITCHING_PROTOCOLS = 101, - HTTP_STATUS_OK = 200, - HTTP_STATUS_CREATED = 201, - HTTP_STATUS_ACCEPTED = 202, - HTTP_STATUS_NON_AUTHORITATIVE = 203, - HTTP_STATUS_NO_CONTENT = 204, - HTTP_STATUS_RESET_CONTENT = 205, - HTTP_STATUS_PARTIAL_CONTENT = 206, - HTTP_STATUS_MULTIPLE_CHOICES = 300, - HTTP_STATUS_MOVED_PERMANENTLY = 301, - HTTP_STATUS_FOUND = 302, - HTTP_STATUS_SEE_OTHER = 303, - HTTP_STATUS_NOT_MODIFIED = 304, - HTTP_STATUS_USE_PROXY = 305, - HTTP_STATUS_TEMPORARY_REDIRECT = 307, - HTTP_STATUS_BAD_REQUEST = 400, - HTTP_STATUS_UNAUTHORIZED = 401, - HTTP_STATUS_PAYMENT_REQUIRED = 402, - HTTP_STATUS_FORBIDDEN = 403, - HTTP_STATUS_NOT_FOUND = 404, - HTTP_STATUS_METHOD_NOT_ALLOWED = 405, - HTTP_STATUS_NOT_ACCEPTABLE = 406, - HTTP_STATUS_PROXY_AUTH_REQUIRED = 407, - HTTP_STATUS_REQUEST_TIMEOUT = 408, - HTTP_STATUS_CONFLICT = 409, - HTTP_STATUS_GONE = 410, - HTTP_STATUS_LENGTH_REQUIRED = 411, - HTTP_STATUS_PRECONDITION_FAILED = 412, - HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413, - HTTP_STATUS_REQUEST_URI_TOO_LARGE = 414, - HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, - HTTP_STATUS_REQUEST_RANGE_INVALID = 416, - HTTP_STATUS_EXPECTATION_FAILED = 417, - HTTP_STATUS_INTERNAL_ERROR = 500, - HTTP_STATUS_NOT_IMPLEMENTED = 501, - HTTP_STATUS_BAD_GATEWAY = 502, - HTTP_STATUS_SERVICE_UNAVAILABLE = 503, - HTTP_STATUS_GATEWAY_TIMEOUT = 504, - HTTP_STATUS_BAD_VERSION = 505 -}; -#if defined(__cplusplus) -} -#endif -#endif /* !__H_HTTP_H */ - -#endif /* ! KORE_NO_HTTP */ diff --git a/includes/jsonrpc.h b/includes/jsonrpc.h @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2016 Raphaël Monrouzeau <raphael.monrouzeau@gmail.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#if !defined(KORE_NO_HTTP) - -#ifndef __H_JSONRPC_H -#define __H_JSONRPC_H - -#if defined(__cplusplus) -extern "C" { -#endif - -/* JSON RPC request handling log entry. */ -struct jsonrpc_log -{ - char *msg; - struct jsonrpc_log *next, *prev; - int lvl; -}; - -/* JSON RPC request. */ -struct jsonrpc_request -{ - struct jsonrpc_log log; - struct kore_buf buf; - struct http_request *http; - yajl_gen gen; - yajl_val json; - yajl_val id; - char *method; - yajl_val params; - unsigned int flags; - int log_levels; -}; - -#define YAJL_GEN_CONST_STRING(CTX, STR) \ - yajl_gen_string((CTX), (unsigned char *)(STR), sizeof (STR) - 1) - -#define YAJL_GEN_CONST_NUMBER(CTX, STR) \ - yajl_gen_number((CTX), (unsigned char *)(STR), sizeof (STR) - 1) - -#define YAJL_GEN_KO(OPERATION) \ - ((OPERATION) != yajl_gen_status_ok) - -enum jsonrpc_error_code -{ -#define JSONRPC_PARSE_ERROR_MSG "Parse error" - JSONRPC_PARSE_ERROR = -32700, -#define JSONRPC_INVALID_REQUEST_MSG "Invalid Request" - JSONRPC_INVALID_REQUEST = -32600, -#define JSONRPC_METHOD_NOT_FOUND_MSG "Method not found" - JSONRPC_METHOD_NOT_FOUND = -32601, -#define JSONRPC_INVALID_PARAMS_MSG "Invalid params" - JSONRPC_INVALID_PARAMS = -32602, -#define JSONRPC_INTERNAL_ERROR_MSG "Internal error" - JSONRPC_INTERNAL_ERROR = -32603, -#define JSONRPC_SERVER_ERROR_MSG "Server error" - JSONRPC_SERVER_ERROR = -32000, -#define JSONRPC_LIMIT_REACHED_MSG "Limit reached" - JSONRPC_LIMIT_REACHED = -31997 -}; - -void jsonrpc_log(struct jsonrpc_request *, int, const char *, ...); -int jsonrpc_read_request(struct http_request *, struct jsonrpc_request *); -void jsonrpc_destroy_request(struct jsonrpc_request *); -int jsonrpc_error(struct jsonrpc_request *, int, const char *); -int jsonrpc_result(struct jsonrpc_request *, - int (*)(struct jsonrpc_request *, void *), void *); -#if defined(__cplusplus) -} -#endif -#endif /* !__H_JSONRPC_H */ - -#endif /* ! KORE_NO_HTTP */ diff --git a/includes/kore.h b/includes/kore.h @@ -1,716 +0,0 @@ -/* - * Copyright (c) 2013-2018 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __H_KORE_H -#define __H_KORE_H - -#if defined(__APPLE__) -#define daemon portability_is_king -#endif - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/queue.h> - -#include <netinet/in.h> -#include <arpa/inet.h> - -#if !defined(KORE_NO_TLS) -#include <openssl/err.h> -#include <openssl/dh.h> -#include <openssl/ssl.h> -#endif - -#include <errno.h> -#include <regex.h> -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <stdarg.h> - -#if defined(__cplusplus) -extern "C" { -#endif - -#if defined(__APPLE__) -#undef daemon -extern int daemon(int, int); -#endif - -#define KORE_RESULT_ERROR 0 -#define KORE_RESULT_OK 1 -#define KORE_RESULT_RETRY 2 - -#define KORE_VERSION_MAJOR 2 -#define KORE_VERSION_MINOR 1 -#define KORE_VERSION_PATCH 0 -#define KORE_VERSION_STATE "devel" - -#define KORE_TLS_VERSION_1_2 0 -#define KORE_TLS_VERSION_1_0 1 -#define KORE_TLS_VERSION_BOTH 2 - -#define KORE_RESEED_TIME (1800 * 1000) - -#define errno_s strerror(errno) -#define ssl_errno_s ERR_error_string(ERR_get_error(), NULL) - -#define KORE_DOMAINNAME_LEN 255 -#define KORE_PIDFILE_DEFAULT "kore.pid" -#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" - -#if defined(KORE_DEBUG) -#define kore_debug(...) \ - if (kore_debug) \ - kore_debug_internal(__FILE__, __LINE__, __VA_ARGS__) -#else -#define kore_debug(...) -#endif - -#define NETBUF_RECV 0 -#define NETBUF_SEND 1 -#define NETBUF_SEND_PAYLOAD_MAX 8192 - -#define NETBUF_LAST_CHAIN 0 -#define NETBUF_BEFORE_CHAIN 1 - -#define NETBUF_CALL_CB_ALWAYS 0x01 -#define NETBUF_FORCE_REMOVE 0x02 -#define NETBUF_MUST_RESEND 0x04 -#define NETBUF_IS_STREAM 0x10 - -#define X509_GET_CN(c, o, l) \ - X509_NAME_get_text_by_NID(X509_get_subject_name(c), \ - NID_commonName, o, l) - -#define X509_CN_LENGTH (ub_common_name + 1) - -/* XXX hackish. */ -#if !defined(KORE_NO_HTTP) -struct http_request; -#endif - -struct netbuf { - u_int8_t *buf; - size_t s_off; - size_t b_len; - size_t m_len; - u_int8_t type; - u_int8_t flags; - - void *owner; - - void *extra; - int (*cb)(struct netbuf *); - - TAILQ_ENTRY(netbuf) list; -}; - -TAILQ_HEAD(netbuf_head, netbuf); - -#define KORE_TYPE_LISTENER 1 -#define KORE_TYPE_CONNECTION 2 -#define KORE_TYPE_PGSQL_CONN 3 -#define KORE_TYPE_TASK 4 - -#define CONN_STATE_UNKNOWN 0 -#define CONN_STATE_TLS_SHAKE 1 -#define CONN_STATE_ESTABLISHED 2 -#define CONN_STATE_DISCONNECTING 3 - -#define CONN_PROTO_UNKNOWN 0 -#define CONN_PROTO_HTTP 1 -#define CONN_PROTO_WEBSOCKET 2 -#define CONN_PROTO_MSG 3 - -#define CONN_READ_POSSIBLE 0x01 -#define CONN_WRITE_POSSIBLE 0x02 -#define CONN_WRITE_BLOCK 0x04 -#define CONN_IDLE_TIMER_ACT 0x10 -#define CONN_READ_BLOCK 0x20 -#define CONN_CLOSE_EMPTY 0x40 -#define CONN_WS_CLOSE_SENT 0x80 - -#define KORE_IDLE_TIMER_MAX 5000 - -#define WEBSOCKET_OP_CONT 0x00 -#define WEBSOCKET_OP_TEXT 0x01 -#define WEBSOCKET_OP_BINARY 0x02 -#define WEBSOCKET_OP_CLOSE 0x08 -#define WEBSOCKET_OP_PING 0x09 -#define WEBSOCKET_OP_PONG 0x0a - -#define WEBSOCKET_BROADCAST_LOCAL 1 -#define WEBSOCKET_BROADCAST_GLOBAL 2 - -#define KORE_TIMER_ONESHOT 0x01 - -#define KORE_CONNECTION_PRUNE_DISCONNECT 0 -#define KORE_CONNECTION_PRUNE_ALL 1 - -struct connection { - u_int8_t type; - int fd; - u_int8_t state; - u_int8_t proto; - void *owner; -#if !defined(KORE_NO_TLS) - X509 *cert; - SSL *ssl; - int tls_reneg; -#endif - u_int8_t flags; - void *hdlr_extra; - - int (*handle)(struct connection *); - void (*disconnect)(struct connection *); - int (*read)(struct connection *, size_t *); - int (*write)(struct connection *, size_t, size_t *); - - u_int8_t addrtype; - union { - struct sockaddr_in ipv4; - struct sockaddr_in6 ipv6; - } addr; - - struct { - u_int64_t length; - u_int64_t start; - } idle_timer; - - struct netbuf_head send_queue; - struct netbuf *snb; - struct netbuf *rnb; - -#if !defined(KORE_NO_HTTP) - struct kore_runtime_call *ws_connect; - struct kore_runtime_call *ws_message; - struct kore_runtime_call *ws_disconnect; - TAILQ_HEAD(, http_request) http_requests; -#endif - - TAILQ_ENTRY(connection) list; -}; - -TAILQ_HEAD(connection_list, connection); -extern struct connection_list connections; -extern struct connection_list disconnected; - -#define KORE_RUNTIME_NATIVE 0 -#define KORE_RUNTIME_PYTHON 1 - -struct kore_runtime { - int type; -#if !defined(KORE_NO_HTTP) - int (*http_request)(void *, struct http_request *); - int (*validator)(void *, struct http_request *, const void *); - void (*wsconnect)(void *, struct connection *); - void (*wsdisconnect)(void *, struct connection *); - void (*wsmessage)(void *, struct connection *, - u_int8_t, const void *, size_t); -#endif - void (*execute)(void *); - int (*onload)(void *, int); - void (*connect)(void *, struct connection *); -}; - -struct kore_runtime_call { - void *addr; - struct kore_runtime *runtime; -}; - -extern struct kore_runtime kore_native_runtime; - -struct listener { - u_int8_t type; - u_int8_t addrtype; - int fd; - struct kore_runtime_call *connect; - - union { - struct sockaddr_in ipv4; - struct sockaddr_in6 ipv6; - } addr; - - LIST_ENTRY(listener) list; -}; - -LIST_HEAD(listener_head, listener); - -#if !defined(KORE_NO_HTTP) - -#define KORE_PARAMS_QUERY_STRING 0x0001 - -struct kore_handler_params { - char *name; - int flags; - u_int8_t method; - struct kore_validator *validator; - - TAILQ_ENTRY(kore_handler_params) list; -}; - -#define KORE_AUTH_TYPE_COOKIE 1 -#define KORE_AUTH_TYPE_HEADER 2 -#define KORE_AUTH_TYPE_REQUEST 3 - -struct kore_auth { - u_int8_t type; - char *name; - char *value; - char *redirect; - struct kore_validator *validator; - - TAILQ_ENTRY(kore_auth) list; -}; - -#define HANDLER_TYPE_STATIC 1 -#define HANDLER_TYPE_DYNAMIC 2 - -#endif /* !KORE_NO_HTTP */ - -#define KORE_MODULE_LOAD 1 -#define KORE_MODULE_UNLOAD 2 - -#define KORE_MODULE_NATIVE 0 -#define KORE_MODULE_PYTHON 1 - -struct kore_module; - -struct kore_module_functions { - void (*free)(struct kore_module *); - void (*reload)(struct kore_module *); - int (*callback)(struct kore_module *, int); - void (*load)(struct kore_module *); - void *(*getsym)(struct kore_module *, const char *); -}; - -struct kore_module { - void *handle; - char *path; - char *onload; - int type; - time_t mtime; - struct kore_runtime_call *ocb; - - struct kore_module_functions *fun; - struct kore_runtime *runtime; - - TAILQ_ENTRY(kore_module) list; -}; - -struct kore_module_handle { - char *path; - char *func; - int type; - int errors; - regex_t rctx; - struct kore_domain *dom; - struct kore_runtime_call *rcall; -#if !defined(KORE_NO_HTTP) - struct kore_auth *auth; - TAILQ_HEAD(, kore_handler_params) params; -#endif - TAILQ_ENTRY(kore_module_handle) list; -}; - -struct kore_worker { - u_int8_t id; - u_int8_t cpu; - pid_t pid; - int pipe[2]; - struct connection *msg[2]; - u_int8_t has_lock; - u_int64_t time_locked; - struct kore_module_handle *active_hdlr; -}; - -struct kore_domain { - char *domain; - int accesslog; -#if !defined(KORE_NO_TLS) - char *cafile; - char *crlfile; - char *certfile; - char *certkey; - SSL_CTX *ssl_ctx; -#endif - TAILQ_HEAD(, kore_module_handle) handlers; - TAILQ_ENTRY(kore_domain) list; -}; - -TAILQ_HEAD(kore_domain_h, kore_domain); - -#if !defined(KORE_NO_HTTP) - -#define KORE_VALIDATOR_TYPE_REGEX 1 -#define KORE_VALIDATOR_TYPE_FUNCTION 2 - -struct kore_validator { - u_int8_t type; - char *name; - char *arg; - regex_t rctx; - struct kore_runtime_call *rcall; - - TAILQ_ENTRY(kore_validator) list; -}; -#endif /* !KORE_NO_HTTP */ - -#define KORE_BUF_OWNER_API 0x0001 - -struct kore_buf { - u_int8_t *data; - int flags; - size_t length; - size_t offset; -}; - -struct kore_pool_region { - void *start; - size_t length; - LIST_ENTRY(kore_pool_region) list; -}; - -struct kore_pool_entry { - u_int8_t state; - struct kore_pool_region *region; - LIST_ENTRY(kore_pool_entry) list; -}; - -struct kore_pool { - size_t elen; - size_t slen; - size_t elms; - size_t inuse; - volatile int lock; - char *name; - - LIST_HEAD(, kore_pool_region) regions; - LIST_HEAD(, kore_pool_entry) freelist; -}; - -struct kore_timer { - u_int64_t nextrun; - u_int64_t interval; - int flags; - void *arg; - void (*cb)(void *, u_int64_t); - - TAILQ_ENTRY(kore_timer) list; -}; - -#define KORE_WORKER_KEYMGR 0 - -/* Reserved message ids, registered on workers. */ -#define KORE_MSG_ACCESSLOG 1 -#define KORE_MSG_WEBSOCKET 2 -#define KORE_MSG_KEYMGR_REQ 3 -#define KORE_MSG_KEYMGR_RESP 4 -#define KORE_MSG_SHUTDOWN 5 -#define KORE_MSG_ENTROPY_REQ 6 -#define KORE_MSG_ENTROPY_RESP 7 - -/* Predefined message targets. */ -#define KORE_MSG_PARENT 1000 -#define KORE_MSG_WORKER_ALL 1001 - -struct kore_msg { - u_int8_t id; - u_int16_t src; - u_int16_t dst; - u_int32_t length; -}; - -#if !defined(KORE_NO_TLS) -struct kore_keyreq { - int padding; - char domain[KORE_DOMAINNAME_LEN]; - u_int8_t domain_len; - u_int16_t data_len; - u_int8_t data[]; -}; -#endif - -#if !defined(KORE_SINGLE_BINARY) -extern char *config_file; -#endif - -extern pid_t kore_pid; -extern int foreground; -extern int kore_debug; -extern int skip_chroot; -extern char *chroot_path; -extern int skip_runas; -extern char *runas_user; -extern char *kore_pidfile; -extern char *kore_tls_cipher_list; -extern int tls_version; - -#if !defined(KORE_NO_TLS) -extern DH *tls_dhparam; -extern char *rand_file; -#endif - -extern u_int8_t nlisteners; -extern u_int16_t cpu_count; -extern u_int8_t worker_count; -extern u_int8_t worker_set_affinity; -extern u_int32_t worker_rlimit_nofiles; -extern u_int32_t worker_max_connections; -extern u_int32_t worker_active_connections; -extern u_int32_t worker_accept_threshold; -extern u_int64_t kore_websocket_maxframe; -extern u_int64_t kore_websocket_timeout; -extern u_int32_t kore_socket_backlog; - -extern struct listener_head listeners; -extern struct kore_worker *worker; -extern struct kore_domain_h domains; -extern struct kore_domain *primary_dom; -extern struct kore_pool nb_pool; - -void kore_signal(int); -void kore_worker_wait(int); -void kore_worker_init(void); -void kore_worker_shutdown(void); -void kore_worker_privdrop(void); -void kore_worker_dispatch_signal(int); -void kore_worker_spawn(u_int16_t, u_int16_t); -void kore_worker_entry(struct kore_worker *); - -struct kore_worker *kore_worker_data(u_int8_t); - -void kore_platform_init(void); -void kore_platform_event_init(void); -void kore_platform_event_cleanup(void); -void kore_platform_proctitle(char *); -void kore_platform_disable_read(int); -void kore_platform_enable_accept(void); -void kore_platform_disable_accept(void); -int kore_platform_event_wait(u_int64_t); -void kore_platform_event_all(int, void *); -void kore_platform_schedule_read(int, void *); -void kore_platform_schedule_write(int, void *); -void kore_platform_event_schedule(int, int, int, void *); -void kore_platform_worker_setcpu(struct kore_worker *); - -void kore_accesslog_init(void); -void kore_accesslog_worker_init(void); -int kore_accesslog_write(const void *, u_int32_t); - -#if !defined(KORE_NO_HTTP) -int kore_auth_run(struct http_request *, struct kore_auth *); -void kore_auth_init(void); -int kore_auth_new(const char *); -struct kore_auth *kore_auth_lookup(const char *); -#endif - -void kore_timer_init(void); -u_int64_t kore_timer_run(u_int64_t); -void kore_timer_remove(struct kore_timer *); -struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t), - u_int64_t, void *, int); - -int kore_sockopt(int, int, int); -void kore_listener_cleanup(void); -int kore_server_bind(const char *, const char *, const char *); -#if !defined(KORE_NO_TLS) -int kore_tls_sni_cb(SSL *, int *, void *); -void kore_tls_info_callback(const SSL *, int, int); -#endif - -void kore_connection_init(void); -void kore_connection_cleanup(void); -void kore_connection_prune(int); -struct connection *kore_connection_new(void *); -int kore_connection_nonblock(int, int); -void kore_connection_check_timeout(u_int64_t); -int kore_connection_handle(struct connection *); -void kore_connection_remove(struct connection *); -void kore_connection_disconnect(struct connection *); -void kore_connection_start_idletimer(struct connection *); -void kore_connection_stop_idletimer(struct connection *); -void kore_connection_check_idletimer(u_int64_t, - struct connection *); -int kore_connection_accept(struct listener *, - struct connection **); - -u_int64_t kore_time_ms(void); -void kore_log_init(void); - -void *kore_malloc(size_t); -void kore_parse_config(void); -void *kore_calloc(size_t, size_t); -void *kore_realloc(void *, size_t); -void kore_free(void *); -void kore_mem_init(void); -void kore_mem_cleanup(void); -void kore_mem_untag(void *); -void *kore_mem_lookup(u_int32_t); -void kore_mem_tag(void *, u_int32_t); -void *kore_malloc_tagged(size_t, u_int32_t); - -void *kore_pool_get(struct kore_pool *); -void kore_pool_put(struct kore_pool *, void *); -void kore_pool_init(struct kore_pool *, const char *, - size_t, size_t); -void kore_pool_cleanup(struct kore_pool *); - -time_t kore_date_to_time(char *); -char *kore_time_to_date(time_t); -char *kore_strdup(const char *); -void kore_log(int, const char *, ...) - __attribute__((format (printf, 2, 3))); -u_int64_t kore_strtonum64(const char *, int, int *); -size_t kore_strlcpy(char *, const char *, const size_t); -void kore_server_disconnect(struct connection *); -int kore_split_string(char *, const char *, char **, size_t); -void kore_strip_chars(char *, const char, char **); -int kore_snprintf(char *, size_t, int *, const char *, ...); -long long kore_strtonum(const char *, int, long long, long long, int *); -int kore_base64_encode(const void *, size_t, char **); -int kore_base64_decode(const char *, u_int8_t **, size_t *); -void *kore_mem_find(void *, size_t, void *, size_t); -char *kore_text_trim(char *, size_t); -char *kore_read_line(FILE *, char *, size_t); - -#if !defined(KORE_NO_HTTP) -void kore_websocket_handshake(struct http_request *, - const char *, const char *, const char *); -void kore_websocket_send(struct connection *, - u_int8_t, const void *, size_t); -void kore_websocket_broadcast(struct connection *, - u_int8_t, const void *, size_t, int); -#endif - -void kore_msg_init(void); -void kore_msg_worker_init(void); -void kore_msg_parent_init(void); -void kore_msg_parent_add(struct kore_worker *); -void kore_msg_parent_remove(struct kore_worker *); -void kore_msg_send(u_int16_t, u_int8_t, const void *, u_int32_t); -int kore_msg_register(u_int8_t, - void (*cb)(struct kore_msg *, const void *)); - -void kore_domain_init(void); -void kore_domain_cleanup(void); -int kore_domain_new(char *); -void kore_domain_free(struct kore_domain *); -void kore_module_init(void); -void kore_module_cleanup(void); -void kore_module_reload(int); -void kore_module_onload(void); -int kore_module_loaded(void); -void kore_domain_closelogs(void); -void *kore_module_getsym(const char *, struct kore_runtime **); -void kore_domain_load_crl(void); -void kore_domain_keymgr_init(void); -void kore_domain_tlsinit(struct kore_domain *); -void kore_module_load(const char *, const char *, int); -void kore_domain_callback(void (*cb)(struct kore_domain *)); -int kore_module_handler_new(const char *, const char *, - const char *, const char *, int); -void kore_module_handler_free(struct kore_module_handle *); - -struct kore_runtime_call *kore_runtime_getcall(const char *); - -void kore_runtime_execute(struct kore_runtime_call *); -int kore_runtime_onload(struct kore_runtime_call *, int); -void kore_runtime_connect(struct kore_runtime_call *, struct connection *); -#if !defined(KORE_NO_HTTP) -int kore_runtime_http_request(struct kore_runtime_call *, - struct http_request *); -int kore_runtime_validator(struct kore_runtime_call *, - struct http_request *, const void *); -void kore_runtime_wsconnect(struct kore_runtime_call *, struct connection *); -void kore_runtime_wsdisconnect(struct kore_runtime_call *, - struct connection *); -void kore_runtime_wsmessage(struct kore_runtime_call *, - struct connection *, u_int8_t, const void *, size_t); -#endif - -struct kore_domain *kore_domain_lookup(const char *); -struct kore_module_handle *kore_module_handler_find(const char *, - const char *); - -#if !defined(KORE_NO_HTTP) -void kore_validator_init(void); -void kore_validator_reload(void); -int kore_validator_add(const char *, u_int8_t, const char *); -int kore_validator_run(struct http_request *, const char *, char *); -int kore_validator_check(struct http_request *, - struct kore_validator *, const void *); -struct kore_validator *kore_validator_lookup(const char *); -#endif - -void fatal(const char *, ...) __attribute__((noreturn)); -void kore_debug_internal(char *, int, const char *, ...); - -u_int16_t net_read16(u_int8_t *); -u_int32_t net_read32(u_int8_t *); -u_int64_t net_read64(u_int8_t *); -void net_write16(u_int8_t *, u_int16_t); -void net_write32(u_int8_t *, u_int32_t); -void net_write64(u_int8_t *, u_int64_t); - -void net_init(void); -void net_cleanup(void); -int net_send(struct connection *); -int net_send_flush(struct connection *); -int net_recv_flush(struct connection *); -int net_read(struct connection *, size_t *); -int net_read_tls(struct connection *, size_t *); -int net_write(struct connection *, size_t, size_t *); -int net_write_tls(struct connection *, size_t, size_t *); -void net_recv_reset(struct connection *, size_t, - int (*cb)(struct netbuf *)); -void net_remove_netbuf(struct netbuf_head *, struct netbuf *); -void net_recv_queue(struct connection *, size_t, int, - int (*cb)(struct netbuf *)); -void net_recv_expand(struct connection *c, size_t, - int (*cb)(struct netbuf *)); -void net_send_queue(struct connection *, const void *, size_t); -void net_send_stream(struct connection *, void *, - size_t, int (*cb)(struct netbuf *), struct netbuf **); - -void kore_buf_free(struct kore_buf *); -struct kore_buf *kore_buf_alloc(size_t); -void kore_buf_init(struct kore_buf *, size_t); -void kore_buf_append(struct kore_buf *, const void *, size_t); -u_int8_t *kore_buf_release(struct kore_buf *, size_t *); -void kore_buf_reset(struct kore_buf *); -void kore_buf_cleanup(struct kore_buf *); - -char *kore_buf_stringify(struct kore_buf *, size_t *); -void kore_buf_appendf(struct kore_buf *, const char *, ...); -void kore_buf_appendv(struct kore_buf *, const char *, va_list); -void kore_buf_replace_string(struct kore_buf *, char *, void *, size_t); - -void kore_keymgr_run(void); -void kore_keymgr_cleanup(void); - -void kore_parent_configure(void); -void kore_worker_configure(void); - -#if defined(__cplusplus) -} -#endif - -#endif /* !__H_KORE_H */ diff --git a/includes/pgsql.h b/includes/pgsql.h @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2014-2018 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _H_KORE_PGSQL -#define _H_KORE_PGSQL - -#include <libpq-fe.h> - -#define KORE_PGSQL_FORMAT_TEXT 0 -#define KORE_PGSQL_FORMAT_BINARY 1 - -#define KORE_PGSQL_SYNC 0x0001 -#define KORE_PGSQL_ASYNC 0x0002 -#define KORE_PGSQL_SCHEDULED 0x0004 - -#if defined(__cplusplus) -extern "C" { -#endif - -struct pgsql_conn { - u_int8_t type; - u_int8_t flags; - char *name; - - PGconn *db; - struct pgsql_job *job; - TAILQ_ENTRY(pgsql_conn) list; -}; - -struct pgsql_db { - char *name; - char *conn_string; - u_int16_t conn_max; - u_int16_t conn_count; - - LIST_ENTRY(pgsql_db) rlist; -}; - -struct kore_pgsql { - u_int8_t state; - int flags; - char *error; - PGresult *result; - struct pgsql_conn *conn; - - struct http_request *req; - void *arg; - void (*cb)(struct kore_pgsql *, void *); - - LIST_ENTRY(kore_pgsql) rlist; -}; - -extern u_int16_t pgsql_conn_max; -extern u_int32_t pgsql_queue_limit; - -void kore_pgsql_sys_init(void); -void kore_pgsql_sys_cleanup(void); -void kore_pgsql_init(struct kore_pgsql *); -void kore_pgsql_bind_request(struct kore_pgsql *, struct http_request *); -void kore_pgsql_bind_callback(struct kore_pgsql *, - void (*cb)(struct kore_pgsql *, void *), void *); -int kore_pgsql_setup(struct kore_pgsql *, const char *, int); -void kore_pgsql_handle(void *, int); -void kore_pgsql_cleanup(struct kore_pgsql *); -void kore_pgsql_continue(struct kore_pgsql *); -int kore_pgsql_query(struct kore_pgsql *, const char *); -int kore_pgsql_query_params(struct kore_pgsql *, - const char *, int, int, ...); -int kore_pgsql_v_query_params(struct kore_pgsql *, - const char *, int, int, va_list); -int kore_pgsql_register(const char *, const char *); -int kore_pgsql_ntuples(struct kore_pgsql *); -int kore_pgsql_nfields(struct kore_pgsql *); -void kore_pgsql_logerror(struct kore_pgsql *); -char *kore_pgsql_fieldname(struct kore_pgsql *, int); -char *kore_pgsql_getvalue(struct kore_pgsql *, int, int); -int kore_pgsql_getlength(struct kore_pgsql *, int, int); - -#if defined(__cplusplus) -} -#endif - -#define KORE_PGSQL_STATE_INIT 1 -#define KORE_PGSQL_STATE_WAIT 2 -#define KORE_PGSQL_STATE_RESULT 3 -#define KORE_PGSQL_STATE_ERROR 4 -#define KORE_PGSQL_STATE_DONE 5 -#define KORE_PGSQL_STATE_COMPLETE 6 - -#endif diff --git a/includes/python_api.h b/includes/python_api.h @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2016 Stanislav Yudin <stan@endlessinsomnia.com> - * Copyright (c) 2017-2018 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __H_PYTHON_H -#define __H_PYTHON_H - -#undef _POSIX_C_SOURCE -#undef _XOPEN_SOURCE - -#include <Python.h> - -void kore_python_init(void); -void kore_python_cleanup(void); -void kore_python_path(const char *); - -PyObject *kore_python_callable(PyObject *, const char *); - -extern struct kore_module_functions kore_python_module; -extern struct kore_runtime kore_python_runtime; - -#endif diff --git a/includes/python_methods.h b/includes/python_methods.h @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2017-2018 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -static PyObject *python_kore_log(PyObject *, PyObject *); -static PyObject *python_kore_fatal(PyObject *, PyObject *); -static PyObject *python_kore_listen(PyObject *, PyObject *); - -#if defined(KORE_USE_PGSQL) -static PyObject *python_kore_pgsql_register(PyObject *, PyObject *); -#endif - -static PyObject *python_websocket_broadcast(PyObject *, PyObject *); - -#define METHOD(n, c, a) { n, (PyCFunction)c, a, NULL } -#define GETTER(n, g) { n, (getter)g, NULL, NULL, NULL } -#define SETTER(n, s) { n, NULL, (setter)g, NULL, NULL } -#define GETSET(n, g, s) { n, (getter)g, (setter)s, NULL, NULL } - -static struct PyMethodDef pykore_methods[] = { - METHOD("log", python_kore_log, METH_VARARGS), - METHOD("fatal", python_kore_fatal, METH_VARARGS), - METHOD("listen", python_kore_listen, METH_VARARGS), - METHOD("websocket_broadcast", python_websocket_broadcast, METH_VARARGS), -#if defined(KORE_USE_PGSQL) - METHOD("register_database", python_kore_pgsql_register, METH_VARARGS), -#endif - { NULL, NULL, 0, NULL } -}; - -static struct PyModuleDef pykore_module = { - PyModuleDef_HEAD_INIT, "kore", NULL, -1, pykore_methods -}; - -struct pyconnection { - PyObject_HEAD - struct connection *c; -}; - -static PyObject *pyconnection_disconnect(struct pyconnection *, PyObject *); -static PyObject *pyconnection_websocket_send(struct pyconnection *, PyObject *); - -static PyMethodDef pyconnection_methods[] = { - METHOD("disconnect", pyconnection_disconnect, METH_NOARGS), - METHOD("websocket_send", pyconnection_websocket_send, METH_VARARGS), - METHOD(NULL, NULL, -1), -}; - -static PyObject *pyconnection_get_fd(struct pyconnection *, void *); -static PyObject *pyconnection_get_addr(struct pyconnection *, void *); - -static PyGetSetDef pyconnection_getset[] = { - GETTER("fd", pyconnection_get_fd), - GETTER("addr", pyconnection_get_addr), - GETTER(NULL, NULL), -}; - -static void pyconnection_dealloc(struct pyconnection *); - -static PyTypeObject pyconnection_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "kore.connection", - .tp_doc = "struct connection", - .tp_getset = pyconnection_getset, - .tp_methods = pyconnection_methods, - .tp_basicsize = sizeof(struct pyconnection), - .tp_dealloc = (destructor)pyconnection_dealloc, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, -}; - -struct pyhttp_request { - PyObject_HEAD - struct http_request *req; - PyObject *data; -}; - -struct pyhttp_file { - PyObject_HEAD - struct http_file *file; -}; - -static void pyhttp_dealloc(struct pyhttp_request *); -static void pyhttp_file_dealloc(struct pyhttp_file *); - -#if defined(KORE_USE_PGSQL) -static PyObject *pyhttp_pgsql(struct pyhttp_request *, PyObject *); -#endif -static PyObject *pyhttp_cookie(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_response(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_argument(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_body_read(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_file_lookup(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_populate_get(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_populate_post(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_populate_multi(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_populate_cookies(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_request_header(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_response_header(struct pyhttp_request *, PyObject *); -static PyObject *pyhttp_websocket_handshake(struct pyhttp_request *, - PyObject *); - -static PyMethodDef pyhttp_request_methods[] = { -#if defined(KORE_USE_PGSQL) - METHOD("pgsql", pyhttp_pgsql, METH_VARARGS), -#endif - METHOD("cookie", pyhttp_cookie, METH_VARARGS), - METHOD("response", pyhttp_response, METH_VARARGS), - METHOD("argument", pyhttp_argument, METH_VARARGS), - METHOD("body_read", pyhttp_body_read, METH_VARARGS), - METHOD("file_lookup", pyhttp_file_lookup, METH_VARARGS), - METHOD("populate_get", pyhttp_populate_get, METH_NOARGS), - METHOD("populate_post", pyhttp_populate_post, METH_NOARGS), - METHOD("populate_multi", pyhttp_populate_multi, METH_NOARGS), - METHOD("populate_cookies", pyhttp_populate_cookies, METH_NOARGS), - METHOD("request_header", pyhttp_request_header, METH_VARARGS), - METHOD("response_header", pyhttp_response_header, METH_VARARGS), - METHOD("websocket_handshake", pyhttp_websocket_handshake, METH_VARARGS), - METHOD(NULL, NULL, -1) -}; - -static PyObject *pyhttp_get_host(struct pyhttp_request *, void *); -static PyObject *pyhttp_get_path(struct pyhttp_request *, void *); -static PyObject *pyhttp_get_body(struct pyhttp_request *, void *); -static PyObject *pyhttp_get_agent(struct pyhttp_request *, void *); -static PyObject *pyhttp_get_method(struct pyhttp_request *, void *); -static PyObject *pyhttp_get_body_path(struct pyhttp_request *, void *); -static PyObject *pyhttp_get_connection(struct pyhttp_request *, void *); - -static PyGetSetDef pyhttp_request_getset[] = { - GETTER("host", pyhttp_get_host), - GETTER("path", pyhttp_get_path), - GETTER("body", pyhttp_get_body), - GETTER("agent", pyhttp_get_agent), - GETTER("method", pyhttp_get_method), - GETTER("body_path", pyhttp_get_body_path), - GETTER("connection", pyhttp_get_connection), - GETTER(NULL, NULL) -}; - -static PyTypeObject pyhttp_request_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "kore.http_request", - .tp_doc = "struct http_request", - .tp_getset = pyhttp_request_getset, - .tp_methods = pyhttp_request_methods, - .tp_dealloc = (destructor)pyhttp_dealloc, - .tp_basicsize = sizeof(struct pyhttp_request), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, -}; - -static PyObject *pyhttp_file_read(struct pyhttp_file *, PyObject *); - -static PyMethodDef pyhttp_file_methods[] = { - METHOD("read", pyhttp_file_read, METH_VARARGS), - METHOD(NULL, NULL, -1) -}; - -static PyObject *pyhttp_file_get_name(struct pyhttp_file *, void *); -static PyObject *pyhttp_file_get_filename(struct pyhttp_file *, void *); - -static PyGetSetDef pyhttp_file_getset[] = { - GETTER("name", pyhttp_file_get_name), - GETTER("filename", pyhttp_file_get_filename), - GETTER(NULL, NULL) -}; - -static PyTypeObject pyhttp_file_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "kore.http_file", - .tp_doc = "struct http_file", - .tp_getset = pyhttp_file_getset, - .tp_methods = pyhttp_file_methods, - .tp_dealloc = (destructor)pyhttp_file_dealloc, - .tp_basicsize = sizeof(struct pyhttp_file), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, -}; - -#if defined(KORE_USE_PGSQL) - -#define PYKORE_PGSQL_PREINIT 1 -#define PYKORE_PGSQL_INITIALIZE 2 -#define PYKORE_PGSQL_QUERY 3 -#define PYKORE_PGSQL_WAIT 4 - -struct pykore_pgsql { - PyObject_HEAD - int state; - char *db; - char *query; - struct http_request *req; - PyObject *result; - struct kore_pgsql sql; -}; - -static void pykore_pgsql_dealloc(struct pykore_pgsql *); -int pykore_pgsql_result(struct pykore_pgsql *); - -static PyObject *pykore_pgsql_await(PyObject *); -static PyObject *pykore_pgsql_iternext(struct pykore_pgsql *); - -static PyAsyncMethods pykore_pgsql_async = { - (unaryfunc)pykore_pgsql_await, - NULL, - NULL -}; - -static PyTypeObject pykore_pgsql_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "kore.pgsql", - .tp_doc = "struct kore_pgsql", - .tp_as_async = &pykore_pgsql_async, - .tp_iternext = (iternextfunc)pykore_pgsql_iternext, - .tp_basicsize = sizeof(struct pykore_pgsql), - .tp_dealloc = (destructor)pykore_pgsql_dealloc, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, -}; -#endif diff --git a/includes/tasks.h b/includes/tasks.h @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2014 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __H_KORE_TASKS -#define __H_KORE_TASKS - -#include <pthread.h> - -#define KORE_TASK_STATE_CREATED 1 -#define KORE_TASK_STATE_RUNNING 2 -#define KORE_TASK_STATE_FINISHED 3 -#define KORE_TASK_STATE_ABORT 4 - -#define KORE_TASK_THREADS 2 - -#if defined(__cplusplus) -extern "C" { -#endif - -#if !defined(KORE_NO_HTTP) -struct http_request; -#endif - -struct kore_task { - u_int8_t type; - int state; - int result; - pthread_rwlock_t lock; - -#if !defined(KORE_NO_HTTP) - struct http_request *req; -#endif - - int fds[2]; - int (*entry)(struct kore_task *); - void (*cb)(struct kore_task *); - - struct kore_task_thread *thread; - - TAILQ_ENTRY(kore_task) list; - LIST_ENTRY(kore_task) rlist; -}; - -struct kore_task_thread { - u_int8_t idx; - pthread_t tid; - pthread_mutex_t lock; - pthread_cond_t cond; - TAILQ_HEAD(, kore_task) tasks; - - TAILQ_ENTRY(kore_task_thread) list; -}; - -void kore_task_init(void); -void kore_task_run(struct kore_task *); -void kore_task_finish(struct kore_task *); -void kore_task_destroy(struct kore_task *); -int kore_task_finished(struct kore_task *); -void kore_task_handle(struct kore_task *, int); - -#if !defined(KORE_NO_HTTP) -void kore_task_bind_request(struct kore_task *, - struct http_request *); -#endif -void kore_task_bind_callback(struct kore_task *, - void (*cb)(struct kore_task *)); -void kore_task_create(struct kore_task *, - int (*entry)(struct kore_task *)); - -u_int32_t kore_task_channel_read(struct kore_task *, void *, u_int32_t); -void kore_task_channel_write(struct kore_task *, void *, u_int32_t); - -void kore_task_set_state(struct kore_task *, int); -void kore_task_set_result(struct kore_task *, int); - -int kore_task_state(struct kore_task *); -int kore_task_result(struct kore_task *); - -extern u_int16_t kore_task_threads; - -#if defined(__cplusplus) -} -#endif - -#endif