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 160eb791f7217e5626d080405efd2cca1f35ebf7
parent b234b7ed655db9c220bbf3fb2aa3ee60bfde4c31
Author: Joris Vink <joris@coders.se>
Date:   Thu,  2 Apr 2015 13:20:01 +0200

Merge pull request #37 from Geenz/master

Allow modules to use C++.
Diffstat:
examples/cpp/.gitignore | 5+++++
examples/cpp/README.md | 30++++++++++++++++++++++++++++++
examples/cpp/conf/cpp.conf | 11+++++++++++
examples/cpp/dh2048.pem | 9+++++++++
examples/cpp/src/cpp.cpp | 33+++++++++++++++++++++++++++++++++
examples/cpp/src/example_class.cpp | 30++++++++++++++++++++++++++++++
examples/cpp/src/example_class.h | 32++++++++++++++++++++++++++++++++
includes/http.h | 8+++++++-
includes/kore.h | 8++++++++
includes/pgsql.h | 8++++++++
includes/spdy.h | 7+++++++
includes/tasks.h | 8++++++++
src/cli.c | 68+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
13 files changed, 241 insertions(+), 16 deletions(-)

diff --git a/examples/cpp/.gitignore b/examples/cpp/.gitignore @@ -0,0 +1,5 @@ +*.o +.objs +cpp.so +assets.h +cert diff --git a/examples/cpp/README.md b/examples/cpp/README.md @@ -0,0 +1,30 @@ +Kore example showing how to use C++ support! + +All functions accessible to kore must have their prototypes wrapped with the extern keyword like so: +``` +extern ā€œCā€ { + int pageA(struct http_request *); + int pageB(struct http_request *); + int validatorA(struct http_request *, char *); +} +``` + +You will also need to compile kore with the KORE_CPP_SUPPORT environment variable enabled: +``` + # env KORE_CPP_SUPPORT=1 make +``` + +In order to run this example with the default C++ settings (default compiler dialect, libstdc++): +``` + # kore run +``` + +In order to run with a specific dialect and C++ runtime: +``` + # env CXXSTD=c++11 CXXLIB=c++ kore run +``` + +You can also supply your own compiler combined with the above: +``` + # env CXX=clang++ CXXSTD=c++11 CXXLIB=c++ kore run +``` diff --git a/examples/cpp/conf/cpp.conf b/examples/cpp/conf/cpp.conf @@ -0,0 +1,11 @@ +# Placeholder configuration + +bind 127.0.0.1 8888 +load ./cpp.so +ssl_dhparam dh2048.pem + +domain 127.0.0.1 { + certfile cert/server.crt + certkey cert/server.key + static / page +} diff --git a/examples/cpp/dh2048.pem b/examples/cpp/dh2048.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv +VKVT7jO8c4msSNikUf6eEfoH0H4VTCaj+Habwu+Sj+I416r3mliMD4SjNsUJrBrY +Y0QV3ZUgZz4A8ARk/WwQcRl8+ZXJz34IaLwAcpyNhoV46iHVxW0ty8ND0U4DIku/ +PNayKimu4BXWXk4RfwNVP59t8DQKqjshZ4fDnbotskmSZ+e+FHrd+Kvrq/WButvV +Bzy9fYgnUlJ82g/bziCI83R2xAdtH014fR63MpElkqdNeChb94pPbEdFlNUvYIBN +xx2vTUQMqRbB4UdG2zuzzr5j98HDdblQ+wIBAg== +-----END DH PARAMETERS-----+ \ No newline at end of file diff --git a/examples/cpp/src/cpp.cpp b/examples/cpp/src/cpp.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015 Jonathan Goodman <geenz@geenzo.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. + */ + +#include <kore/kore.h> +#include <kore/http.h> + +#include "example_class.h" + +extern "C" { + int page(struct http_request *); +} + +int +page(struct http_request *req) +{ + example_class example; + const char* str = example.a(); + http_response(req, 200, static_cast<void*>(const_cast<char*>(str)), strlen(str)); + return (KORE_RESULT_OK); +} diff --git a/examples/cpp/src/example_class.cpp b/examples/cpp/src/example_class.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Jonathan Goodman <geenz@geenzo.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. + */ + +#include "example_class.h" + +example_class::example_class() { + +} + +example_class::~example_class() { + +} + +const char* +example_class::a() { + return "Hello world!"; +} diff --git a/examples/cpp/src/example_class.h b/examples/cpp/src/example_class.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Jonathan Goodman <geenz@geenzo.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. + */ + +#ifndef ____example_class__ +#define ____example_class__ + +#include <stdio.h> + +class example_class { + +public: + example_class(); + ~example_class(); + + const char* + a(); +}; + +#endif /* defined(____example_class__) */ diff --git a/includes/http.h b/includes/http.h @@ -17,6 +17,10 @@ #ifndef __H_HTTP_H #define __H_HTTP_H +#if defined(__cplusplus) +extern "C" { +#endif + #define HTTP_KEEPALIVE_TIME 20 #define HTTP_HSTS_ENABLE 31536000 #define HTTP_HEADER_MAX_LEN 4096 @@ -283,5 +287,7 @@ enum http_status_code { HTTP_STATUS_GATEWAY_TIMEOUT = 504, HTTP_STATUS_BAD_VERSION = 505 }; - +#if defined(__cplusplus) +} +#endif #endif /* !__H_HTTP_H */ diff --git a/includes/kore.h b/includes/kore.h @@ -37,6 +37,10 @@ #include <unistd.h> #include <zlib.h> +#if defined(__cplusplus) +extern "C" { +#endif + #if defined(__APPLE__) #undef daemon extern int daemon(int, int); @@ -547,4 +551,8 @@ void spdy_stream_close(struct connection *, struct spdy_header_block *spdy_header_block_create(int); +#if defined(__cplusplus) +} +#endif + #endif /* !__H_KORE_H */ diff --git a/includes/pgsql.h b/includes/pgsql.h @@ -22,6 +22,10 @@ #define KORE_PGSQL_FORMAT_TEXT 0 #define KORE_PGSQL_FORMAT_BINARY 1 +#if defined(__cplusplus) +extern "C" { +#endif + struct pgsql_conn { u_int8_t type; u_int8_t flags; @@ -58,6 +62,10 @@ void kore_pgsql_queue_remove(struct http_request *); 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 diff --git a/includes/spdy.h b/includes/spdy.h @@ -20,6 +20,9 @@ #include <sys/types.h> #include <sys/queue.h> +#if defined(__cplusplus) +extern "C" { +#endif struct spdy_ctrl_frame { u_int16_t version; u_int16_t type; @@ -65,6 +68,10 @@ struct spdy_stream { }; extern const unsigned char SPDY_dictionary_txt[]; + +#if defined(__cplusplus) +} +#endif #define KORE_SSL_PROTO_STRING "\x08spdy/3.1\x08http/1.1" #define SPDY_CONTROL_FRAME(x) ((x & (1 << 31))) diff --git a/includes/tasks.h b/includes/tasks.h @@ -24,6 +24,10 @@ #define KORE_TASK_STATE_FINISHED 3 #define KORE_TASK_STATE_ABORT 4 +#if defined(__cplusplus) +extern "C" { +#endif + struct http_request; struct kore_task { @@ -72,5 +76,9 @@ void kore_task_set_result(struct kore_task *, int); int kore_task_state(struct kore_task *); int kore_task_result(struct kore_task *); + +#if defined(__cplusplus) +} +#endif #endif diff --git a/src/cli.c b/src/cli.c @@ -69,7 +69,8 @@ struct filegen { struct cfile { struct stat st; - int build; + int build; + int cpp; char *name; char *fpath; char *opath; @@ -103,7 +104,7 @@ static int cli_file_requires_build(struct stat *, const char *); static void cli_find_files(const char *, void (*cb)(char *, struct dirent *)); static void cli_add_cfile(char *, char *, char *, - struct stat *, int); + struct stat *, int, int); static void cli_run(int, char **); static void cli_help(int, char **); @@ -189,6 +190,7 @@ static int s_fd = -1; static char *appl = NULL; static char *rootdir = NULL; static char *compiler = "gcc"; +static char *cppcompiler = "g++"; static struct cfile_list source_files; static int cfiles_count; static struct cmd *command = NULL; @@ -300,6 +302,9 @@ cli_build(int argc, char **argv) if ((p = getenv("CC")) != NULL) compiler = p; + + if ((p = getenv("CXX")) != NULL) + cppcompiler = p; cfiles_count = 0; TAILQ_INIT(&source_files); @@ -336,6 +341,7 @@ cli_build(int argc, char **argv) /* Build all source files. */ cli_find_files(src_path, cli_register_cfile); + free(src_path); requires_relink = 0; @@ -603,8 +609,8 @@ cli_build_asset(char *fpath, struct dirent *dp) *(ext)++ = '\0'; cli_write_asset(name, ext); *ext = '_'; - - cli_add_cfile(name, cpath, opath, &st, 0); + + cli_add_cfile(name, cpath, opath, &st, 0, 0); kore_mem_free(name); return; } @@ -663,12 +669,12 @@ cli_build_asset(char *fpath, struct dirent *dp) *--ext = '.'; /* Register the .c file now (cpath is free'd later). */ - cli_add_cfile(name, cpath, opath, &st, 1); + cli_add_cfile(name, cpath, opath, &st, 1, 0); kore_mem_free(name); } static void -cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, int build) +cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, int build, int cpp) { struct cfile *cf; @@ -677,6 +683,7 @@ cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, int build) cf->st = *st; cf->build = build; + cf->cpp = cpp; cf->fpath = fpath; cf->opath = opath; cf->name = kore_strdup(name); @@ -689,20 +696,26 @@ cli_register_cfile(char *fpath, struct dirent *dp) { struct stat st; char *ext, *opath; + int cpp; - if ((ext = strrchr(fpath, '.')) == NULL || strcmp(ext, ".c")) + if ((ext = strrchr(fpath, '.')) == NULL || !(!strcmp(ext, ".c") || !strcmp(ext, ".cpp"))) return; + + if (!strcmp(ext, ".cpp")) + cpp = 1; + else + cpp = 0; if (stat(fpath, &st) == -1) cli_fatal("stat(%s): %s", fpath, errno_s); (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, dp->d_name); if (!cli_file_requires_build(&st, opath)) { - cli_add_cfile(dp->d_name, fpath, opath, &st, 0); + cli_add_cfile(dp->d_name, fpath, opath, &st, 0, cpp); return; } - - cli_add_cfile(dp->d_name, fpath, opath, &st, 1); + + cli_add_cfile(dp->d_name, fpath, opath, &st, 1, cpp); } static void @@ -847,7 +860,7 @@ cli_compile_cfile(void *arg) { int idx; struct cfile *cf = arg; - char *args[20], *ipath[2]; + char *args[24], *ipath[2], *cppdialect; #if defined(KORE_USE_PGSQL) char *ppath; #endif @@ -885,13 +898,29 @@ cli_compile_cfile(void *arg) args[idx++] = "-fPIC"; args[idx++] = "-g"; + if (cf->cpp) { + + args[idx++] = "-Woverloaded-virtual"; + args[idx++] = "-Wold-style-cast"; + args[idx++] = "-Wnon-virtual-dtor"; + + if ((cppdialect = getenv("CXXSTD")) != NULL) { + char *cppstandard = NULL; + (void)cli_vasprintf(&cppstandard, "-std=%s", cppdialect); + args[idx++] = cppstandard; + } + } + args[idx++] = "-c"; args[idx++] = cf->fpath; args[idx++] = "-o"; args[idx++] = cf->opath; args[idx] = NULL; - - execvp(compiler, args); + + if (cf->cpp) + execvp(cppcompiler, args); + else + execvp(compiler, args); } static void @@ -900,7 +929,8 @@ cli_link_library(void *arg) struct cfile *cf; int idx, f, i; char *p, *libname, *flags[LD_FLAGS_MAX]; - char *args[cfiles_count + 10 + LD_FLAGS_MAX]; + char *args[cfiles_count + 11 + LD_FLAGS_MAX]; + char *cpplib; if ((p = getenv("LDFLAGS")) != NULL) f = kore_split_string(p, " ", flags, LD_FLAGS_MAX); @@ -923,7 +953,15 @@ cli_link_library(void *arg) TAILQ_FOREACH(cf, &source_files, list) args[idx++] = cf->opath; - + + if ((cpplib = getenv("CXXLIB")) != NULL) { + char *cpplibrary = NULL; + (void)cli_vasprintf(&cpplibrary, "-l%s", cpplib); + args[idx++] = cpplibrary; + } else { + args[idx++] = "-lstdc++"; + } + for (i = 0; i < f; i++) args[idx++] = flags[i];