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 d9bbb0b1f1ca89d172318e90eb9867b3328b3c69
parent a074258dcc0f7693c5a0abe75e0ff4035d5ba300
Author: Joris Vink <joris@coders.se>
Date:   Wed,  1 May 2013 16:03:48 +0200

initial module support

Diffstat:
Makefile | 3++-
example.conf | 12++++++++++++
includes/kore.h | 21+++++++++++++++++++++
src/http.c | 22+++++-----------------
src/kore.c | 16++++++++++++----
src/module.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/utils.c | 33+++++++++++++++++++++++++++++++++
7 files changed, 186 insertions(+), 22 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,7 +3,8 @@ CC=gcc BIN=kore -S_SRC= src/kore.c src/net.c src/spdy.c src/http.c src/utils.c src/zlib_dict.c +S_SRC= src/kore.c src/config.c src/net.c src/spdy.c src/http.c \ + src/module.c src/utils.c src/zlib_dict.c S_OBJS= $(S_SRC:.c=.o) CFLAGS+=-I/usr/local/ssl/include diff --git a/example.conf b/example.conf @@ -0,0 +1,12 @@ +# Example Kore configuration + +# Server configuration. +bind 10.211.55.3 443 + +# Load our site module now (containing all the goodies). +load ../betrippin/betrippin.module + +# Declare page handlers below. +# handler path module_callback +static /css/style.css betrippin_serve_style_css +static / betrippin_serve_index diff --git a/includes/kore.h b/includes/kore.h @@ -78,12 +78,33 @@ struct connection { TAILQ_HEAD(, spdy_stream) spdy_streams; }; +#define HANDLER_TYPE_STATIC 1 +#define HANDLER_TYPE_DYNAMIC 2 + +struct kore_module_handle { + char *uri; + void *func; + int type; + + TAILQ_ENTRY(kore_module_handle) list; +}; + +extern int server_port; +extern char *server_ip; + void *kore_malloc(size_t); void *kore_calloc(size_t, size_t); void *kore_realloc(void *, size_t); char *kore_strdup(const char *); +void kore_parse_config(const char *); void kore_strlcpy(char *, const char *, size_t); void kore_server_disconnect(struct connection *); +long long kore_strtonum(const char *, long long, long long, int *); + +void kore_module_load(char *); +int kore_module_loaded(void); +void *kore_module_handler_find(char *); +int kore_module_handler_new(char *, char *, int); void fatal(const char *, ...); void kore_log_internal(char *, int, const char *, ...); diff --git a/src/http.c b/src/http.c @@ -39,7 +39,6 @@ TAILQ_HEAD(, http_request) http_requests; -static int http_generic_cb(struct http_request *); static int http_generic_404(struct http_request *); void @@ -125,7 +124,8 @@ http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len) void http_process(void) { - struct http_request *req, *next; + struct http_request *req, *next; + int (*handler)(struct http_request *); if (TAILQ_EMPTY(&http_requests)) return; @@ -134,12 +134,12 @@ http_process(void) for (req = TAILQ_FIRST(&http_requests); req != NULL; req = next) { next = TAILQ_NEXT(req, list); - /* XXX - add module hooks here */ - if (!strcmp(req->path, "/favicon.ico")) { + handler = kore_module_handler_find(req->path); + if (handler == NULL) { if (!http_generic_404(req)) kore_server_disconnect(req->owner); } else { - if (!http_generic_cb(req)) + if (!handler(req)) kore_server_disconnect(req->owner); } @@ -150,18 +150,6 @@ http_process(void) } static int -http_generic_cb(struct http_request *req) -{ - u_int32_t len; - - kore_log("http_generic_cb(%s, %s, %s)", - req->host, req->method, req->path); - - len = strlen("<p>Hello world</p>"); - return (http_response(req, 200, (u_int8_t *)"<p>Hello world</p>", len)); -} - -static int http_generic_404(struct http_request *req) { kore_log("http_generic_404(%s, %s, %s)", diff --git a/src/kore.c b/src/kore.c @@ -42,6 +42,8 @@ static int efd = -1; static SSL_CTX *ssl_ctx = NULL; +int server_port = 0; +char *server_ip = NULL; static int kore_socket_nonblock(int); static int kore_server_sslstart(void); @@ -59,11 +61,17 @@ main(int argc, char *argv[]) struct epoll_event *events; int n, i, *fd; - if (argc != 3) - fatal("Usage: kore [ip] [port]"); + if (argc != 2) + fatal("Usage: kore [config file]"); - if (!kore_server_bind(&server, argv[1], atoi(argv[2]))) - fatal("cannot bind to %s:%s", argv[1], argv[2]); + kore_parse_config(argv[1]); + if (!kore_module_loaded()) + fatal("no site module was loaded"); + + if (server_ip == NULL || server_port == 0) + fatal("missing a correct bind directive in configuration"); + if (!kore_server_bind(&server, server_ip, server_port)) + fatal("cannot bind to %s:%d", server_ip, server_port); if (!kore_server_sslstart()) fatal("cannot initiate SSL"); diff --git a/src/module.c b/src/module.c @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/queue.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <openssl/err.h> +#include <openssl/ssl.h> + +#include <ctype.h> +#include <dlfcn.h> +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <zlib.h> + +#include "spdy.h" +#include "kore.h" + +static void *mod_handle = NULL; +static time_t mod_last_mtime = 0; + +static TAILQ_HEAD(, kore_module_handle) handlers; + +void +kore_module_load(char *module_name) +{ + struct stat st; + + kore_log("kore_module_load(%s)", module_name); + + if (mod_handle != NULL) + fatal("site module already loaded, skipping %s", module_name); + + if (stat(module_name, &st) == -1) + fatal("stat(%s): %s", module_name, errno_s); + + mod_last_mtime = st.st_mtime; + mod_handle = dlopen(module_name, RTLD_NOW); + if (mod_handle == NULL) + fatal("dlopen(%s) failed", module_name); + + TAILQ_INIT(&handlers); +} + +int +kore_module_loaded(void) +{ + return (mod_handle != NULL ? KORE_RESULT_OK : KORE_RESULT_ERROR); +} + +int +kore_module_handler_new(char *uri, char *func, int type) +{ + void *addr; + struct kore_module_handle *hdlr; + + kore_log("kore_module_handler_new(%s, %s, %d)", uri, func, type); + + addr = dlsym(mod_handle, func); + if (addr == NULL) { + kore_log("function '%s' not found", func); + return (KORE_RESULT_ERROR); + } + + hdlr = (struct kore_module_handle *)kore_malloc(sizeof(*hdlr)); + hdlr->uri = kore_strdup(uri); + hdlr->func = addr; + hdlr->type = type; + TAILQ_INSERT_TAIL(&(handlers), hdlr, list); + + return (KORE_RESULT_OK); +} + +void * +kore_module_handler_find(char *uri) +{ + return (NULL); +} diff --git a/src/utils.c b/src/utils.c @@ -107,6 +107,39 @@ kore_strlcpy(char *dst, const char *src, size_t len) } } +long long +kore_strtonum(const char *str, long long min, long long max, int *err) +{ + long long l; + char *ep; + + if (min > max) { + *err = KORE_RESULT_ERROR; + return (0); + } + + l = 0; + errno = 0; + l = strtoll(str, &ep, 10); + if (errno != 0 || str == ep || *ep != '\0') { + *err = KORE_RESULT_ERROR; + return (0); + } + + if (l < min) { + *err = KORE_RESULT_ERROR; + return (0); + } + + if (l > max) { + *err = KORE_RESULT_ERROR; + return (0); + } + + *err = KORE_RESULT_OK; + return (l); +} + void fatal(const char *fmt, ...) {