forked from Telodendria/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