Remove obsolete documentation.

This commit is contained in:
Jordan Bancino 2023-04-29 18:47:20 +00:00
parent e0c94d7bd2
commit a08018870e
23 changed files with 0 additions and 2710 deletions

View File

@ -1,132 +0,0 @@
.Dd $Mdocdate: November 24 2022 $
.Dt ARRAY 3
.Os Telodendria Project
.Sh NAME
.Nm Array
.Nd A simple dynamic array data structure.
.Sh SYNOPSIS
.In Array.h
.Ft Array *
.Fn ArrayCreate "void"
.Ft void
.Fn ArrayFree "Array *"
.Ft int
.Fn ArrayTrim "Array *"
.Ft size_t
.Fn ArraySize "Array *"
.Ft void *
.Fn ArrayGet "Array *" "size_t"
.Ft int
.Fn ArrayInsert "Array *" "void *" "size_t"
.Ft int
.Fn ArrayAdd "Array *" "void *"
.Ft void *
.Fn ArrayDelete "Array *" "size_t"
.Ft void
.Fn ArraySort "Array *" "int (*) (void *, void *)"
.Ft Array *
.Fn ArrayFromVarArgs "size_t" "va_list"
.Ft Array *
.Fn ArrayDuplicate "Array *"
.Sh DESCRIPTION
These functions implement a simple array data structure that
is automatically resized as necessary when new values are added.
This implementation does not actually store the values of the
items in it; it only stores pointers to the data. As such, you will
still have to manually maintain all your data. The advantage of this
is that these functions don't have to copy data, and thus don't care
how big the data is. Furthermore, arbitrary data can be stored in the
array.
.Pp
This array implementation is optimized for storage space and appending.
Deletions are expensive in that all the items of the list above a deletion
are moved down to fill the hole where the deletion occurred. Insertions are
also expensive in that all the elements above the given index must be shifted
up to make room for the new element.
.Pp
Due to these design choices, this array implementation is best suited to
linear writing, and then linear or random reading.
.Pp
These functions operate on an array structure which is opaque to the
caller.
.Pp
.Fn ArrayCreate
and
.Fn ArrayFree
allocate and deallocate an array, respectively.
Note that
.Fn ArrayFree
does not free any of the values stored in the array; it is the caller's
job to manage the memory for each item. Typically, the caller would
iterate over all the items in the array and free them before freeing
the array.
.Fn ArrayTrim
reduces the amount of unused memory by calling
.Xr realloc 3
on the internal structure to perfectly fit the elements in the array. It
is intended to be used by functions that return relatively read-only arrays
that will be long-lived.
.Pp
.Fn ArrayInsert
and
.Fn ArrayDelete
are the main functions used to modify the array.
.Fn ArrayAdd
is a convenience method that simply appends a value to the end of the
array. It uses
.Fn ArrayInsert .
The array can also be sorted by using
.Fn ArraySort ,
which takes a pointer to a function that compares elements. The function
should take two
.Dv void
pointers as parameters, and return an integer. The return value indicates
to the algorithm how the elements relate to each other. A return value of
0 indicates the elements are identical. A return value greater than 0
indicates that the first item is "bigger" than the second item and should
thus appear after it in the array, and a value less than zero indicates
the opposite: the second element should appear after the first in the array.
.Pp
.Fn ArrayGet
is used to get the element at the specified index.
.Pp
.Fn ArrayFromVarArgs
is used to convert a variadic arguments list into an Array. In many
cases, the Array API is much easier to work with than
.Fn va_arg
and friends.
.Pp
.Fn ArrayDuplicate
duplicates an existing array. Note that Arrays only hold
pointers to data, not the data itself, so the duplicated array will
point to the same places in memory as the original array.
.Sh RETURN VALUES
.Fn ArrayCreate ,
.Fn ArrayFromVarArgs ,
and
.Fn ArrayDuplicate
return a pointer on the heap to a newly allocated array structure, or
.Dv NULL
if the allocation fails.
.Pp
.Fn ArrayGet
and
.Fn ArrayDelete
return pointers to values that were put into the array, or
.Dv NULL
if the provided array is
.Dv NULL
or the provided index was out of bounds.
.Fn ArrayDelete
returns the element at the specified index after removing it so that
it can be properly handled by the caller.
.Pp
.Fn ArrayTrim ,
.Fn ArrayInsert ,
and
.Fn ArrayAdd
return a boolean value indicating their status. They return a value of zero
on failure, and a non-zero value on success.
.Sh SEE ALSO
.Xr HashMap 3 ,
.Xr Queue 3

View File

@ -1,81 +0,0 @@
.Dd $Mdocdate: September 30 2022 $
.Dt BASE64 3
.Os Telodendria Project
.Sh NAME
.Nm Base64
.Nd A simple base64 encoder/decoder with "unpadded base64" support.
.Sh SYNOPSIS
.In Base64.h
.Ft size_t
.Fn Base64EncodedSize "size_t"
.Ft size_t
.Fn Base64DecodedSize "const char *" "size_t"
.Ft char *
.Fn Base64Encode "const char *" "size_t"
.Ft char *
.Fn Base64Decode "const char *" "size_t"
.Ft void
.Fn Base64Unpad "char *" "size_t"
.Ft int
.Fn Base64Pad "char **" "size_t"
.Sh DESCRIPTION
This is an efficient yet simple base64 encoding and decoding
library that supports regular base64, as well as the Matrix
specification's extension to base64, called "unpadded base64."
.Nm provides the ability to convert between the two, instead of
just implementing "unpadded base64."
.Pp
.Fn Base64EncodedSize
and
.Fn Base64DecodedSize
compute the amount of characters needed to store an encoded or
decoded message, respectively. Both functions take the size of
the message being encoded or decoded, but
.Fn Base64DecodedSize
also takes a pointer to an encoded string, because a few bytes of
the string need to be read in order to compute the size.
.Pp
.Fn Base64Encode
and
.Fn Base64Decode
do the actual work of encoding and decoding base64 data. They both
take a string and its length.
.Pp
.Fn Base64Unpad
and
.Fn Base64Pad
are used to implement Matrix unpadded base64.
.Fn Base64Unpad
takes a valid base64 string and strips off the trailing equal signs,
as per the specification.
.Fn Base64Pad
does the opposite; it takes an unpadded base64 input string, and pads
it with equal signs as necessary, so that it can be properly decoded
with
.Fn Base64Decode
if necessary. However, the Matrix specification envisons unpadded base64
as opaque; that is, once it's encoded, it never needs to be decoded.
In practice, a homeserver might need to decode an unpadded base64 string.
.Sh RETURN VALUES
.Fn Base64EncodedSize
and
.Fn Base64DecodedSize
simply return unsigned integers representing a number of bytes generated
from a simple computation.
.Pp
.Fn Base64Encode
and
.Fn Base64Decode
return pointers to new strings, allocated on the heap, or
.Dv NULL
if a heap allocation fails. These pointers must be
.Xr free 3 -ed
at some point when they are no longer needed.
.Pp
.Fn Base64Unpad
modifies the passed string in-place. It thus has no return value, because
it cannot fail. If the passed pointer is invalid, the behavior is undefined.
.Fn Base64Pad
returns a boolean value indicating whether the pad operation was successful.
In practice, this function will only fail if a bigger string is necessary, but
could not be automatically allocated on the heap.

View File

@ -1,69 +0,0 @@
.Dd $Mdocdate: November 30 2022 $
.Dt CANONICALJSON 3
.Os Telodendria Project
.Sh NAME
.Nm CanonicalJson
.Nd An extension of JSON that produces the Matrix spec's "canonical" JSON.
.Sh SYNOPSIS
.In CanonicalJson.h
.Ft int
.Fn CanonicalJsonEncode "HashMap *" "FILE *"
.Ft char *
.Fn CanonicalJsonEncodeToString "HashMap *"
.Sh DESCRIPTION
.Pp
.Nm
is an extension of
.Xr Json 3
that is specifically designed to produce the Matrix specification's
"canonical" JSON.
.Pp
Canonical JSON is defined as JSON that:
.Bl -bullet -offset indent
.It
Does not have any unecessary whitespace.
.It
Has all object keys lexicographically sorted.
.It
Does not contain any floating point numerical values.
.El
.Pp
The regular JSON encoder has no such rules, because normally they are
not needed. However, Canonical JSON is needed to consistently sign JSON
objects.
.Pp
.Fn CanonicalJsonEncode
encodes a JSON object following the rules of Canonical Json. See the
documentation for
.Fn JsonEncode ,
documented in
.Xr Json 3
for more details on how JSON encoding operates. This function exists
as an alternative to
.Fn JsonEncode ,
but should not be preferred to it in most circumstances. It is a lot
more costly, as it must lexicographically sort all keys and strip out
float values. If at all possible, use
.Fn JsonEncode
because it is much cheaper both in terms of memory and CPU time.
.Pp
.Fn CanonicalJsonEncodeToString
encodes a JSON object to a string.
.Xr Json 3
doesn't have any way to send JSON to a string, because there's
absolutely no reason to handle JSON strings in most cases. However,
the sole reason Canonical JSON exists is so that JSON objects can
be signed in a consistent way. Thus, you need a string to pass to
the signing function.
.Sh RETURN VALUES
.Pp
.Fn CanonicalJsonEncode
returns whether or not the JSON encoding operation was sucessful.
This function will fail only if NULL was given for any parameter.
Otherwise, if an invalid pointer is given, undefined behavior results.
.Pp
.Fn CanonicalJsonEncodeToString
returns a C string containing the canonical JSON representation of
the given object, or NULL if the encoding failed.
.Sh SEE ALSO
.Xr Json 3

View File

@ -1,96 +0,0 @@
.Dd $Mdocdate: December 24 2022 $
.Dt CRON 3
.Os Telodendria Project
.Sh NAME
.Nm Cron
.Nd Basic periodic job scheduler.
.Sh SYNOPSIS
.In Cron.h
.Ft Cron *
.Fn CronCreate "unsigned long"
.Ft void
.Fn CronOnce "Cron *" "void (*) (void *)" "void *"
.Ft void
.Fn CronEvery "Cron *" "unsigned long" "void (*) (void *)" "void *"
.Ft void
.Fn CronStart "Cron *"
.Ft void
.Fn CronStop "Cron *"
.Ft void
.Fn CronFree "Cron *"
.Sh DESCRIPTION
.Pp
.Nm
is an extremely basic job scheduler. So basic, in fact,
that it runs all jobs on a single thread, which means that it
is intended for short-lived jobs. In the future,
.Nm
might be extended to support a one-thread-per-job model, but
for now, jobs should consider that they are sharing their
thread, so they should not be long-running jobs.
.Pp
.Nm
works by "ticking" at an interval defined by the caller of
.Fn CronCreate .
At each tick, all the jobs are queried, and if they are due
to run again, their function is executed. As much as possible,
.Nm
tries to tick at constant intervals, however it is possible that
a job may overrun the tick duration. If this happens,
.Nm
ticks again immediately after all the jobs for the previous tick
have completed. This is in an effort to compensate for the lost
time, however it is important to note that when jobs overrun the
tick interval, the interval is pushed back. In this way,
.Nm
is best suited for scheduling jobs that should happen
"approximately" every so often; it is not a real-time scheduler
by any means.
.Pp
.Fn CronCreate
creates a new
.Nm
object that all the other functions use. Like most of the other
APIs in this project, it must be freed with
.Fn CronFree
when it is no longer needed.
.Pp
Jobs can be scheduled with
.Fn CronOnce
and
.Fn CronEvery .
.Fn CronOnce
schedules a one-off job to be executed only at the next tick, and
then discarded. This is useful for scheduling tasks that only have
to happen once, or very infrequently depending on conditions other
than the current time, but don't have to happen immediately. The
caller simply indicates that it wishes for the task to execute at
some time in the future. How far into the future this practically
ends up being is determined by how long it takes other jobs to
finish, and what the tick interval is.
.Pp
.Fn CronEvery
schedules a repetitive task to be executed at approximately the
given interval. As stated above, this is a fuzzy interval; depending
on the jobs being run and the tick interval, tasks may not happen
at exactly the scheduled time, but they will eventually happen.
.Pp
.Fn CronStart
and
.Fn CronStop
start and stop the ticking, respectively.
.Fn CronFree
discards all the job references and frees all memory associated
with the given instance of the
.Nm
instance.
.Sh RETURN VALUES
.Pp
.Fn CronCreate
returns a reference to a
.Nm ,
or NULL if it was unable to allocate memory for it.
.Pp
The other functions in this header don't return anything. They
are assumed to usually work, unless their input is obviously
wrong.

View File

@ -1,121 +0,0 @@
.Dd $Mdocdate: March 6 2023 $
.Dt DB 3
.Os Telodendria Project
.Sh NAME
.Nm Db
.Nd A minimal flat-file database with object locking and an efficient cache.
.Sh SYNOPSIS
.In Db.h
.Ft Db *
.Fn DbOpen "char *" "size_t"
.Ft void
.Fn DbClose "Db *"
.Ft DbRef *
.Fn DbCreate "Db *" "size_t" "..."
.Ft int
.Fn DbDelete "Db *" "size_t" "..."
.Ft DbRef *
.Fn DbLock "Db *" "size_t" "..."
.Ft int
.Fn DbUnlock "Db *" "DbRef *"
.Ft int
.Fn DbExists "Db *" "size_t" "..."
.Ft Array *
.Fn DbList "Db *" "size_t" "..."
.Ft void
.Fn DbListFree "Array *"
.Ft HashMap *
.Fn DbJson "DbRef *"
.Sh DESCRIPTION
.Pp
Telodendria operates on a flat-file database instead of a traditional relational
database. This greatly simplifies the persistent storage code, and creates a
relatively basic API, described by this page.
.Pp
.Fn DbOpen
and
.Fn DbClose
open and close a data directory.
.Fn DbOpen
takes the path to open, and a cache size in bytes. This API relies heavily on
caching, so the cache must be greater than the DB_MIN_CACHE preprocessor
constant.
.Pp
.Fn DbCreate
and
.Fn DbLock
load data objects from the database, with the notable difference being that
.Fn DbCreate
will fail if an object already exists, and
.Fn DbLock
will fail if an object does not exist. These are both variadic functions that
take a variable number of C strings, with the exact number being specified by
the second paramter. These C strings are used to generate a filesystem path from
which an object is loaded, unless it is already in the cache.
.Pp
Objects, when loaded, are locked both in memory and on disk, so that other threads
or processes cannot access them while they are locked. This is to ensure data
integrity.
.Pp
.Fn DbUnlock
unlocks an object and returns it back to the database, which syncs it to the
filesystem and caches it, if it isn't in the cache already.
.Pp
.Fn DbExists
checks the existence of the given database object in a more efficient
manner than attempting to lock it with
.Fn DbLock .
.Fn DbExists
does not lock the object, nor does it load it into memory if it exists. It
takes the same arguments as
.Fn DbLock
and
.Fn DbUnlock .
.Pp
.Fn DbJson
converts a database reference into JSON. At this time, the database actually
stores objects as JSON, so this just returns an internal pointer, but in the
future it may have to be generated by decompressing a binary blob, or something
of that nature.
.Pp
.Fn DbDelete
completely removes an object from the database. It purges it from both the
cache and the disk as soon as no more references to it are open.
.Pp
.Fn DbList
lists all of the objects at a given path. Unlike the other varargs
functions, it does not take a path to a specific object; it takes
a directory to be iterated. Note that the resulting list only contains
the objects in that directory, not subdirectories.
.Fn DbListFree
frees the list returned by this function.
.Sh RETURN VALUES
.Pp
.Fn DbOpen
returns a reference to a database pointer, or NULL if there was an error
allocating memory, or opening the given directory with the given cache size.
.Pp
.Fn DbCreate
and
.Fn DbLock
return a database reference, or NULL if there was an error obtaining a reference
to the specified object.
.Pp
.Fn DbUnlock
returns a boolean value indicating whether or not the reference was successfully
unlocked. If the unlock is successful, then a non-zero value is returned. If it
isn't, 0 is returned, and it is up to the caller to decide how to proceed.
.Pp
.Fn DbDelete
follows the same return value conventions as
.Fn DbUnlock ;
it reports the status of the deletion operation as a boolean value.
.Pp
.Fn DbList
returns an array of strings, or NULL if there was a memory or
filesystem error.
.Pp
.Fn DbJson
returns a JSON object. Consult
.Xr Json 3
for the API used to manipulate this object.

View File

@ -1,146 +0,0 @@
.Dd $Mdocdate: October 11 2022 $
.Dt HASHMAP 3
.Os Telodendria Project
.Sh NAME
.Nm HashMap
.Nd A simple hash map implementation.
.Sh SYNOPSIS
.In HashMap.h
.Ft HashMap *
.Fn HashMapCreate "void"
.Ft void
.Fn HashMapFree "HashMap *"
.Ft void
.Fn HashMapLoadSet "HashMap *" "float"
.Ft void
.Fn HashMapFunctionSet "HashMap *" "unsigned long (*) (const char *)"
.Ft void *
.Fn HashMapSet "HashMap *" "char *" "void *"
.Ft void *
.Fn HashMapGet "HashMap *" "char *"
.Ft void *
.Fn HashMapDelete "HashMap *" "char *"
.Ft int
.Fn HashMapIterate "HashMap *" "char **" "void **"
.Sh DESCRIPTION
This is the public interface for Telodendria's hash map implementation.
This hash map is designed to be simple, well documented, and generally
readable and understandable, yet also performant enough to be useful,
because it is used extensively in Telodendria.
.Pp
Fundamentally, this is an entirely generic map implementation. It can
be used for many general purposes, but it is designed to only implement
the features that Telodendria needs to function well. One example of a
Telodendria-specific feature is that keys are
.Dv NULL -terminated
strings, not any arbitrary data.
.Pp
These functions operate on an opaque
.Dv HashMap
structure, which the caller has no knowledge about.
.Pp
.Fn HashMapCreate
creates a new hash map that is ready to be used with the rest of the
hash map functions.
.Fn HashMapFree
frees this hash map, such that it becomes invalid and any future use
with the functions in this API results in undefined behavior. Note that
it does not free the keys or values stored in the hash map, since this
implementation has no way of knowing what is actually stored in it, and
where it is located. You should use
.Fn HashMapIterate
to free the values appropriately.
.Pp
.Fn HashMapMaxLoadSet
controls the maximum load of the hash map before it is expanded.
When the hash map reaches the given capacity, it is grown. You don't
want to only grow hash maps when they are full, because that makes
them perform very poorly. The maximum load value is a percentage of how
full the hash map is, and it should be between 0
and 1, where 0 means that no elements will cause the map to be expanded,
and 1 means that the hash map must be completely full before it is
expanded. The default maximum load on a new
.Dv HashMap
object is 0.75, which should be good enough for most purposes, but
if you need finer tuning, feel free to play with the max load with
this function. The changes take effect on the next insert.
.Pp
.Fn HashMapFunctionSet
allows the given hash map to use a custom hashing function. New hash
maps have a sane hashing function that should work okay for most use
cases, but if you have a better hash function, it can be specified with
this function. Do not change the hash function after keys have been
added; doing so results in undefined behavior. Only set the hash
function immediately after constructing a new hash map.
.Pp
.Fn HashMapSet
sets the given string key to the given value. Note neither the key nor the
value is copied into the hash map's own memory space; only pointers are
stored. It is the caller's job to ensure that the key and value memory
remains valid for the life of the HashMap, and are freed when they are no
longer needed.
.Fn HashMapGet
retrieves the value for the given key and .Fn HashMapDelete
removes a value from a given key.
.Pp
.Fn HashMapIterate
iterates over all the keys and values of a hash map. This function works
very similarly to
.Xr getopt 3 ,
where calls are repeatedly made in a
.Dv while
loop until there are no more items to go over. The difference is that this
function does not rely on globals; it takes pointer pointers, and stores all
necessary state inside the hash map structure itself. Note that this does not
make this function thread-safe; two threads cannot be iterating over any given
hash map at the same time, though they can be iterating over different hash
maps at the same time.
.Pp
This function can be tricky to use in some scenarios, as it continues where
it left off on each call, until there are no more elements to go through in
the hash map. If you are not iterating over the entire map in one go, and
happen to break the loop, then the next time you attempt to iterate the
hash map, you'll start somewhere in the middle. Thus, it's recommended to
always iterate over the entire hash map if you're going to use this
function. Also note that the behavior of this function is undefined if
insertions or deletions occur during the iteration. It may work fine; it may
not. That functionality has not been tested.
.Pp
.Fn HashMapIterate
takes a pointer to a string ponter, and a pointer to a value pointer. When
iterating over the keys and values of the hash map, it sets these pointers
to the current position in the map so that the caller can use them for his
own purposes.
.Sh RETURN VALUES
.Fn HashMapCreate
may return
.Dv NULL
if memory could not be allocated on the heap. Otherwise, it returns a
valid pointer to a
.Dv HashMap
structure which can be used with the other functions in this API.
.Pp
.Fn HashMapSet
returns the previous value at the passed key, or
.Dv NULL
if no such value exists. All keys must have values; you can't set a key
to
.Dv NULL .
To delete a key, use the
.Fn HashMapDelete
function.
.Pp
.Fn HashMapDelete
returns the value that was deleted from the hash map at the given key,
or
.Dv NULL
if no such value exists.
.Pp
.Fn HashMapIterate
returns 1 if there are still elements left in the current iteration of the
hash map, or 0 if no valid hash map was provided, or there are no more elements
in it for the current iteration. Note that as soon as this function returns 0
on a hash map, subsequent iterations will start from the beginning.
.Sh SEE ALSO
.Xr HashMap 3 ,
.Xr Queue 3

View File

@ -1,186 +0,0 @@
.Dd $Mdocdate: March 12 2023 $
.Dt HTTP 3
.Os Telodendria Project
.Sh NAME
.Nm Http
.Nd Encode and decode various parts of the HTTP protocol.
.Sh SYNOPSIS
.In Http.h
.Ft const char *
.Fn HttpStatusToString "const HttpStatus"
.Ft HttpRequestMethod
.Fn HttpRequestMethodFromString "const char *"
.Ft const char *
.Fn HttpRequestMethodToString "const HttpRequestMethod"
.Ft char *
.Fn HttpUrlEncode "char *"
.Ft char *
.Fn HttpUrlDecode "char *"
.Ft HashMap *
.Fn HttpParamDecode "char *"
.Ft char *
.Fn HttpParamEncode "HashMap *"
.Ft HashMap *
.Fn HttpParseHeaders "FILE *"
.Sh DESCRIPTION
.Pp
.Nm
is a collection of utility functions that are useful for dealing with
HTTP. HTTP is not a complex protocol, but this API makes it a lot easier
to work with.
.Pp
.Fn HttpStatusToString
takes an HttpStatus and converts it into a string description of the
status, which is to be used in an HTTP response. For example, calling
.Fn HttpStatusToString "HTTP_GATEWAY_TIMEOUT"
produces the string "Gateway Timeout".
.Pp
HttpStatus is an enumeration that corresponds to the actual integer
values of the valid HTTP response codes. For example, calling
.Fn HttpStatusToString "504"
produces the same output. HttpStatus is defined as follows:
.Bd -literal -offset indent
typedef enum HttpStatus
{
/* Informational responses */
HTTP_CONTINUE = 100,
HTTP_SWITCHING_PROTOCOLS = 101,
HTTP_EARLY_HINTS = 103,
/* Successful responses */
HTTP_OK = 200,
HTTP_CREATED = 201,
HTTP_ACCEPTED = 202,
HTTP_NON_AUTHORITATIVE_INFORMATION = 203,
HTTP_NO_CONTENT = 204,
HTTP_RESET_CONTENT = 205,
HTTP_PARTIAL_CONTENT = 206,
/* Redirection messages */
HTTP_MULTIPLE_CHOICES = 300,
HTTP_MOVED_PERMANENTLY = 301,
HTTP_FOUND = 302,
HTTP_SEE_OTHER = 303,
HTTP_NOT_MODIFIED = 304,
HTTP_TEMPORARY_REDIRECT = 307,
HTTP_PERMANENT_REDIRECT = 308,
/* Client error messages */
HTTP_BAD_REQUEST = 400,
HTTP_UNAUTHORIZED = 401,
HTTP_FORBIDDEN = 403,
HTTP_NOT_FOUND = 404,
HTTP_METHOD_NOT_ALLOWED = 405,
HTTP_NOT_ACCEPTABLE = 406,
HTTP_PROXY_AUTH_REQUIRED = 407,
HTTP_REQUEST_TIMEOUT = 408,
HTTP_CONFLICT = 409,
HTTP_GONE = 410,
HTTP_LENGTH_REQUIRED = 411,
HTTP_PRECONDITION_FAILED = 412,
HTTP_PAYLOAD_TOO_LARGE = 413,
HTTP_URI_TOO_LONG = 414,
HTTP_UNSUPPORTED_MEDIA_TYPE = 415,
HTTP_RANGE_NOT_SATISFIABLE = 416,
HTTP_EXPECTATION_FAILED = 417,
HTTP_TEAPOT = 418,
HTTP_UPGRADE_REQUIRED = 426,
HTTP_PRECONDITION_REQUIRED = 428,
HTTP_TOO_MANY_REQUESTS = 429,
HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451,
/* Server error responses */
HTTP_INTERNAL_SERVER_ERROR = 500,
HTTP_NOT_IMPLEMENTED = 501,
HTTP_BAD_GATEWAY = 502,
HTTP_SERVICE_UNAVAILABLE = 503,
HTTP_GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505,
HTTP_VARIANT_ALSO_NEGOTIATES = 506,
HTTP_NOT_EXTENDED = 510,
HTTP_NETWORK_AUTH_REQUIRED = 511
} HttpStatus;
.Ed
.Pp
.Fn HttpRequestMethodFromString
and
.Fn HttpRequestMethodToString
convert an HttpRequestMethod enumeration value from and to a
string, respectively. The HttpRequestMethod enumeration is
defined as follows:
.Bd -literal -offset indent
typedef enum HttpRequestMethod
{
HTTP_METHOD_UNKNOWN,
HTTP_GET,
HTTP_HEAD,
HTTP_POST,
HTTP_PUT,
HTTP_DELETE,
HTTP_CONNECT,
HTTP_OPTIONS,
HTTP_TRACE,
HTTP_PATCH
} HttpRequestMethod;
.Ed
.Pp
These can be used for parsing a request method and then storing
it efficiently; it doesn't have be stored as a string, and it's
much nicer to work with enumeration values than it is with
strings in C. The very first enumeration value is not to be
passed to
.Fn HttpRequestMethodToString ,
rather it may be returned by
.Fn HttpRequestMethodFromString
if it cannot identify the request method string passed to it.
.Pp
.Fn HttpUrlEncode
and
.Fn HttpUrlDecode
deal with URL-safe strings.
.Fn HttpUrlEncode
encodes a C string such that it can appear in a URL, and
.Fn HttpUrlDecode
does the opposite; it decodes a URL string into the actual
bytes it is supposed to represent.
.Pp
.Fn HttpParamDecode
and
.Fn HttpParamEncode
convert HTTP parameters in the form of "param=value&param2=val2"
to and from a hash map for easy parsing, manipulation, and encoding.
.Pp
.Fn HttpParseHeaders
reads HTTP headers from a stream and returns a hash map
of keys and values. All keys are lowercased to make
querying them consistent and not dependent on the casing
that was read from the stream. This is useful for both
client and server code, since the headers are of the same
format. This function should be used after parsing the
HTTP status line, because it does not parse that line.
It will stop when it encounters the first blank line,
which indicates that the body is beginning. After this
function completes, the body may be immediately be read
from the stream without any additional processing.
.Sh RETURN VALUES
.Pp
.Fn HttpStatusToString
and
.Fn HttpRequestMethodToString
both return constant strings; they are not to be manipulated because
doing so would result in a segmentation fault, as these strings
are stored in the data segment of the program.
.Pp
.Fn HttpUrlEncode ,
.Fn HttpUrlDecode ,
.Fn HttpParamDecode ,
and
.Fn HttpParamEncode
all return strings that were allocated on the heap using the
Memory API, or NULL if there was an error allocating memory.
Thee strings returned can be manipulated at will, and must be
freed using the Memory API when they're no longer needed.
.Sh SEE ALSO
.Xr HashMap 3 ,
.Xr Memory 3

View File

@ -1,157 +0,0 @@
.Dd $Mdocdate: December 13 2022 $
.Dt HTTPSERVER 3
.Os Telodendria Project
.Sh NAME
.Nm HttpServer
.Nd Extremely simple HTTP server.
.Sh SYNOPSIS
.In HttpServer.h
.Ft HttpServer *
.Fn HttpServerCreate "unsigned short" "unsigned int" "unsigned int" "HttpHandler *" "void *"
.Ft void
.Fn HttpServerFree "HttpServer *"
.Ft int
.Fn HttpServerStart "HttpServer *"
.Ft void
.Fn HttpServerJoin "HttpServer *"
.Ft void
.Fn HttpServerStop "HttpServer *"
.Ft HashMap *
.Fn HttpRequestHeaders "HttpServerContext *"
.Ft HttpRequestMethod
.Fn HttpRequestMethodGet "HttpServerContext *"
.Ft char *
.Fn HttpRequestPath "HttpServerContext *"
.Ft HashMap *
.Fn HttpRequestParams "HttpServerContext *"
.Ft char *
.Fn HttpResponseHeader "HttpServerContext *" "char *" "char *"
.Ft void
.Fn HttpResponseStatus "HttpServerContext *" HttpStatus"
.Ft FILE *
.Fn HttpStream "HttpServerContext *"
.Ft void
.Fn HttpSendHeaders "HttpServerContext *"
.Sh DESCRIPTION
.Nm
builds on the
.Xr Http 3
API, and provides a very simple, yet very functional API for
creating an HTTP server. It aims at being easy to use and minimal,
yet also efficient. It uses non-blocking I/O, is fully multi-threaded,
very configurable, yet also able to be set up in just two function calls.
.Pp
This API should be familiar to those that have dealt with the HTTP server
libraries of other programming languages, particularly Java. In fact,
much of the terminology used in this code came from Java, and you'll
notice that the way responses are sent and received very closely resemble
the way it's done in Java.
.Pp
An HTTP server itself is created with
.Fn HttpServerCreate ,
which takes the port number to create the server on, the number of threads to
use, the maximum number of connections, a request handler function, and the
arguments to that function, in that order. The request handler function is
of the following type:
.Bd -literal -offset indent
typedef void (HttpHandler) (HttpServerContext *, void *)
.Ed
.Pp
Where the void pointer received is the same pointer that was passed into
.Fn HttpServerCreate
as the last parameter.
.Pp
The returned HttpServer pointer is then managed by
.Fn HttpServerStart ,
.Fn HttpServerStop ,
.Fn HttpServerJoin ,
and
.Fn HttpServerFree .
.Fn HttpServerStart
attempts to start the HTTP server, and returns immediately with the status.
This API is fully threaded and asyncronous, so the caller can continue working
while the HTTP server is running in a separate thread, and managing a pool
of threads to handle responses. Typically at some point after calling
.Fn HttpServerStart ,
the program will have no more work to do, and so it will want to wait for
the HTTP server to finish. This is accomplished with
.Fn HttpServerJoin ,
which joins the HTTP worker thread to the calling thread, making the
calling thread wait until the HTTP server has stopped.
.Pp
The only condition that will cause the HTTP server to stop is when
.Fn HttpServerStop
is invoked. This will typically happen in a signal handler that catches
signals instructing the program to shut down. Only after the server has
been stopped can it be freed with
.Fn HttpServerFree .
Note that calling
.Fn HttpServerFree
while the server is running results in undefined behavior.
.Pp
The remainder of the functions in this API are used inside of the
HTTP handler function passed by the caller of
.Fn HttpServerCreate .
They allow the handler to figure out the context of an HTTP request,
which includes the path that was requested, any parameters, and the
headers used to make the request. They also allow the handler
to respond with a status code, headers, and a body.
.Pp
.Fn HttpRequestHeaders ,
.Fn HttpRequestMethodGet ,
.Fn HttpRequestPath ,
and
.Fn HttpRequestParams
get the information about the request. They should all be passed the
server context pointer that was passed into the handler function.
The data returned by these functions should be treated as read-only,
and should not be freed; their memory is handled outside of the HTTP
server handler function.
.Pp
.Fn HttpResponseHeader
and
.Fn HttpResponseStatus
are used to set response headers, and the response status of the
request, respectively.
.Pp
.Fn HttpStream
returns a stream that is both readable and writable. Reading from
the stream reads the request body that the client sent, if there is
one. Note that the request headers have already been read, so the stream
is correctly positioned at the beginning of the body of the request.
.Fn HttpSendHeaders
must be called before the stream is written to, otherwise a malformed
HTTP response will be sent. An HTTP handler should properly set all
the headers it intends to send, send those headers, and then write the
response body to the stream. Finally, note that the stream does not
need to be closed by the HTTP handler; in fact, doing so results in
undefined behavior. The stream is managed by the server itself.
.Sh RETURN VALUES
.Pp
.Fn HttpRequestHeaders
and
.Fn HttpRequestParams
return a hash map that can be used to access the request headers and
parameters, if necessary. Note that the request parameters would be
GET parameters, attached to the path that was requested. To get POST
parameters, read the stream returned by
.Fn HttpStream
and pass the contents into
.Fn HttpParamDecode
to get a hash map.
.Pp
.Fn HttpRequestPath
returns a string that represents the path that the client requested. Note
that it is not normalized; it is exactly what the client sent, so it should
be checked for path traversal attacks and other malformed paths that the
client may sent.
.Pp
.Fn HttpResponseHeader
returns the previous value of the given header, or NULL if there was no
previous value.
.Pp
.Fn HttpStream
returns a FILE pointer that can be read and written using the C standard
I/O functions.
.Sh SEE ALSO
.Xr Http 3

View File

@ -1,263 +0,0 @@
.Dd $Mdocdate: March 12 2023 $
.Dt JSON 3
.Os Telodendria Project
.Sh NAME
.Nm Json
.Nd A fully-featured JSON API.
.Sh SYNOPSIS
.In Json.h
.Ft JsonType
.Fn JsonValueType "JsonValue *"
.Ft JsonValue *
.Fn JsonValueObject "HashMap *"
.Ft HashMap *
.Fn JsonValueAsObject "JsonValue *"
.Ft JsonValue *
.Fn JsonValueArray "Array *"
.Ft Array *
.Fn JsonValueAsArray "
.Ft JsonValue *
.Fn JsonValueString "char *"
.Ft char *
.Fn JsonValueAsString "JsonValue *"
.Ft JsonValue *
.Fn JsonValueInteger "long"
.Ft long
.Fn JsonValueAsInteger "JsonValue *"
.Ft JsonValue *
.Fn JsonValueFloat "double"
.Ft double
.Fn JsonValueAsFloat "JsonValue *"
.Ft JsonValue *
.Fn JsonValueBoolean "int"
.Ft int
.Fn JsonValueAsBoolean "JsonValue *"
.Ft JsonValue *
.Fn JsonValueNull "void"
.Ft void
.Fn JsonValueFree "JsonValue *"
.Ft void
.Fn JsonFree "HashMap *"
.Ft void
.Fn JsonEncodeString "const char *" "FILE *"
.Ft void
.Fn JsonEncodeValue "JsonValue *" "FILE *" "int"
.Ft int
.Fn JsonEncode "HashMap *" "FILE *" "int"
.Ft HashMap *
.Fn JsonDecode "FILE *"
.Ft JsonValue *
.Fn JsonGet "HashMap *" "size_t" "..."
.Ft JsonValue *
.Fn JsonSet "HashMap *" "size_t" "..."
.Sh DESCRIPTION
.Nm
is a fully-featured JSON API for C using
.Xr Array 3
and
.Xr HashMap 3
that can parse JSON, and serialize an in-memory structure
to JSON.
It builds on the foundation set up by those APIs because
that's all JSON really is, just maps and arrays.
.Nm
also provides a structure for encapsulating an arbitrary
value and identifying its type, making it easy for a program
to work with JSON data.
.Nm
is very strict and tries to adhere as closely as possible to
the proper defintion of JSON. It will fail on syntax errors
of any kind, which is fine for a Matrix homeserver because we can
just return M_BAD_JSON if anything here fails, but it may not
be suitable for other purposes.
.Pp
This JSON implementation focuses primarily on serialization and
deserialization to and from streams. It does not provide facilities
for handling JSON strings; it only writes JSON to output streams, and
reads them from input streams. If course, you can use the POSIX
.Xr fmemopen 3
and
.Xr open_memstream 3
if you want to deal with JSON strings, but JSON is intended to be an
exchange format. Data should be converted to JSON right before it is
leaving the program, and converted from JSON as soon as it is coming
in.
.Pp
The
.Nm
header defines the following enumeration for identifying types of
values:
.Bd -literal -offset indent
typedef enum JsonType
{
JSON_NULL, /* Maps to C NULL */
JSON_OBJECT, /* Maps to a HashMap of JsonValues */
JSON_ARRAY, /* Maps to an Array of JsonValues */
JSON_STRING, /* Maps to a NULL-terminated C string */
JSON_INTEGER, /* Maps to a C long */
JSON_FLOAT, /* Maps to a C double */
JSON_BOOLEAN /* Maps to a C boolean, 1 or 0 */
} JsonType;
.Ed
.Pp
A JsonValue encapsulates all the possible types that can be stored in
JSON. It is an opaque structure that can be managed entirely by the
functions defined in this API. It is important to note that in the case
of objects, arrays, and strings, this structure only stores pointers to
the allocated data, it doesn't store the data itself, but the data IS
freed when using
.Fn JsonFree .
.Pp
Objects are represented as hash maps consisting entirely of JsonValue
structures, and arrays are represented as arrays consisting entirely
of JsonValue structures. When generating a JSON object, any
attempt to stuff a value into a hash map or array without encoding it
as a JsonValue first will result in undefined behavior.
.Pp
.Fn JsonValueType
determines the type of a given JsonValue.
.Pp
The
.Fn JsonValue*
functions wrap their input in a JsonValue that represents the given
value. The
.Fn JsonValueAs*
functions do the opposite; they unwrap a JsonValue and return the
actual usable value itself. They all closely resemble each other and
they all behave the same way, so to save on time and effort, they're
not explicitly documented individually. If something is unclear about
how these functions work, consult the source code, and feel free
to write the documentation yourself for clarification. Otherwise,
reach out to the official Matrix rooms, and someone should be able
to help you.
.Pp
.Fn JsonValueNull
is a special case that represents a JSON null. Because
.Xr Array 3
and
.Xr HashMap 3
do not accept NULL values, this function should be used to represent
NULL in JSON. Even though a small amount of memory is allocated just
to point to NULL, this keeps the APIs clean.
.Pp
.Fn JsonValueFree
frees the memory being used by a JSON value. Note that this will
recursively free all Arrays, HashMaps, and other JsonValues that
are reachable from the given value. It also invokes
.Fn Free
(documented in
.Xr Memory )
on all strings, so make sure passed string pointers point to strings
on the heap, not the stack. This will be the case for all strings
returned by
.Fn JsonDecode ,
but if you are manually creating JSON objects and stitching them
together, you should be aware that calling this function on a value
that contains a pointer to a stack string will result in undefined
behavior.
.Pp
.Fn JsonFree
recursively frees a JSON object, iterating over all the values and
freeing them using
.Fn JsonValueFree .
.Pp
.Fn JsonEncodeString
encodes the given string in such a way that it can be embedded in a
JSON stream. This entails:
.Bl -bullet -offset indent
.It
Escaping quotes, backslashes, and other special characters using
their backslash escape.
.It
Encoding bytes that are not UTF-8 using escapes.
.It
Wrapping the entire string in double quotes.
.El
.Pp
This function is provided via the public
.Nm
API so that it is accessible to custom JSON encoders, such as
.Xr CanonicalJson 3 .
This will typically be used for encoding JSON keys; for encoding
values, just use
.Fn JsonEncodeValue .
.Pp
.Fn JsonEncodeValue
serializes a JsonValue as it would appear in JSON output. This is
a recursive function that also encodes all child values reachable
from the given value. This function is exposed via the public
.Nm
API so that it is accessible to custom JSON encoders. Normal users
that are not writing custom encoders should in most cases just use
.Fn JsonEncode
to encode an entire object. The third parameter is an integer that
represents the indent level of the value to be printed, or a negative
number if pretty-printing should be disabled, and JSON should be
printed as minimized as possible. If you want to pretty-print a
JSON object, set this to
.Va JSON_PRETTY .
To get the minified output, set it to
.Va JSON_DEFAULT .
.Pp
.Fn JsonEncode
encodes a JSON object as minimized JSON and writes it to the given
output stream. This function is recursive; it will serialize
everything accessible from the passed object. The third integer
parameter has the same behavior asa described above.
.Pp
.Fn JsonDecode
does the opposite of
.Fn JsonEncode ;
it reads from a JSON stream and decodes it into a hash map
of JsonValues.
.Pp
.Fn JsonSet
and
.Fn JsonGet
are convenience functions that allow the caller to retrieve and
manipulate arbitrarily deep keys within a JSON object. They take
a root JSON object, the number of levels deep to go, and then that
number of keys as a varargs list. All keys must have objects
as values, with the exception of the last one, which is the one
being retrieved or set.
.Fn JsonSet
will create any intermediate objects as necessary to set the
proper key.
.Sh RETURN VALUES
.Pp
.Fn JsonValueType
returns a JsonType, documented above, that tells what the given
value actually is, or JSON_NULL if the passed value is NULL.
Note that even a fully valid JsonValue may actually be of type
JSON_NULL, so this function should not be used to determine
whether or not a given value is valid.
.Pp
The
.Fn JsonValue*
functions return a JsonValue that holds a pointer to the passed
value, or NULL if there was an error allocating memory. The
.Fn JsonValueAs*
functions return the actual value represented by the given
JsonValue so that it can be manipulated by the program, or
NULL if no value was provided, or the value is not of the
correct type expected by the function.
.Pp
.Fn JsonEncode
returns whether or not the encoding operation was successful.
This function will fail if any passed parameters are NULL,
otherwise it will assume all pointers are valid and return a
success value.
.Pp
.Fn JsonDecode
returns a hash map of JsonValues that can be manipulated by
this API, or NULL if there was an error parsing the JSON.
.Pp
.Fn JsonGet
returns a JsonValue, or NULL if the requested key is not set
in the object.
.Fn JsonGet
returns the previous value of the provided key, or NULL if there
was no previous value.
.Sh SEE ALSO
.Xr HashMap 3 ,
.Xr Array 3

View File

@ -1,155 +0,0 @@
.Dd $Mdocdate: February 15 2023 $
.Dt LOG 3
.Os Telodendria Project
.Sh NAME
.Nm Log
.Nd A simple logging framework for logging to files, standard output, or the system log.
.Sh SYNOPSIS
.In Log.h
.Ft LogConfig *
.Fn LogConfigCreate "void"
.Ft void
.Fn LogConfigFree "LogConfig *"
.Ft void
.Fn LogConfigLevelSet "LogConfig *" "int"
.Ft void
.Fn LogConfigIndent "LogConfig *"
.Ft void
.Fn LogConfigUnindent "LogConfig *"
.Ft void
.Fn LogConfigIndentSet "LogConfig *" "size_t"
.Ft void
.Fn LogConfigOutputSet "LogConfig *" "FILE *"
.Ft void
.Fn LogConfigFlagSet "LogConfig *" "int"
.Ft void
.Fn LogConfigFlagClear "LogConfig *" "int"
.Ft void
.Fn LogConfigTimeStampFormatSet "LogConfig *" "char *"
.Ft void
.Fn Log "LogConfig *" "int" "const char *" "..."
.Sh DESCRIPTION
.Pp
A heavily-modifed version of Shlog, a simple C logging library facility
that allows for colorful outputs, timestamps, and custom log levels.
This library differs from Shlog in that the naming conventions have
been updated to be consistent with Telodendria, and system log support
has been added.
.Pp
Shlog was originally a learning project. It worked well and produced
elegant logging output, so it was chosen to be the main logging
mechanism of Telodendria. The original Shlog project is now dead; Shlog
lives on now only as Telodendria's logging mechanism.
.Pp
One of the design choices made in this library, which unfortunately
makes code using it a little more verbose, is that multiple logging
configurations can exist in a program. No global variables are used,
and all functions are thread-safe.
.Pp
.Fn LogConfigCreate
creates a new log configuration with sane defaults that can be used
immediately. Note that every call to
.Fn Log
requires a valid configuration pointer.
.Fn LogConfigFree
frees all memory associated with that configuration, invalidating
it. Passing an invalid configuration pointer into any of the
functions defined here result in undefined behavior. The
.Fn LogConfig*Set
functions manipulate the data pointed to by the pointer returned
by
.Fn LogConfigCreate .
.Pp
.Fn LogConfigLevelSet
sets the current log level on the specified log configuration. This
indicates that only messages at or above this level should be
logged; all other messages are silently discarded by the
.Fn Log
function. The passed log level should be one of the log levels
defined by
.Xr syslog 3 .
Refer to that page for a complete list of acceptable log levels,
and note that passing in an invalid or unknown log level will
result in undefined behavior.
.Pp
.Fn LogConfigIndent
causes the output of
.Fn Log
to be indented two more spaces than it was previously. This can be
helpful when generating stack traces, or otherwise producing
hierarchical output. After calling this function, all future
messages using the given config will be indented two more spaces
than they were before. This is just a wrapper function around
.Fn LogConfigIndentSet ,
which allows the caller to specify an arbitrary indentation in
spaces.
.Fn LogConfigUnindent
does the exact opposite of
.Fn LogConfigIndent ;
it subtracts two spaces from the indentation level, unless there
is no indent, then it does nothing.
.Pp
.Fn LogConfigOutputSet
sets the file stream that logging output should be written to. This
defaults to standard output, but it can be standard error, or some
other file stream. Passing a NULL value for the file pointer sets
the log output to standard output. Note that the output file stream
is only used if FLAG_OUTPUT_SYSLOG is not set.
.Pp
.Fn LogConfigFlagSet
and
.Fn LogConfigFlagClear
are used for setting a number of boolean options on a log
configuration. They utilize bitwise operators, so multiple options
can be set or cleared with a single function call using bitwise OR
operators. The flags defined as preprocessor macros, and are as
follows:
.Bl -tag -width Ds
.It LOG_FLAG_COLOR
When set, enable color-coded output on TTYs. Note that colors are
implemented as ANSI escape sequences, and are not written to file
streams that are not actually connected to a TTY, to prevent those
sequences from being written to a file.
.Xr isatty 3
is checked before writing ANSI sequences.
.It LOG_FLAG_SYSLOG
When enabled, log output to the syslog using
.Xr syslog 3 ,
instead of logging to the file set by
.Fn LogConfigOutputSet .
This flag always overrides the file stream set by that function,
regardless of when it was set.
.El
.Pp
.Fn LogConfigTimeStampFormatSet
allows a custom timestamp to be prepended to each message
if the output is not going to the system log. Consult your
system's documentation for
.Xr strftime 3 .
A value of NULL disables outputting a timestamp before messages.
.Pp
The
.Fn Log
function actually writes a log message to a console, file, system
log, or other supported output device using the given configuration.
This function is thread-safe; it locks a mutex before writing a
message, and then unlocks it after the message was written. Each
log configuration has its own mutex, so this function can be used
with mutiple active log configurations.
.Pp
This function only logs messages if their level is above or equal to
the currently configured log level, making it easy to turn some
messages on or off. The function has the same usage as
.Xr printf 3 .
.Sh RETURN VALUES
.Pp
.Fn LogConfigCreate
returns a pointer to a configuration structure on the heap, or NULL
if there was an error allocating memory for it. The returned
structure is opaque to the caller; the
.Fn LogConfig*
functions should be used to manipulate it.
.Pp
All other functions do not return anything. They are simply
assumed to always succeed. If any arguments are NULL, then the
functions do nothing, unless otherwise specifically noted.

View File

@ -1,74 +0,0 @@
.Dd $Mdocdate: March 12 2023 $
.Dt MAIN 3
.Os Telodendria Project
.Sh NAME
.Nm Main
.Nd Telodendria daemon entry function.
.Sh DESCRIPTION
.Pp
The
.Fn main
function is the first function that is executed. It is responsible
for setting things up and tearing them down. In order, it:
.Bl -bullet
.It
Creates a default logging configuration, installs the memory hook,
and prints the header.
.It
If running on OpenBSD, or is patched for other operating systems
that support it, executes
.Xr pledge 2
with a minimal set of permissions for security.
.It
Parses the command line arguments and sets the relevant flags.
.It
If running on OpenBSD, or is patched for other operating systems
that support it, executes
.Xr unveil 2
on the configuration file.
.It
parses and processes the configuration file.
.It
If running on OpenBSD, or is patched for other operating systems
that support it, executes
.Xr unveil 2
on the data directory, and then disables all future calls to
.Xr unveil 2 .
.It
Applies all settings from the configuration file.
.It
Changes into the data directory.
.It
Binds the HTTP socket.
.It
If running as the root user and not on OpenBSD or other operating
systems that support
.Xr unveil 2 ,
executes
.Xr chroot 2
on the data directory.
.It
Detects the running user, and\(emif specified in the
configuration\(emdrops permissions.
.It
Sets up the database, and cron runner, then starts
the HTTP server and installs the signal handlers.
.It
Blocks on the HTTP server.
.It
Shuts down the HTTP server, cleans up all memory and
file handles, then exits.
.El
.Sh RETURN VALUE
.Pp
.Fn main
returns
.Va EXIT_SUCCESS
if everything runs correctly and Telodendria is
quit normally. It returns
.Va EXIT_FAILURE
if there was a fatal failure before the HTTP
server could be started.
.Pp
These values are returned to the operating system and
indicate the exit status of the process.

View File

@ -1,141 +0,0 @@
.Dd $Mdocdate: March 6 2023 $
.Dt MATRIX 3
.Os Telodendria Project
.Sh NAME
.Nm Matrix
.Nd Functions for writing Matrix API endpoints.
.Sh SYNOPSIS
.In Matrix.h
.Ft void
.Fn MatrixHttpHandler "HttpServerContext *" "void *"
.Ft void
.Fn MatrixErrorCreate "MatrixError"
.Ft HashMap *
.Fn MatrixRateLimit "HttpServerContext *" "Db *"
.Ft HashMap *
.Fn MatrixGetAccessToken "HttpServerContext *" "char **"
.Ft HashMap *
.Fn MatrixClientWellKnown "char *" "char *"
.Sh DESCRIPTION
.Nm
provides some helper functions that bind to the
.Xr HttpServer 3
interface and add basic Matrix functionality, turning an
HTTP server into a Matrix homeserver.
.Pp
.Xr MatrixHttpHandler
is the HTTP handler function that handles all Matrix homeserver
functionality. It should be passed into
.Fn HttpServerCreate ,
and it expects that an instance of MatrixHttpHandlerArgs will also
be provided, because that's what the void pointer is cast to.
That structure is defined as follows:
.Bd -literal -offset indent
typedef struct MatrixHttpHandlerArgs
{
LogConfig *lc;
TelodendriaConfig *config;
Db *db;
} MatrixHttpHandlerArgs;
.Ed
.Pp
This structure should be populated once and then never modified again
for the duration of the HTTP server.
.Pp
.Fn MatrixErrorCreate
is a convenience function that constructs an error payload, including
the error code and message, given just a MatrixError. MatrixErrors
exactly follow the errors in the Matrix specification, and are
defined as follows:
.Bd -literal -offset indent
typedef enum MatrixError
{
M_FORBIDDEN,
M_UNKNOWN_TOKEN,
M_MISSING_TOKEN,
M_BAD_JSON,
M_NOT_JSON,
M_NOT_FOUND,
M_LIMIT_EXCEEDED,
M_UNKNOWN,
M_UNRECOGNIZED,
M_UNAUTHORIZED,
M_USER_DEACTIVATED,
M_USER_IN_USE,
M_INVALID_USERNAME,
M_ROOM_IN_USE,
M_IVALID_ROOM_STATE,
M_THREEPID_IN_USE,
M_THREEPID_NOT_FOUND,
M_THREEPID_AUTH_FAILED,
M_THREEPID_DENIED,
M_SERVER_NOT_TRUSTED,
M_UNSUPPORTED_ROOM_VERSION,
M_BAD_STATE,
M_GUEST_ACCESS_FORBIDDEN,
M_CAPTCHA_NEEDED,
M_CAPTCHA_INVALID,
M_MISSING_PARAM,
M_INVALID_PARAM,
M_TOO_LARGE,
M_EXCLUSIVE,
M_RESOURCE_LIMIT_EXCEEDED,
M_CANNOT_LEAVE_SERVER_NOTICE_ROOM
} MatrixError;
.Ed
.Pp
.Fn MatrixRateLimit
determines whether or not the request should be rate limited. It is
expected that this will occur before most, if not all of the caller's
logic.
.Pp
.Fn MatrixGetAccessToken
reads the request headers and parameters, and attempts to obtain
the access token it found. The matrix specification says that an
access token can either be in an
.Dv Authorization
header, or in a
.Dv access_token
.Sy GET
paramter. This function checks both, and stores the access token
it finds in the passed character pointer.
.Pp
.Fn MatrixClientWellKnown
builds a client ``well-known'' JSON object, which contains
information about the homeserver base URL and identity server,
both of which should be provided by the caller in that order. This
object can be sent to a client as-is, as is the case with the
.Pa /.well-known/matrix/client
endpoint, or it can be added as a key in a response, as is the
case with a few endpoints.
.Sh RETURN VALUES
.Pp
.Fn MatrixErrorCreate
returns a JSON object that represents the given error code. It can be
immediately returned as the HTTP response body, or modified as needed.
.Pp
.Fn MatrixUserInteractiveAuth ,
.Fn MatrixAuthenticate ,
and
.Fn MatrixRateLimit
all return NULL when they are successful. That is, if these functions
return NULL, then the caller can proceed assuming that all is well
and no further action needs to be taken. If these functions do not
return NULL, then the returned JSON object should be passed along to the
client immediately without continuing.
.Pp
.Fn MatrixGetAccessToken
returns a JSON object that should be immediately passed to the client
if it is not NULL. This JSON object holds an error message, indicating
that something went wrong. If this function does return NULL, then
the access token can be checked for validity. Otherwise, the access
token is either not valid or not provided so it should not be
checked.
.Pp
.Fn MatrixClientWellKnown
returns a JSON object, or NULL if something went wrong.
.Sh SEE ALSO
.Xr HttpServer 3 ,
.Xr Log 3 ,
.Xr TelodendriaConfig 3 ,
.Xr Db 3

View File

@ -1,145 +0,0 @@
.Dd $Mdocdate: January 9 2023 $
.Dt MEMORY 3
.Os Telodendria Project
.Sh NAME
.Nm Memory
.Nd Smart memory management.
.Sh SYNOPSIS
.In Memory.h
.Ft void *
.Fn MemoryAllocate "size_t" "const char *" "int"
.Ft void *
.Fn MemoryReallocate "void *" "size_t" "const char *" "int"
.Ft void
.Fn MemoryFree "void *" "const char *" "int"
.Ft size_t
.Fn MemoryAllocated "void"
.Ft void
.Fn MemoryFreeAll "void"
.Ft MemoryInfo *
.Fn MemoryInfoGet "void *"
.Ft size_t
.Fn MemoryInfoGetSize "MemoryInfo *"
.Ft const char *
.Fn MemoryInfoGetFile "MemoryInfo *"
.Ft int
.Fn MemoryInfoGetLine "MemoryInfo *"
.Ft void *
.Fn MemoryInfoGetPointer "MemoryInfo *"
.Ft void
.Fn MemoryIterate "void (*) (MemoryInfo *, void *)" "void *"
.Ft void
.Fn MemoryHook "void (*) (MemoryAction, MemoryInfo *, void *" "void *"
.Ft void
.Fn MemoryHexDump "MemoryInfo *" "void (*) (size_t, char *, char *, void *)" "void *"
.Sh DESCRIPTION
.Nm
is an API that allows for smart memory management and profiling. It wraps
the standard library functions
.Xr malloc 3 ,
.Xr realloc 3 ,
and
.Xr free 3 ,
and offers identical semantics, while providing functionality that the
standard library doesn't have, such as getting statistics on the total
memory allocated on the heap, and getting the size of a block of memory
given a pointer. Additionally, thanks to preprocessor macros, the exact
file and line number at which an allocation, reallocation, or free occured
can be obtained given a pointer. Finally, all the blocks allocated on the
heap can be iterated and evaluated, and a callback function can be executed
every time a memory operation occurs.
.Pp
A number of macros are available, which make using the
.Nm
API much more useful.
.Fn Malloc
expands to
.Fn MemoryAllocate
with the __FILE__ and __LINE__ constants for the second and third
arguments respectively. Likewise,
.Fn Realloc
and
.Fn Free
expand to
.Fn MemoryReallocate
and
.Fn MemoryFree
with __FILE__ and __LINE__ as the second and third parameters.
This allows the API to be used exactly how the standard library
would be used. In fact, the functions which these macros expand to
are not intended to be called directly; only use the macros for the
best results.
.Pp
If all memory used in the program is managed by this API, there are some
helpful functions that allow the program to probe the state of the heap.
These functions are described here.
.Pp
.Fn MemoryAllocated
gets the total memory that the program has on the heap. This operation
iterates over all the heap allocations made with
.Fn MemoryAllocate
and then returns a total count, in bytes.
.Pp
.Fn MemoryFreeAll
iterates over all the heap allocations made with
.Fn MemoryAllocate
and calls
.Fn MemoryFree
on them. It immediately invalidates all pointers, and any subsequent
reads or writes to heap memory result in undefined behavior. This
is typically used at the end of the program.
.Pp
.Fn MemoryInfoGet
takes a pointer and fetches information about it, storing it in a
structure that can then be queried.
.Pp
.Fn MemoryInfoGetSize ,
.Fn MemoryInfoGetFile ,
.Fn MemoryInfoGetLine ,
and
.Fn MemoryInfoGetPointer
all take in the structure returned by
.Fn MemoryInfoGet ,
and return the respective property about the given property. These are
especially useful for logging and debugging with
.Fn MemoryIterate
and
.Fn MemoryHook .
.Pp
.Fn MemoryIterate
takes a pointer to a function that takes the memory information structure,
as well as a void pointer for caller-provided arguments. It iterates over
all the heap memory currently allocated at the time of calling.
.Fn MemoryHook
has a similar prototype, although the function pointer it takes is slightly
different. It also takes a memory action as the first argument. The
.Nm
API stores the pointer to this function, and executes it every time memory
is allocated, reallocated, or freed. This allows a program to execute code
whenever memory is allocated.
.Pp
.Fn MemoryHexDump
can be useful for debugging memory errors. It reads over a block of memory
and generates a hexadecimal and an ASCII string for each chunk of the block.
It takes a memory infomation structure and a callback function that processes
the offset, hexadecimal string, and ASCII string. This callback function
typically prints the strings out to a console, file, or other output
device.
.Sh RETURN VALUES
.Pp
.Fn MemoryAllocate
and
.Fn MemoryReallocate
return the same as their standard library counterparts. That is, a pointer
to memory on the heap, or NULL if there was an error allocating it.
.Pp
.Fn MemoryInfoGet
returns a pointer to information about a block on the heap, or NULL if the
passed pointer was not allocated by the
.Nm
API, or is no longer allocated.
.Pp
.Fn MemoryAllocated
returns an unsigned integer that indicates the number of bytes currently
allocated on the heap.

View File

@ -1,100 +0,0 @@
.Dd $Mdocdate: November 25 2022 $
.Dt QUEUE 3
.Os Telodendria Project
.Sh NAME
.Nm Array
.Nd A simple static queue data structure.
.Sh SYNOPSIS
.In Queue.h
.Ft Queue *
.Fn QueueCreate "size_t"
.Ft void
.Fn QueueFree "Array *"
.Ft int
.Fn QueuePush "Queue *" "void *"
.Ft void *
.Fn QueuePop "Queue *"
.Ft void *
.Fn QueuePeek "Queue *"
.Ft int
.Fn QueueFull "Queue *"
.Ft int
.Fn QueueEmpty "Queue *"
.Sh DESCRIPTION
These functions implement a simple queue data structure that
is statically sized.
This implementation does not actually store the values of the
items in it; it only stores pointers to the data. As such, you will
still have to manually maintain all your data. The advantage of this
is that these functions don't have to copy data, and thus don't care
how big the data is. Furthermore, arbitrary data can be stored in the
queue.
.Pp
This queue implementation operates on the heap. It is a circular
queue, and it does not grow as it is used. Once the size is set, the
queue never gets any bigger.
.Pp
These functions operate on a queue structure which is opaque to the
caller.
.Pp
.Fn QueueCreate
and
.Fn QueueFree
allocate and deallocate a queue, respectively.
Note that
.Fn QueueFree
does not free any of the values stored in the queue; it is the caller's
job to manage the memory for each item. Typically, the caller would
dequeue all the items in the queue and free them before freeing
the queue itself.
.Pp
.Fn QueuePush
and
.Fn QueuePop
are the main functions used to modify the array. They enqueue and dequeue
elements from the queue structure, respectively.
.Pp
.Fn QueuePeek
simply returns the pointer that is next up in the queue without actually
discarding it, such that the next call to
.Fn QueuePeek
or
.Fn QueuePop
return the same pointer.
.Pp
.Fn QueueFull
and
.Fn QueueEmpty
return a boolean value that indicates whether or not the queue is full
or empty, respectively.
.Sh RETURN VALUES
.Pp
.Fn QueueCreate
returns a queue structure, or
.Dv NULL
if there was a memory allocation error.
.Pp
.Fn QueuePush
as well as
.Fn QueueFull
and
.Fn QueueEmpty
all return boolean values. In the case of
.Fn QueuePush
whether or not the push was actually successful is returned. This will
only happen if the queue is already full, or a
.Dv NULL
pointer is passed.
.Pp
.Fn QueuePop
and
.Fn QueuePeek
both return caller-managed pointers that would have been at some point
pushed into the queue with the
.Fn QueuePush
function. They may also return
.Dv NULL
if the queue is empty.
.Sh SEE ALSO
.Xr Array 3 ,
.Xr HashMap 3

View File

@ -1,44 +0,0 @@
.Dd $Mdocdate: February 16 2023 $
.Dt RAND 3
.Os Telodendria Project
.Sh NAME
.Nm Rand
.Nd Thread-safe random numbers.
.Sh SYNOPSIS
.In Rand.h
.Ft int
.Fn RandInt "unsigned int"
.Ft void
.Fn RandIntN "int *" "size_t" "unsigned int"
.Sh DESCRIPTION
.Nm
is used for generating random numbers in a thread-safe way. Currently,
one seed is shared across all threads, which means only one thread can
generate random numbers at a time. In the future, a seed pool may be
maintained. The seed is initialized on the first call to a function
that needs it. It is initialized with the current timestamp,
the process ID, and the thread ID. These should be sufficiently random
sources, so the seed should be secure enough.
.Pp
.Fn RandInt
generates a single random integer between 0 and the passed value.
.Fn RandIntN
takes an integer pointer, a buffer size, and the maximum value a
random number is allowed to be. It generates the number of random
integers specified by the buffer size, and stores them at the passed
pointer. This allows a caller to get multiple random numbers at a
time, as each call to
.Fn RandInt
will have to lock and unlock a mutex, whereas
.Fn RandIntN
can obtain multiple random integers in a single pass.
.Sh RETURN VALUES
.Pp
.Fn RandInt
returns the value of
.Xr rand_r 3
with the internally-stored seed. The return value should be in the
range of 0 to RAND_MAX.
.Sh SEE ALSO
.Xr Util 3 ,
.Xr rand 3

View File

@ -1,87 +0,0 @@
.Dd $Mdocdate: December 12 2022 $
.Dt ROUTES 3
.Os Telodendria Project
.Sh NAME
.Nm Routes
.Nd Matrix API endpoint abstractions.
.Sh SYNOPSIS
.In Routes.h
.Ft char *
.Fn MATRIX_PATH_POP "MATRIX_PATH"
.Ft size_t
.Fn MATRIX_PATH_PARTS "MATRIX_PATH"
.Ft int
.Fn MATRIX_PATH_EQUALS "char *" "char *"
.Sh DESCRIPTION
.Pp
.Nm
provides all of the Matrix API route functions, as well as a few
helpful macros to be used to declare those route functions, and some
macros that are intended to be used inside them.
.Pp
The route macros are intended to increase the readability of the header,
so the individual routes are not documented here; only the helper
macros and structures are documented here. Consult the
.Pa Routes.h
file for a list of the registered route functions.
.Pp
.Fn MATRIX_PATH_POP
and
.Fn MATRIX_PATH_PARTS
are macros that abstract away the underlying data structure of the
path so that that routes don't have to care what it is. The reason
this design choice was made was so that the data structure can be
switched out without breaking all the routes. These macros should
be preferred to the actual underlying data structure functions,
because the data structure may change in the future.
.Pp
At the moment, the path data structure is just an array, but it would
be much more efficient to switch to a queue (which can be easily done
with the current Queue implementation if we just add a function that
computes how many elements are in the queue.)
.Pp
.Fn MATRIX_PATH_POP
returns the next available part of the path, and removes it from
the path such that the next call to
.Fn MATRIX_PATH_POP
returns the part after.
.Fn MATRIX_PATH_PARTS
returns the number of path parts remaining.
.Pp
.Fn MATRIX_PATH_EQUALS
is just a simple string comparison macro. It takes two strings and
returns a boolean value indicating whether or not they're equal.
.Pp
.Nm
also defines
.Fn ROUTE
and
.Fn ROUTE_IMPL .
.Fn ROUTE
is intended to be used only inside the route header, and should be
invoked to declare a new route function prototype. It takes the
route function name, which by convention starts with "Route".
.Fn ROUTE_IMPL
may be used to actually implement a route function. It takes the
route function name, and the name of the variable to put the
RouteArgs in.
.Pp
Every route function takes a RouteArgs structure, which is defined
as follows:
.Bd -literal -offset indent
typedef struct RouteArgs
{
MatrixHttpHandlerArgs *matrixArgs;
HttpServerContext *context;
MATRIX_PATH *path;
} RouteArgs;
.Ed
.Sh RETURN VALUES
.Pp
Each route returns a JSON hash map that contains the response it
intends to return to the client making the request. Routes
should NOT return NULL, because then no body will be returned to
the client, and that is almost always a bug. The Matrix specification
usually mandates that at least an empty JSON object is returned.
.Sh SEE ALSO
.Xr Matrix 3

View File

@ -1,27 +0,0 @@
.Dd $Mdocdate: December 19 2022 $
.Dt SHA2 3
.Os Telodendria Project
.Sh NAME
.Nm Sha2
.Nd A simple implementation of the SHA2 hashing functions.
.Sh SYNOPSIS
.In Sha2.h
.Ft char *
.Fn Sha256 "char *"
.Sh DESCRIPTION
.Pp
This API defines simple functions for computing SHA2 hashes. At the
moment, it only defines
.Fn Sha256 ,
which computes the SHA-256 hash of the given C string. It is not trivial
to implement SHA-512 in ANSI C due to the lack of a 64-bit integer
type, so that hash function has been omitted.
.Sh RETURN VALUES
.Pp
.Fn Sha256
returns a string allocated on the heap using the Memory API, or NULL
if there was an error allocating memory for it. The returned string
should be freed when it is no longer needed.
.Sh SEE ALSO
.Xr Memory 3 ,
.Xr Base64 3

View File

@ -1,55 +0,0 @@
.Dd $Mdocdate: February 15 2023 $
.Dt STR 3
.Os Telodendria Project
.Sh NAME
.Nm Str
.Nd Functions for manipulating and creating strings.
.Sh SYNOPSIS
.In Str.h
.Ft char *
.Fn StrUtf8Encode "unsigned long"
.Ft char *
.Fn StrDuplicate "const char *"
.Ft char *
.Fn StrConcat "size_t" "..."
.Ft char *
.Fn StrRandom "size_t"
.Sh DESCRIPTION
.Nm
provides string-related functions. It is called
.Nm ,
not String, because some platforms (Windows) do not have
case-sensitive filesystems, so String and string are the same thing, which poses
a problem because string is a standard library header.
.Pp
.Fn StrUtf8Encode
takes a UTF-8 codepoint and encodes it into a string buffer containing between
1 and 4 bytes. The string buffer is allocated on the heap, so it should be freed
when it is no longer needed.
.Pp
.Fn StrDuplicate
duplicates a NULL-terminated string, and returns a new string on the heap. This is
useful when a function takes in a string that it needs to store for long amounts
of time, even perhaps after the original string is gone.
.Pp
.Fn StrConcat
is a var-args function that takes the number of NULL-terminated strings specified
by the first argument, and returns a new string that contains their concatenation.
It works a lot like
.Xr strcat 3 ,
but it takes care of allocating memory big enough to hold all the strings. Any
strings may be NULL. If a string is NULL, it is treated like an empty string.
.Pp
.Fn StrRandom
generates a random string of the specified length.
.Sh RETURN VALUES
.Pp
.Fn StrUtf8Encode ,
.Fn StrDuplicate ,
.Fn StrConcat ,
and
.Fn StrRandom
return a pointer to a NULL-terminated C string on the heap, or NULL if a memory
allocation error occurs. Returned pointers should be freed using the Memory API.
.Sh SEE ALSO
.Xr Memory 3

View File

@ -1,93 +0,0 @@
.Dd $Mdocdate: March 12 2023 $
.Dt TELODENDRIA 3
.Os Telodendria Project
.Sh NAME
.Nm Telodendria
.Nd Branding and callback functions specific to Telodendria.
.Sh SYNOPSIS
.In Telodendria.h
.Vt const char
.Va TelodendriaLogo[][]
.Pp
.Vt const char
.Va TelodendriaHeader[][]
.Pp
.Ft void
.Fn TelodendriaHexDump "size_t" "char *" "char *" "void *"
.Ft void
.Fn TelodendriaMemoryHook "MemoryAction" "MemoryInfo *" "void *"
.Ft void
.Fn TelodendriaMemoryIterator "MemoryInfo *" "void *"
.Ft void
.Fn TelodendriaPrintHeader "LogConfig *"
.Sh DESCRIPTION
.Pp
This API provides the callbacks used to hook Telodendria into
the various other APIs. It exists primarily to be called by
.Fn main ,
but these functions are not static so that
.Fn
main can be in a separate compilation unit.
.Pp
.Va TelodendriaLogo
and
.Va TelodendriaHeader
are
.Va TELODENDRIA_LOGO_HEIGHT
by
.Va TELODENDRIA_LOGO_WIDTH
and
.Va TELODENDRIA_HEADER_HEIGHT
by
.Va TELODENDRIA_HEADER_WIDTH
character arrays, respectively. They hold C strings that
are used to generate the logo and header.
.Sy NOTE:
the Telodendria logo belong solely to the Telodendria
project. If this code is modified and distributed as a
package other than the official Telodendria source
package, the logo must be replaced with a different
one, or removed entirely. Consult the license section
of
.Xr Telodendria 7
for details.
.Pp
.Fn TelodendriaHexDump
follows the function prototype required by the
.Fn MemoryHexDump
function, documented in
.Xr Memory 3 .
This function is responsible for outputting memory
hex dumps to the log.
Its fourth parameter is cast to a LogConfig object,
so one should be passed into the
.Fn MemoryHexDump
function.
.Pp
.Fn TelodendriaMemoryIterator
follows the function prototype required by the
.Fn MemoryIterate
function, documented in
.Xr Memory 3 .
This function is executed at the end of the program's
execution and detects leaks that occurred during normal
operation.
.Pp
.Fn TelodendriaMemoryHook
follows the function prototype required by the
.Fn MemoryHook
function, documented in
.Xr Memory 3 .
This function is executed every time an allocation,
re-allocation, or free occurs, and is responsible for
logging memory operations to the log.
.Pp
.Fn TelodendriaPrintHeader
prints the logo and header, along with the copyright
year and holder, and version number out to the log.
.Sh RETURN VALUES
.Pp
None of the functions in this API return anything.
.Sh SEE ALSO
.Xr Memory 3 ,
.Xr Log 3

View File

@ -1,95 +0,0 @@
.Dd $Mdocdate: December 10 2022 $
.Dt TELODENDRIACONFIG 3
.Os Telodendria Project
.Sh NAME
.Nm TelodendriaConfig
.Nd Parse the configuration file into a structure.
.Sh SYNOPSIS
.In TelodendriaConfig.h
.Ft TelodendriaConfig *
.Fn TelodendriaConfigParse "HashMap *" "LogConfig *"
.Ft void
.Fn TelodendriaConfigFree "TelodendriaConfig *"
.Sh DESCRIPTION
.Pp
Validate and maintain the Telodendria server's configuration data. This API
builds on the JSON API to add Telodendria-specific parsing. It takes a
fully-parsed JSON object and converts it into a TelodendriaConfig, which is
much more structured and easier to work with than the JSON. The config
structure is not opaque like many other structures in Telodendria. This is
intentional; defining functions for all of the fields would just add a lot
of unecessary overhead. The structure is defined as follows:
.Bd -literal -offset indent
typedef struct TelodendriaConfig
{
char *serverName;
char *baseUrl;
char *identityServer;
char *uid;
char *gid;
char *dataDir;
unsigned short listenPort;
unsigned int flags;
unsigned int threads;
unsigned int maxConnections;
size_t maxCache;
char *logTimestamp;
int logLevel;
} TelodendriaConfig;
.Ed
.Pp
Since the configuration will live in memory for a long time, it is important
that unused values are freed as soon as possible. Therefore, the Telodendria
structure is not opaque; values are accessed directly, and they can be
freed as the program wishes. Do note that if you're going to free a value, you
should set it to NULL, because
.Fn TelodendriaConfigFree
will unconditionally call
.Fn Free
on all values.
.Pp
The flags variable in this structure is a bit field that contains the OR-ed values
of any of the given flags:
.Bd -literal -offset indent
typedef enum TelodendriaConfigFlag
{
TELODENDRIA_FEDERATION,
TELODENDRIA_REGISTRATION,
TELODENDRIA_LOG_COLOR,
TELODENDRIA_LOG_FILE,
TELODENDRIA_LOG_STDOUT,
TELODENDRIA_LOG_SYSLOG
} TelodendriaConfigFlag;
.Ed
.Pp
Do note that the actual values of these enums are omitted, but they can be
OR-ed together and added to flags.
.Pp
.Fn TelodendriaConfigParse
parses a JSON map, extracting the necessary values, validating them, and then
adding them to a new TelodendriaConfig for future use by the program. All values
are copied, so the JSON hash map can be safely freed if this function
succeeds. It takes a working log configuration so that messages can be written
to the log as the parsing progresses, to warn users about default values and
report errors, for example.
.Pp
.Fn TelodendriaConfigFree
frees all of the memory allocated for the given configuration. This function
unconditionally calls
.Fn Free
on all items in the structure, so make sure that items that were already freed
are NULL.
.Sh RETURN VALUES
.Pp
.Fn TelodendriaConfigParse
returns a TelodendriaConfig that is completely independent of the passed
configuration hash map, or NULL if one or more required values is missing, or
there was some other error while parsing the configuration.
.Sh SEE ALSO
.Xr Json 3

View File

@ -1,123 +0,0 @@
.Dd $Mdocdate: March 7 2023 $
.Dt UIA 3
.Os Telodendria Project
.Sh NAME
.Nm Uia
.Nd User Interactive Authentication API.
.Sh SYNOPSIS
.In Uia.h
.Ft UiaStage *
.Fn UiaStageBuild "char *" "HashMap *"
.Ft Array *
.Fn UiaDummyFlow "void"
.Ft void
.Fn UiaCleanup "MatrixHttpHandlerArgs *"
.Ft int
.Fn UiaComplete "Array *" "HttpServerContext *" "Db *" "HashMap *" "HashMap **" "TelodendriaConfig *"
.Ft void
.Fn UiaFlowsFree "Array *"
.Sh DESCRIPTION
.Nm
takes care of all the logic for performing user interactive
authentication as defined by the Matrix specification. API endpoints
that require authentication via user interactive authentication
build up flows and any necessary parameters, and pass them into
.Fn UiaComplete ,
which validates
.Dv auth
objects and maintains session state to track the progress of a
client through the user interactive authentication flows. The idea
is that an API endpoint will not progress until user interactive
authentication has succeeded.
.Nm
makes it easy for the numerous API endpoints that utilize this
authentication mechanism to implement it.
.Pp
.Fn UiaStageBuild
builds a single stage. A stage consists of a string identifying its
type, which is used to instruct the client as to what should be
done, and parameters, which is a JSON object that contains
implementation-specific parameters for completing the stage. This
function takes those two parameters in that order.
.Pp
.Fn UiaDummyFlow
builds a flow that consists only of a dummy stage. This is useful
when an endpoint is required to use user interactive authentication,
but doesn't actually want to require the user to do anything. Since
the dummy flow is a pretty common flow, it seemed sensible to have
a function for it. Other flows are built by the caller that wishes
to perform user interactive authentication.
.Pp
.Fn UiaCleanup
should be called periodically to purge old sessions. Session are
only valid for a few minutes after their last access. After that, they
should be purged so the database doesn't fill up with session files.
This function is specifically designed to be called via
.Xr Cron 3 .
.Pp
.Fn UiaComplete
does the bulk of the work for user interactive authentication. It
takes many paramters:
.Bl -bullet
.It
An array of arrays of stages. Stages should be created with
.Fn UiaStageBuild ,
and then put into an array to create a flow. Those flows should then
be put into an array and passed as this paramter. Do note that
because of the loose typing of Telodendria's Array API, it is very
easy to make mistakes here; if you are implementing a new route that
requires user interactive authentication, then refer to an existing
route so you can see how it works.
.It
An HTTP server context. This is required to set the response headers
in the event of an error.
.It
The database where user interactive authentication sessons are
persisted.
.It
The JSON request body that contains the client's
.Dv auth
object, which will be read, parsed, and handled as appropriate.
.It
A pointer to a pointer where a JSON response can be placed if
necessary. If
.Fn UiaComplete
encounters a client error, such as a failure to authenticate, or
outstanding stages that have not been completed, it will place a
JSON response here that is expected to be returned to the client.
This response will include a description of all the flows, stages,
and their parameters.
.It
A valid Telodendria configuration structure, because a few values
are read from the configuration during certain stages of the
authentication.
.El
.Pp
.Fn UiaFlowsFree
frees an array of flows, as described above. Even though the
caller constructs this array, it is convenient to free it in its
entirety in a single function call.
.Sh RETURN VALUES
.Pp
.Fn UiaStageBuild
returns an opaque structure that represents a user interactive
authentication stage, and any parameters the client needs to complete
it. It may return NULL if there is an error allocating memory.
.Pp
.Fn UiaDummyFlow
returns an array that represents a dummy authentication flow, or
NULL if it could not allocate memory for it.
.Pp
.Fn UiaComplete
returns an integer less than zero if it experiences an internal
failure, such as a failure to allocate memory, or a corrupted
database. It returns 0 if the client has remaining stages to
complete. In this case, it will have set the response headers
and the passed response pointer, so the caller should immediately
return the response to the client. This function returns 1 if the
user has successfully completed all stages. Only in this case shall
the caller proceed with its logic.
.Sh SEE ALSO
.Xr User 3 ,
.Xr Db 3 ,
.Xr Cron 3

View File

@ -1,219 +0,0 @@
.Dd $Mdocdate: March 6 2023 $
.Dt USER 3
.Os Telodendria Project
.Sh NAME
.Nm User
.Nd Convenience functions for working with local users.
.Sh SYNOPSIS
.In User.h
.Ft int
.Fn UserValidate "char *" "char *"
.Ft int
.Fn UserHistoricalValidate "char *" "char *"
.Ft int
.Fn UserExists "Db *" "char *"
.Ft User *
.Fn UserCreate "Db *" "char *" "char *"
.Ft User *
.Fn UserLock "Db *" "char *"
.Ft User *
.Fn UserAuthenticate "Db *" "char *"
.Ft int
.Fn UserUnlock "User *"
.Ft UserLoginInfo *
.Fn UserLogin "User *" "char *" "char *" "char *" "int"
.Ft char *
.Fn UserGetName "User *"
.Ft int
.Fn UserCheckPassword "User *" "char *"
.Ft int
.Fn UserSetPassword "User *" "char *"
.Ft int
.Fn UserDeactivate "User *"
.Ft HashMap *
.Fn UserGetDevices "User *"
.Ft UserAccessToken *
.Fn UserGenerateAccessToken "User *" "char *" "int"
.Ft int
.Fn UserAccessTokenSave "Db *" "UserAccessToken *"
.Ft void
.Fn UserAccessTokenFree "UserAccessToken *"
.Ft int
.Fn UserDeleteToken "User *" "char *"
.Ft int
.Fn UserDeleteTokens "User *"
.Ft UserId *
.Fn UserIdParse "char *" "char *"
.Ft void
.Fn UserIdFree "UserId *"
.Sh DESCRIPTION
The
.Nm
API provides a wrapper over the database and offers an easy way for managing
local users. It supports all of the locking mechanisms that the database does,
and provides features for authenticating local users, among other tasks.
.Pp
.Bd -literal -offset indent
typedef struct UserLoginInfo
{
UserAccessToken *accessToken;
char *refreshToken;
} UserLoginInfo;
typedef struct UserAccessToken
{
char *user;
char *string;
char *deviceId;
long lifetime;
} UserAccessToken;
typedef struct UserId
{
char *localpart;
char *server;
} UserId;
.Ed
.Pp
.Fn UserValidate
takes a localpart and domain as separate parameters and validates it against the
rules of the Matrix specification. The reason the domain is required is because
the spec imposes limitations on the length of the user name, and the longer the
domain name is, the shorter the local part can be. This function is used to
ensure that client-provided localparts are valid on this server.
.Fn UserHistoricalValidate
is called the exact same way, except it is a little more lenient. It is used to
validate user parts on other servers, since some usernames might exist that are
not fully spec compliant, but remain in use due to historical reasons.
.Pp
.Fn UserExists
takes a localpart and checks whether or not it exists in the database.
.Pp
.Fn UserCreate
creates a new user. It takes a localpart, which is assumed to be valid, and
a password.
.Pp
.Fn UserLock
takes a localpart and obtains a database reference to the user represented by that
localpart. It behaves analogously to
.Fn DbLock ,
and in fact uses it under the hood to ensure that the user can only be modified
by the thread that has locked the user.
.Fn UserUnlock
returns the user reference back to the database. It uses
.Fn DbUnlock
under the hood.
.Pp
.Fn UserAuthenticate
takes an access token, figures out what user it belongs to, and returns the
reference to that user. This function should be used by most endpoints that
require valid user authentication, since most endpoints are authenticated via
access tokens.
.Pp
.Fn UserLogin
is used for logging in a user. It takes the user's password, device ID, device
display name, and a boolean value indicating whether or not the client supports
refresh tokens. This function logs in the user and generates an access token to be
returned to the client.
.Pp
.Fn UserGetName
gets the name attached to a user object. It can be used for the few cases where
it's necessary to know the localpart of a user.
.Pp
.Fn UserCheckPassword
takes a password and verifies it against a user object. Telodendria does not
store passwords in plain text, so this function hashes the password and and
checks it against what's stored in the database.
.Pp
.Fn UserSetPassword
resets the given user's password by hashing a plain text password and
storing it in the database.
.Pp
.Fn UserDeactivate
deactivates a user such that it can no longer be used to log in, but
the username is still taken. This is to prevent future users from
pretending to be previous users of a given localpart.
.Pp
.Fn UserGetDevices
fetches the devices that belong to the user, in JSON format,
identical to what's stored in the database. In fact, this JSON is
still linked to the database, so it should not be freed with
.Fn JsonFree .
.Pp
.Fn UserAccessTokenGenerate ,
.Fn UserAccessTokenSave ,
and
.Fn UserAccessTokenFree
are used for managing individual access tokens on a user. They
operate on the UserAccessToken structure.
.Fn UserAccessTokenGenerate
takes the user localpart to generate the token for, the device ID,
for the token, and a boolean value indicating whether or not the token
should expire.
.Fn UserAccessTokenSave
writes the access token to the database.
.Pp
.Fn UserDeleteToken
and
.Fn UserDeleteTokens
delete a specific access token/refresh token pair, or all the access
and refresh tokens for a given user, respectively.
.Pp
.Fn UserIdParse
parses either a localpart or a fully-qualified Matrix ID.
.Fn UserIdFree
frees the result of this parsing.
.Sh RETURN VALUES
.Pp
.Fn UserValidate ,
.Fn UserHistoricalValidate ,
.Fn UserExists ,
.Fn UserUnlock ,
.Fn UserCheckPassword ,
.Fn UserSetPassword ,
.Fn UserDeactivate ,
.Fn UserAccessTokenSave ,
.Fn UserDeleteToken ,
and
.Fn UserDeleteTokens
all return a boolean value. Non-zero values indicate success, and zero values
indicate failure.
.Pp
.Fn UserCreate ,
.Fn UserLock ,
and
.Fn UserAuthenticate
return a pointer to a User, or NULL if an error occurred.
.Pp
.Fn UserGetName
returns a pointer to the string that holds the localpart of the user represented
by the given user pointer. This pointer should not be freed by the caller , as it
is used internally and will be freed when the user is unlocked.
.Pp
.Fn UserLogin
returns a UserLoginInfo struct, or
.Dv NULL
if something goes wrong.
All this information should be returned to the client that is logging in. If the
client doesn't support refresh tokens, then refreshToken will be NULL.
.Pp
.Fn UserGetDevices
returns a JSON object that is linked to the database, or NULL if
there was an error. The result should not be freed with
.Fn JsonFree
because it is still directly attached to the database. This object
is an exact representation of what is stored on the disk.
.Pp
.Fn UserAccessTokenGenerate
generates an access token structure that should be freed when it is
no longer needed, or
.Dv NULL
if there was a memory error.
.Pp
.Fn UserIdParse
returns a UserId structure that should be freed when it is no longer
needed, or
.Dv NULL
if there was a memory error.
.Sh SEE ALSO
.Xr Db 3

View File

@ -1,101 +0,0 @@
.Dd $Mdocdate: February 15 2023 $
.Dt UTIL 3
.Os Telodendria Project
.Sh NAME
.Nm Util
.Nd Some misc. helper functions that don't need their own headers.
.Sh SYNOPSIS
.In Util.h
.Ft unsigned long
.Fn UtilServerTs "void"
.Ft unsigned long
.Fn UtilLastModified "char *"
.Ft int
.Fn UtilMkdir "const char *" "const mode_t"
.Ft int
.Fn UtilSleepMillis "long"
.Ft size_t
.Fn UtilParseBytes "char *"
.Ft ssize_t
.Fn UtilGetDelim "char **" "size_t *" "int" "FILE *"
.Ft ssize_t
.Fn UtilGetLine "char **" "size_t *" "FILE *"
.Sh DESCRIPTION
.Pp
This header holds a number of random functions related to strings,
time, and other tasks that don't require a full API, just one or
two functions. For the most part, the functions here are entirely
standalone, depending only on POSIX functions, however there are a
few that specifically utilize Telodendria APIs. Those are noted.
.Pp
.Fn UtilServerTs
gets the current time in milliseconds since the Unix epoch. This
uses
.Xr gettimeofday 2
and time_t, and converts it to a single number, which is then
returned to the caller. A note on the 2038 problem: as long as
sizeof(long) >= 8, that is, as long as the long datatype is 64 bits
or more, which it is on all modern 64-bit Unix-like operating
systems, then everything should be fine. Expect Telodendria on 32 bit
machines to break in 2038. I didn't want to try to hack together
some system to store larger numbers than the architecture supports.
We can always re-evaluate things over the next decade.
.Pp
.Fn UtilMkdir
behaves just like the system call
.Xr mkdir 2 ,
but it creates any intermediate directories if necessary, unlike
.Xr mkdir 2 .
.Pp
.Fn UtilSleepMillis
sleeps the calling thread for the given number of milliseconds. It
occurred to me that POSIX does not specify a super friendly way to
sleep, so this is a wrapper around the POSIX
.Xr nanosleep 2
designed to make its usage much, much simpler.
.Pp
.Fn UtilLastModified
uses
.Xr stat 2
to get the last modified time of the given file. This is used
primarily for caching file data.
.Pp
.Fn UtilParseBytes
is a highly specialized function used in parsing the configuration file.
It takes in a string which is supposed to represent a number of bytes.
It must consist of an integer, followed by an optional suffix of k, K, m, M,
g, or G, indicating the value is kilobytes, megabytes, or gigabytes.
.Pp
.Fn UtilGetDelim
and
.Fn UtilGetLine
work identically to the POSIX equivalents, documented in
.Xr getdelim 3 ,
except it assumes pointers were allocated using the Memory API, and it
uses the Memory API itself to reallocate necessary pointers.
.Sh RETURN VALUES
.Pp
.Fn UtilServerTs
and
.Fn UtilLastModified
return timestamps in the form of milliseconds since the Unix epoch as an unsigned
long. The Matrix specification requires timestamps be in milliseconds, so these
functions are designed to make that easy and convenient.
.Pp
.Fn UtilMkdir
returns 0 on success, and -1 on failure, just like
.Xr mkdir 2 .
It also sets errno as appropriate.
.Pp
.Fn UtilSleepMillis
returns the result of calling
.Xr nanosleep 2 .
.Pp
.Fn UtilParseBytes
returns a number of bytes, or 0 if there was an error parsing the byte string.
.Pp
.Fn UtilGetDelim
and
.Fn UtilGetLine
return the same value as their POSIX equivalents, documented in
.Xr getdelim 3 .