forked from lda/telodendria
Remove obsolete documentation.
This commit is contained in:
parent
e0c94d7bd2
commit
a08018870e
23 changed files with 0 additions and 2710 deletions
132
man/man3/Array.3
132
man/man3/Array.3
|
@ -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
|
|
|
@ -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.
|
|
|
@ -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
|
|
|
@ -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.
|
|
121
man/man3/Db.3
121
man/man3/Db.3
|
@ -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.
|
|
|
@ -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
|
|
186
man/man3/Http.3
186
man/man3/Http.3
|
@ -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¶m2=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
|
|
|
@ -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
|
|
263
man/man3/Json.3
263
man/man3/Json.3
|
@ -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
|
|
155
man/man3/Log.3
155
man/man3/Log.3
|
@ -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.
|
|
|
@ -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.
|
|
|
@ -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
|
|
|
@ -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.
|
|
||||||
|
|
100
man/man3/Queue.3
100
man/man3/Queue.3
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
123
man/man3/Uia.3
123
man/man3/Uia.3
|
@ -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
|
|
219
man/man3/User.3
219
man/man3/User.3
|
@ -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
|
|
101
man/man3/Util.3
101
man/man3/Util.3
|
@ -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 .
|
|
Loading…
Reference in a new issue