123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- // SPDX-License-Identifier: GPL-2.0 or GPL-3.0
- // Copyright © 2018-2019 Ariadne Devos
- /* shttpd - functions for workers */
- /* # High-level architecture
- There are multiple processes.
- In a process, there are multiple workers.
- Each worker has its own file descriptor table.
- This table can have the following format:
- 0: unix socket (control lifecycle)
- 1: /dev/null (for now)
- 2: /dev/null (for now)
- 3: epollfd
- ???: asynchronous IO?
- ...: accept sockets, read/write sockets, open files,
- connections to external services ...
- The unix socket is for controlling when the worker should stop.
- The worker polls for changes in file descriptor readyness and reacts
- to those and asynchronous IO events.
- Everything is mutually distrusting.
- # Seperation of knowledge
- Use case: a HTTPS server. A HTTPS server conceptually is TLS encryption
- after a HTTP server encrypted connections. The HTTP code and TLS code
- (or even HTTPS code and encryption and signing) can live in different
- workers or processes.
- TODO: an intra-shttpd communication system (passing around and transcribing
- paper).
- # Paper
- A character buffer that can be passed around.
- # The control thread
- - Control thread creates worker.
- - Control thread -> asks worker to perform apoptosis
- - Control thread -> sends tasks to worker
- - Control thread -> asks tasks from worker -> sends tasks to control thread
- - Worker thread -> reports hard errors to control thread
- - Kernel -> notifies worker -> asks kernel to do stuff
- */
- #include <stddef.h>
- #include <stdint.h>
- #include <sys/epoll.h>
- /* Don't change this group! control.c relies upon these values. */
- #define sHT_FD_CONTROL 0
- #define sHT_FD_STDOUT 1
- #define sHT_FD_STDERR 2
- /* Only for sHT_start_worker. Points to a worker executable. */
- #define sHT_FD_WORKEREXE 4
- #include <sHT/paper.h>
- #include <sHT/task.h>
- #include <sHT/taskset.h>
- #include <sHT/scheduling.h>
- typedef unsigned int sHT_worker_flags;
- #define sHT_WORKER_OOM 1
- #define sHT_WORKER_LIMIT_TASKS 2
- #define sHT_WORKER_LIMIT_PAPER 4
- #define sHT_WORKER_LIMIT_WATCHES 8
- /* file descriptor */
- #define sHT_WORKER_LIMIT_FDS 16
- /* file descriptor */
- #define sHT_WORKER_SYSTEM_FDS 32
- struct sHT_objcache;
- struct sHT_worker
- {
- struct sHT_objcache *papers;
- /* Use sHT_deschedule_rr, sHT_schedule_rr */
- struct sHT_taskset todo;
- struct sHT_objcache *free_streams;
- /* length: todo->n */
- struct epoll_event *epoll_events;
- /* indexed by fd, length: todo->capacity */
- struct sHT_task *tasks;
- /* The control thread is notified if any is set. */
- sHT_worker_flags flags;
- sHT_watch_set watches;
- };
- /* epoll_wait(2) returned n events. Schedule corresponding tasks, setting
- task->epollflags.
- @var{n} must be less than SSIZE_MAX. */
- __attribute__((nonnull (1)))
- void
- sHT_schedule_events(struct sHT_worker *worker, size_t n);
- /* _logic$ is defined by worker-specific code */
- __attribute__((nonnull (1, 2)))
- void
- sHT_diy_logic(struct sHT_worker *worker, struct sHT_task *task);
- __attribute__((nonnull (1, 2)))
- void
- sHT_aio_logic(struct sHT_worker *worker, struct sHT_task *task);
- /* Send information about resource utilisation to the control thread.
- More specifically,
- send and clear task->flags.
- Doesn't allocate any resources.
- (May be extended) */
- __attribute__((nonnull (1, 2)))
- void
- sHT_sendstatus_task(struct sHT_worker *worker, struct sHT_task *task);
- /* Perform the IO actions of worker->io_type.
- Then, call sHT_diy_logic, sHT_socket_logic, sHT_aio_logic or
- sHT_accept_logic, depending on the io type.
- task must reschedule itself if it:
- - it has some things to do, even if no IO is possible
- */
- __attribute__((nonnull (1, 2)))
- void
- sHT_perform_task(struct sHT_worker *worker, struct sHT_task *task);
- __attribute__((nonnull (1)))
- _Noreturn void
- sHT_worker(struct sHT_worker *worker);
|