Move away from the parent constantly hitting the disk for every
accesslog the workers are sending.
The workers will now write their own accesslogs to shared
memory before the parent will pick those up. The parent
will flush them to disk once every second or if they grow
larger then 1MB.
This removes the heavy penalty for having access logs
turned on when you are dealing with a large volume
of requests.
This commit removes TLS 1.0 support no matter what OpenSSL
you are linking against.
Changes the value of tls_version from 1.2 to both. Meaning if
you link with OpenSSL 1.1.1 you will get 1.2 + 1.3.
This adds kore.proc to the python runtime allowing async processing
handling:
The kore.proc method takes the command to run and an optional timeout
parameter in milliseconds. If the process did not exit normally after
that amount of time a TimeoutError exception is raised.
For instance:
async def run(cmd):
proc = kore.proc(cmd, 1000)
try:
await proc.send("hello")
proc.close_stdin()
except TimeoutError:
proc.kill()
retcode = await proc.reap()
return retcode
If exists these functions are called when the worker is exiting
and when right before the parent exists.
Allows for cleanup code for applications if need to do cleanup on exit.
This means you can now do things like:
resp = await koresock.recv(1024)
await koresock.send(resp)
directly from page handlers if they are defined as async.
Adds lots more to the python goo such as fatalx(), bind_unix(),
task_create() and socket_wrap().
Now anyone can schedule events and get a callback to work as long
as the user data structure that is added for the event begins
with a kore_event data structure.
All event state is now kept in that kore_event structure and renamed
CONN_[READ|WRITE]_POSSIBLE to KORE_EVENT_[READ|WRITE].
This commit introduces the ability for the keymgr process
to reload the certificates/keys for domains when receiving
a SIGUSR1 signal.
The keymgr receives 2 new configuration options:
- keymgr_root_path
The root path where the keymgr will live.
If -n is not specified when the application starts the
keymgr process will chroot into here.
- keymgr_runas_user
The user the keymgr will drop privileges towards if
-r was not specified.
All certfile and certkey configuration options are now relative to the
keymgr_root_path configuration setting.
The keymgr process will now also load the certificate for the domain
(rather then the workers) and submit these to the worker processes so
they can be reloaded when required.
Worker processes will refuse connections until the TLS configuration
for a given domain is completed (aka: the workers receive the certificate
for that domain).
Other changes:
- client_certificates renamed to client_verify.
- the chroot configuration option is now called root.
- kore is a little more verbose if privsep options are missing.
- filemaps are now relative to the root configuration option.
A filemap is a way of telling Kore to serve files from a directory
much like a traditional webserver can do.
Kore filemaps only handles files. Kore does not generate directory
indexes or deal with non-regular files.
The way files are sent to a client differs a bit per platform and
build options:
default:
- mmap() backed file transfer due to TLS.
NOTLS=1
- sendfile() under FreeBSD, macOS and Linux.
- mmap() backed file for OpenBSD.
The opened file descriptors/mmap'd regions are cached and reused when
appropriate. If a file is no longer in use it will be closed and evicted
from the cache after 30 seconds.
New API's are available allowing developers to use these facilities via:
void net_send_fileref(struct connection *, struct kore_fileref *);
void http_response_fileref(struct http_request *, struct kore_fileref *);
Kore will attempt to match media types based on file extensions. A few
default types are built-in. Others can be added via the new "http_media_type"
configuration directive.
This function now takes any remaining arguments passed on the command line
after kore parsed its own.
For C the new prototype looks like this:
void kore_parent_configure(int argc, char **argv);
For python code, kore will pass each argument to the function so you
can do things like:
def kore_parent_configure(arg1, arg2):
doing this allows us to get rid of the validator reload
and handler reload as well as fixing websocket runtime
callbacks which were never being resolved upon module reloads.
Having the create, build, run tools baked into the kore binary
made things harder then they had to be for multiple projects with
each different build flavors.
So move away this functionality into a new "kodev" (name may change)
binary that is installed next to kore.
The new build tools will automatically pick up the correct flavors
the kore binary it points to is installed with. Or for single builds
what flavors where enabled.
The new tool also will honor looking into PREFIX for the kore binary
when doing a `kodev run`.
Additionally add a new command "info" that shows some basic info
about your project and how it will be built. For example it will
show you the flavors of the kore binary installed on the system
or the flavors you configured for a single binary build.
Obligitory, hacking on a plane comment.
This commit adds the ability to use python "await" to suspend
execution of your page handler until the query sent to postgresql
has returned a result.
This is built upon the existing asynchrous query framework Kore had.
With this you can now write stuff like:
async def page(req):
result = await req.pgsql("db", "SELECT name FROM table");
req.response(200, json.dumps(result).encode("utf-8"))
The above code will fire off a query and suspend itself so Kore can
take care of business as usual until the query is successful at which
point Kore will jump back into the handler and resume.
This does not use threading, it's purely based on Python's excellent
coroutines and generators and Kore its built-in pgsql support.
Renamed both of them:
kore_preload -> kore_parent_configure
kore_onload -> kore_worker_configure
These functions will now always be called if they are defined in any module
regardless of your application being built as a single binary or not.
- Change pools to use mmap() for allocating regions.
- Change kore_malloc() to use pools for commonly sized objects.
(split into multiple of 2 buckets, starting at 8 bytes up to 8192).
- Rename kore_mem_free() to kore_free().
The preallocated pools will hold up to 128K of elements per block size.
In case a larger object is to be allocated kore_malloc() will use
malloc() instead.
Producing single binaries can now be done with building with
"kore build". To get started edit your build.conf and add the
following directives:
single_binary = yes
kore_source = /path/to/kore
optionally you can add kore_flavor to instruct how kore should
be built:
kore_flavor = NOTLS=1
When doing this your build.conf must also include the correct
linking options as the linking is now done fully by kore build.
The binary produced will include your configuration and takes
over a few of kore its command line flags (such as -f, -n or -r).
Kore will now isolate RSA private keys to a separate process (keymgr).
Worker processes that require RSA signing for TLS connections will
communicate with this keymgr process in order to do so.
This behaviour cannot be disabled and is always turned on.
- Build with -O2 unless NOOPT is set to 1.
- Hide -g behind DEBUG instead of always building with it.
- Explicitely set the standard used to c99, use pedantic.
This commit is a flag day, your old modules will almost certainly
need to be updated in order to build properly with these changes.
Summary of changes:
- Offload HTTP bodies to disk if they are large (inspired by #100).
(disabled by default)
- The http_argument_get* macros now takes an explicit http_request parameter.
- Kore will now throw 404 errors almost immediately after an HTTP request
has come in instead of waiting until all data has arrived.
API changes:
- http_argument_get* macros now require an explicit http_request parameter.
(no more magic invokations).
- http_generic_404() is gone
- http_populate_arguments() is gone
- http_body_bytes() is gone
- http_body_text() is gone
- http_body_read() has been added
- http_populate_post() has been added
- http_populate_get() has been added
- http_file_read() has been added
- http_file_rewind() has been added
- http_file_lookup() no longer takes name, fname, data and len parameters.
- http_file_lookup() now returns a struct http_file pointer.
- http_populate_multipart_form() no longer takes an secondary parameter.
New configuration options:
- http_body_disk_offload:
Number of bytes after which Kore will offload the HTTP body to
disk instead of retaining it in memory. If 0 this feature is
disabled. (Default: 0)
- http_body_disk_path:
The path where Kore will store temporary HTTP body files.
(this directory does not get created if http_body_disk_offload is 0).
New example:
The upload example has been added, demonstrating how to deal with file
uploads from a multipart form.
This basically turns off the HTTP layer for Kore. It does not
compile in anything for HTTP.
This allows Kore to be used as a network application platform as well.
Added an example for this called nohttp.
Other changes that sneaked in while hacking on this:
* Use calloc(), kill pendantic malloc option.
* Killed off SPDY/3.1 support completely, will be superseded by http2
Note that comes with massive changes to a lot of the core API
functions provided by Kore, these might break your application.
Change the callback prototypes to:
void callback(struct kore_msg *msg, const void *data);
This allows the callbacks to receive the full kore_msg data structure
as sent over the wire (including length and id). Useful for future
additions to the kore_msg structure (such as worker origin).
Several other improvements:
* Accesslog now uses the msg framework as well.
* Websocket WEBSOCKET_BROADCAST_GLOBAL now works.
Small websocket improvement in this commit:
* Build the frame to be sent only once when broadcasting
instead of per connection we are broadcasting towards.
With this framework apps can now send messages between worker processes.
A new API function exists:
int kore_msg_register(u_int8_t id, void (*cb)(const void *, u_int32_t);
This API call allows your app to register a new message callback for a given ID.
You can then send messages on this ID to other workers using:
void kore_msg_send(u_int8_t id, void *data, u_int32_t length);
This framework will interally be used for a few things such as allowing
websocket data to broadcasted between all workers, adding unified caching
and hopefully eventually moving the access log to this as well.
Some internals have changed with this commit:
* worker_clients has been called connections.
* the parent now initializes the net, and event subsystems.
* kore_worker_websocket_broadcast() is dead.
Add new command line knob '-r', that disables runas similar to '-n',
it's implied as well for kore command runs.
Add default runas (nobody) user and chroot (/var/empty) path, if none
are specified, fallback to these.
Add configuration setting tls_version to specify if you
either want TLSv1.2 or TLSv1.0 or both.
The configuration options ssl_cipher and ssl_dhparam
have changed name to tls_cipher and tls_dhparam. There is
no fallback so you might have to update your configs.
Introduces two new configuration knobs:
* socket_backlog (backlog for listen(2))
* http_request_limit
The second one is the most interesting one.
Before, kore would iterate over all received HTTP requests
in its queue before returning out of http_process().
Under heavy load this queue can cause Kore to spend a considerable
amount of time iterating over said queue. With the http_request_limit,
kore will process at MOST http_request_limit requests before returning
back to the event loop.
This means responses to processed requests are sent out much quicker
and allows kore to handle any other incoming requests more gracefully.
After revisiting why this exists in Kore I decided it
does not belong in this platform and instead of letting
it sit there staring at me I rather just kill it.
Makes more sense and reads easier:
kore create myapp
kore build myapp
kore run myapp
Note that kore retains its cli options (if no command was given),
meaning you can still start kore in the traditional way as well.
The command options are simply to make development easier.
Personally use this for testing Kore its performance without
letting the OpenSSL stack get in the way too much.
Note that it leaves data structures as is, and just removes
any calls to OpenSSL (and removes the linking vs OpenSSL).
When running in -f (foreground) you can now specify
the library Kore needs to load on the command line:
kore -fnc module.conf myapp.so
This has the benefit that your configuration file no
longer needs the load directive when hacking on your code.
Note that you can still specify load in your config file
regardless, if you so chose.
All of this is being done in order to try and move away
from the backwards way of getting up and running with Kore.
Using authentication blocks one can define "authentication" mechanisms
in Kore for page handlers.
This can be used to require a session cookie (validated by your own validator)
for certain page handlers, and hopefully in the future provide a framework
for adding more authentication things (like HTTP Auth).
Right now only cookie checking is available.