aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Timber <dxdt@dev.snart.me>2022-06-02 12:19:11 +0800
committerDavid Timber <dxdt@dev.snart.me>2022-06-02 12:19:11 +0800
commit31e7acb5c965067463f33fa59fc463086a298350 (patch)
tree921df7d673b812255da0bca13b967930a498a7ff
parent80a062ef30a2f945f6634ca9a0bf2b886a54e3ae (diff)
Doc and final touches ...
- Add .settings.json for doxygen settings - Add /doc/impl.md - Doc and change usage of /bootstrap.sh - Add notes to docs - Add 7-bit char machine check - Normailise description for init and free functions - Doc rest of source code - Remove unused function: prne_str_shift_spaces()
-rw-r--r--.vscode/settings.json10
-rw-r--r--README.md1
-rwxr-xr-xbootstrap.sh11
-rw-r--r--doc/dev_notes.md12
-rw-r--r--doc/impl.md106
-rw-r--r--doc/sws.md3
-rw-r--r--doc/user_guide.md2
-rw-r--r--src/bne.h10
-rw-r--r--src/config.h6
-rw-r--r--src/cred_dict.h10
-rw-r--r--src/dvault.h11
-rw-r--r--src/htbt.h10
-rw-r--r--src/protocol.h99
-rw-r--r--src/pth.h11
-rw-r--r--src/recon.h10
-rw-r--r--src/resolv.h40
-rw-r--r--src/rnd.h10
-rw-r--r--src/strmap.h10
-rw-r--r--src/util_ct.h108
-rw-r--r--src/util_rt.c49
-rw-r--r--src/util_rt.h411
-rw-r--r--templates/doxygen12
22 files changed, 753 insertions, 199 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..ebf6b4b
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,10 @@
+{
+ "doxdocgen.cpp.tparamTemplate": "\\tparam {param} ",
+ "doxdocgen.file.fileTemplate": "\\file {name}",
+ "doxdocgen.generic.briefTemplate": "\\brief {text}",
+ "doxdocgen.generic.dateTemplate": "\\date {date}",
+ "doxdocgen.generic.paramTemplate": "\\param {param} ",
+ "doxdocgen.generic.returnTemplate": "\\return {type} ",
+ "doxdocgen.file.versionTag": "\\version 0.1",
+ "doxdocgen.generic.authorTag": "\\author {author} ({email})"
+} \ No newline at end of file
diff --git a/README.md b/README.md
index fd75067..8f12957 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@ Where to go from here
* [User Guide](doc/user_guide.md)
* [Software Design Spec](doc/sws.md)
+* [Implementation Note](doc/impl.md)
* [Heartbeat Protocol Spec](doc/htbt.md)
* [Proone Data Format Spec](doc/fmts.md)
* [Dev Notes](doc/dev_notes.md)
diff --git a/bootstrap.sh b/bootstrap.sh
index d6d0946..141ff9d 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -1,4 +1,15 @@
#!/bin/sh
+if [ $# -ne 0 ]; then
+ cat >&2 << EOF
+Bootstrap the project directory for Autoconf and Automake. Run this script after
+making changes to .ac and .am files.
+Usage: $0
+
+The script requires no arguments in order to run.
+EOF
+ exit 2
+fi
+
aclocal &&
automake --add-missing --copy &&
autoconf &&
diff --git a/doc/dev_notes.md b/doc/dev_notes.md
index 10843c5..544606a 100644
--- a/doc/dev_notes.md
+++ b/doc/dev_notes.md
@@ -1,5 +1,10 @@
# Proone Dev Notes
+## Debugging
+### Capabilities(7)
+Both gdb and the executable to debug must have `CAP_NET_RAW` set in order for
+BNE to work.
+
## Platform-specifics
### Erasing arguments passed to Proone
The Proone instance processes may look suspicious because the cmdline string
@@ -37,7 +42,12 @@ to real threads, expect some race condition related bugs.
### Put Mbed TLS on Diet
The build is not light because the Mbed TLS library is extensive. Proone is
tested using default Mbed TLS config included in Buildroot, but size reduction
-may be achieved by disabling unnessary features like threading and DTLS support.
+may be achieved by disabling unnessary features.
+
+* Threading
+* DTLS
+* TLS Renegotiation
+* ZLIB
### Don't Build Clean-up Code
Disabling clean-up code for release build is widely accepted technique to reduce
diff --git a/doc/impl.md b/doc/impl.md
new file mode 100644
index 0000000..2d598ef
--- /dev/null
+++ b/doc/impl.md
@@ -0,0 +1,106 @@
+# Proone Implementation Note
+## Dynamic Memory Allocation
+POSIX compliant dynamic memory functions may return a valid pointer that can be
+passed to `free()`(MALLOC(3)). Proone does not appreciate this inconsistency as
+it has to be tolerant to memory allocation failure.
+
+Consider following snippet.
+
+```c
+int *get_int_arr (size_t n) {
+ int *ret = (int*)calloc(sizeof(int), n);
+
+ if (ret == NULL) {
+ abort();
+ }
+
+ for (size_t i = 0; i < n; i += 1) {
+ ret[i] = i % INT_MAX;
+ }
+
+ return ret;
+}
+```
+
+The behaviour of this code depends on whether `calloc()` returns a null or valid
+pointer for zero-length allocation. To avoid mistakes like this one, the memory
+allocation functions of the Proone framework(prefixed `prne_`) always returns
+NULL for zero-length allocation. This way, the implementation is forced to infer
+memory allocation failure from the parameter and the return value.
+
+```c
+ if (n > 0 && ret == NULL) {
+```
+
+All the memory allocated using the framework allocaiton functions(`prne_*()`)
+must be freed with `prne_free()`.
+
+## Resource Allocation Hook
+One of the purposes of `prne_free()` and `prne_close()` is to facilitate the
+implementation of a framework-level resource debugging(like MSVC macros) in the
+future. This may be useful when use of Valgrind becomes too cumbersome. Another
+is to keep a registry of the file descriptors for use in `prefork()` and
+`atfork()` equivalent.
+
+## Resource Allocation
+### Transparent Structures
+
+```c
+prne_init_llist()
+prne_free_llist()
+```
+
+Transparent structures must be initialised and deinitialised using the functions
+provided.
+
+The initialisation functions set the members of the structures to their default
+values and prepares the structures for the deinitialisation calls. This is
+normally done by zeroing the entire structure, but there are exceptions where
+values other than zero are used for default values.
+
+The deinitialisation functions are like "desctructors" in other languages. The
+functions free any dynamically allocated members. For the structures that have
+no dynamic members, the functions have no effect.
+
+All initialisation and deinitialisation functions must be used to ensure that
+the members added in the future are initialised/freed. Are guaranteed to take
+one argument.
+
+Deinitialised structures are not reusable. The structures must be reinitialised
+after being deinitialised.
+
+### Opaque Types
+
+```c
+prne_rnd_alloc_well512()
+prne_alloc_resolv()
+```
+
+Opaque types, usually poly-morphed objects(class), are dynamically allocated by
+"instantiation functions". Examples include `resolv` and `rnd`. The destructor
+functions are provided upon successful instantiation. The underlying abstraction
+layer is responsible for the invocation of the destructor functions.
+
+### Dynamic Members
+
+```c
+prne_htbt_alloc_host_info()
+prne_alloc_iobuf()
+```
+
+Some types have dynamically allocated members and the dynamic member allocation
+functions are defined for dynamic members. Dynamic members can be freed by
+calling the functions with zero for the size argument. Dynamic members are freed
+by the deinitialisation functions.
+
+### Ownership of Dynamically Resources
+Some structures have the `ownership` flag member so their dynamic members,
+especially large memory, can be used with other instances. If the structure has
+the flag and its value is set, it means that the structure is the owner of the
+dynamically allocated memory and is responsible for freeing it upon destruction
+by the deinitialisation function. If the flag is unset, the deinitialisation
+function will not free the dynamic members.
+
+The flag can be used to form a chain of structures with the same dynamic
+members. The flag can also be used to use data from .bss or .data as dynamic
+members.
diff --git a/doc/sws.md b/doc/sws.md
index c057937..fb84820 100644
--- a/doc/sws.md
+++ b/doc/sws.md
@@ -360,7 +360,8 @@ proone-htbtclient. MariaDB for DB backend.
### Executables
* /src/proone: Proone instance executable with DVault only
* /src/proone.bin: Proone instance executable ELF part only (not runnable)
-* /src/proone-bne: standalone bne tool for testing and index case(P0)
+* /src/proone-bne: standalone bne tool for testing and deployment of an index
+ case(P0)
* /src/proone-hostinfod: hostinfo daemon, an example of authoritive heartbeat
implementation
* /src/proone-htbtclient: heartbeat client, Proone instance maintenance tool
diff --git a/doc/user_guide.md b/doc/user_guide.md
deleted file mode 100644
index 7f82da5..0000000
--- a/doc/user_guide.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Proone User Guide
-TODO
diff --git a/src/bne.h b/src/bne.h
index 7436920..73b302e 100644
--- a/src/bne.h
+++ b/src/bne.h
@@ -319,15 +319,13 @@ struct prne_bne_result {
};
/**
- * \brief Initialise the BNE worker parameter object
- * \note Initialises the members of \p p to initial values. Prepares \p p so
- * that it can be freed using \c prne_free_bne_param()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_bne_param (prne_bne_param_t *p);
/**
- * \brief Free the resources allocated for the BNE worker parameter object
- * \param p The pointer to the object that has been initialised using
- * \c prne_init_bne_param()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_bne_param (prne_bne_param_t *p);
diff --git a/src/config.h b/src/config.h
index 1b2a746..79c12f0 100644
--- a/src/config.h
+++ b/src/config.h
@@ -33,12 +33,18 @@
#endif
#include "protocol.h"
+#include <limits.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <zlib.h>
+// Refuse 7-bit byte
+#if CHAR_BIT != 8
+#error "FIXME!"
+#endif
+
/** \def PRNE_HOST_WORDSIZE
* \brief Th system "word size". 32 if the system is a 32-bit machine. 64 if the
* system is a 64-bit machine.
diff --git a/src/cred_dict.h b/src/cred_dict.h
index 2528a5d..872f6ae 100644
--- a/src/cred_dict.h
+++ b/src/cred_dict.h
@@ -54,15 +54,13 @@ struct prne_cred_dict {
};
/**
- * \brief Initialise the credential dictionary object
- * \note Initialises the members of \p p to initial values. Prepares \p p so
- * that it can be freed using \c prne_free_cred_dict()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_cred_dict (prne_cred_dict_t *p);
/**
- * \brief Free the resources allocated for the credential dictionary object.
- * \param p The pointer to the object that has been initialised using
- * \c prne_init_cred_dict()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_cred_dict (prne_cred_dict_t *p);
diff --git a/src/dvault.h b/src/dvault.h
index 0f52518..ef0b907 100644
--- a/src/dvault.h
+++ b/src/dvault.h
@@ -101,16 +101,13 @@ void prne_dvault_invert_mem (
const uint8_t *mask);
/**
- * \brief Initialise the data vault masking operation result object
- * \note Initialises the members of \p r to initial values. Prepares \p r so
- * that it can be freed using \c prne_free_dvault_mask_result()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_dvault_mask_result (prne_dvault_mask_result_t *r);
/**
- * \brief Free the resources allocated for the the data vault masking operation
- * result object
- * \param p The pointer to the object that has been initialised using
- * \c prne_init_dvault_mask_result()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_dvault_mask_result (prne_dvault_mask_result_t *r);
/**
diff --git a/src/htbt.h b/src/htbt.h
index 9dc20a8..80a0c0f 100644
--- a/src/htbt.h
+++ b/src/htbt.h
@@ -210,14 +210,12 @@ struct prne_htbt_param {
prne_htbt_t *prne_alloc_htbt (prne_worker_t *w, const prne_htbt_param_t *param);
/**
- * \brief Initialise the heartbeat worker parameter object
- * \note Initialises the members of \p p to initial values. Prepares \p p so
- * that it can be freed using \c prne_htbt_free_param()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_param (prne_htbt_param_t *p);
/**
- * \brief Free the resources allocated for the heartbeat worker parameter object
- * \param p The pointer to the object that has been initialised using
- * \c prne_htbt_init_param()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_param (prne_htbt_param_t *p);
diff --git a/src/protocol.h b/src/protocol.h
index 99fb198..e730409 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -445,16 +445,13 @@ bool prne_net_ep_set_ipv6 (
const char *prne_htbt_op_tostr (const prne_htbt_op_t x);
/**
- * \brief Initialise the heartbeat framing protocol message header frame
- * \note Initialises the members of \p mh to initial values. Prepares \p mh so
- * that it can be freed using \c prne_htbt_free_msg_head()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_msg_head (prne_htbt_msg_head_t *mh);
/**
- * \brief Free the resources allocated for the heartbeat framing protocol
- * message header frame
- * \param mh The pointer to the object that has been initialised using
- * \c prne_htbt_init_msg_head()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_msg_head (prne_htbt_msg_head_t *mh);
/**
@@ -468,16 +465,13 @@ bool prne_htbt_eq_msg_head (
const prne_htbt_msg_head_t *b);
/**
- * \brief Initialise the heartbeat framing protocol status frame
- * \note Initialises the members of \p s to initial values. Prepares \p s so
- * that it can be freed using \c prne_htbt_free_status()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_status (prne_htbt_status_t *s);
/**
- * \brief Free the resources allocated for the heartbeat framing protocol status
- * frame
- * \param s The pointer to the object that has been initialised using
- * \c prne_htbt_init_status()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_status (prne_htbt_status_t *s);
/**
@@ -490,9 +484,8 @@ bool prne_htbt_eq_status (
const prne_htbt_status_t *b);
/**
- * \brief Initialise the host credential object
- * \note Initialises the members of \p hc to initial values. Prepares \p hc so
- * that it can be freed using \c prne_free_host_cred()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_host_cred (prne_host_cred_t *hc);
/**
@@ -512,9 +505,8 @@ bool prne_alloc_host_cred (
const uint8_t id_len,
const uint8_t pw_len);
/**
- * \brief Free the resources allocated for the host credential object
- * \param hc The pointer to the object that has been initialised using
- * \c prne_init_host_cred()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_host_cred (prne_host_cred_t *hc);
/**
@@ -559,9 +551,8 @@ prne_htbt_ser_rc_t prne_dec_host_cred (
prne_host_cred_t *out);
/**
- * \brief Initialise the heartbeat framing protocol hostinfo frame
- * \note Initialises the members of \p hi to initial values. Prepares \p hi so
- * that it can be freed using \c prne_htbt_free_host_info()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_host_info (prne_htbt_host_info_t *hi);
/**
@@ -572,16 +563,15 @@ void prne_htbt_init_host_info (prne_htbt_host_info_t *hi);
* \param bf_len The byte length required for the bit field data
* \return true if allocation was successful
* \return false on failure and \c errno set to \c ENOMEM
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
bool prne_htbt_alloc_host_info (
prne_htbt_host_info_t *hi,
const size_t cred_len,
const size_t bf_len);
/**
- * \brief Free the resources allocated for the heartbeat framing protocol
- * hostinfo frame
- * \param hi The pointer to the object that has been initialised using
- * \c prne_htbt_init_host_info()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_host_info (prne_htbt_host_info_t *hi);
/**
@@ -594,9 +584,8 @@ bool prne_htbt_eq_host_info (
const prne_htbt_host_info_t *b);
/**
- * \brief Initialise the heartbeat framing protocol command frame
- * \note Initialises the members of \p cmd to initial values. Prepares \p cmd so
- * that it can be freed using \c prne_htbt_free_cmd()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_cmd (prne_htbt_cmd_t *cmd);
/**
@@ -615,10 +604,8 @@ bool prne_htbt_alloc_cmd (
const size_t *args_len);
bool prne_htbt_set_cmd (prne_htbt_cmd_t *cmd, const char **args);
/**
- * \brief Free the resources allocated for the heartbeat framing protocol
- * command frame
- * \param cmd The pointer to the object that has been initialised using
- * \c prne_htbt_init_cmd()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_cmd (prne_htbt_cmd_t *cmd);
/**
@@ -629,16 +616,13 @@ void prne_htbt_free_cmd (prne_htbt_cmd_t *cmd);
bool prne_htbt_eq_cmd (const prne_htbt_cmd_t *a, const prne_htbt_cmd_t *b);
/**
- * \brief Initialise the heartbeat framing protocol binary meta frame
- * \note Initialises the members of \p nb to initial values. Prepares \p nb so
- * that it can be freed using \c prne_htbt_free_bin_meta()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_bin_meta (prne_htbt_bin_meta_t *nb);
/**
- * \brief Free the resources allocated for the the heartbeat framing protocol
- * binary meta frame
- * \param nb The pointer to the object that has been initialised using
- * \c prne_htbt_init_bin_meta()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_bin_meta (prne_htbt_bin_meta_t *nb);
/**
@@ -652,16 +636,13 @@ bool prne_htbt_eq_bin_meta (
const prne_htbt_bin_meta_t *b);
/**
- * \brief Initialise the heartbeat framing protocol hand-over frame
- * \note Initialises the members of \p ho to initial values. Prepares \p ho so
- * that it can be freed using \c prne_htbt_free_hover()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_hover (prne_htbt_hover_t *ho);
/**
- * \brief Free the resources allocated for the heartbeat framing protocol
- * hand-over frame
- * \param ho The pointer to the object that has been initialised using
- * \c prne_htbt_init_hover()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_hover (prne_htbt_hover_t *ho);
/**
@@ -685,16 +666,13 @@ bool prne_htbt_cp_hover (
prne_htbt_hover_t *dst);
/**
- * \brief Initialise the heartbeat framing protocol STDIO frame
- * \note Initialises the members of \p s to initial values. Prepares \p s so
- * that it can be freed using \c prne_htbt_free_stdio()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_stdio (prne_htbt_stdio_t *s);
/**
- * \brief Free the resources allocated for the heartbeat framing protocol STDIO
- * frame
- * \param s The pointer to the object that has been initialised using
- * \c prne_htbt_init_stdio()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_stdio (prne_htbt_stdio_t *s);
/**
@@ -707,16 +685,13 @@ bool prne_htbt_eq_stdio (
const prne_htbt_stdio_t *b);
/**
- * \brief Initialise the heartbeat protocol binary RCB frame
- * \note Initialises the members of \p r to initial values. Prepares \p r so
- * that it can be freed using \c prne_htbt_free_rcb()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_init_rcb (prne_htbt_rcb_t *r);
/**
- * \brief Free the resources allocated for the heartbeat protocol binary RCB
- * frame
- * \param r The pointer to the object that has been initialised using
- * \c prne_htbt_init_rcb()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_htbt_free_rcb (prne_htbt_rcb_t *r);
/**
diff --git a/src/pth.h b/src/pth.h
index 5321f8b..fc46a34 100644
--- a/src/pth.h
+++ b/src/pth.h
@@ -50,16 +50,13 @@ typedef struct prne_pth_cv prne_pth_cv_t;
/**
- * \brief Initialise the worker object
- * \note Initialises the members of \p w to initial values. Prepares \p w so
- * that it can be freed using \c prne_free_worker()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_worker (prne_worker_t *w);
/**
- * \brief Free the resources allocated for the worker object
- * \param w The pointer to the object that has been initialised using
- * \c prne_init_worker()
- * \warning The worker has to be joined using \c pth_join() beforehand!
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_worker (prne_worker_t *w);
/**
diff --git a/src/recon.h b/src/recon.h
index ede9600..5fa6e25 100644
--- a/src/recon.h
+++ b/src/recon.h
@@ -84,15 +84,13 @@ prne_recon_t *prne_alloc_recon (
mbedtls_ctr_drbg_context *ctr_drbg,
const prne_recon_param_t *param);
/**
- * \brief Initialise the recon worker parameter object
- * \note Initialises the members of \p p to initial values. Prepares \p p so
- * that it can be freed using \c prne_free_recon_param()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_recon_param (prne_recon_param_t *p);
/**
- * \brief Free the resources allocated for the recon worker parameter object
- * \param p The pointer to the object that has been initialised using
- * \c prne_init_recon_param()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_recon_param (prne_recon_param_t *p);
/**
diff --git a/src/resolv.h b/src/resolv.h
index f823410..f671d21 100644
--- a/src/resolv.h
+++ b/src/resolv.h
@@ -287,15 +287,13 @@ bool prne_resolv_prm_gettxtrec (
prne_resolv_prm_t *out);
/**
- * \brief Initialise the name server pool object
- * \note Initialises the members of \p pool to initial values. Prepares \p pool
- * so that it can be freed using \c prne_resolv_free_ns_pool()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_resolv_init_ns_pool (prne_resolv_ns_pool_t *pool);
/**
- * \brief Free the resources allocated for the name server pool object
- * \param pool The pointer to the object that has been initialised using
- * \c prne_resolv_init_ns_pool()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_resolv_free_ns_pool (prne_resolv_ns_pool_t *pool);
/**
@@ -318,39 +316,33 @@ prne_resolv_ns_pool_t prne_resolv_own_ns_pool(
const prne_resolv_ns_pool_t *pool,
const bool ownership);
/**
- * \brief Initialise the query operation promise object
- * \note Initialises the members of \p prm to initial values. Prepares \p prm so
- * that it can be freed using \c prne_resolv_free_prm()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_resolv_init_prm (prne_resolv_prm_t *prm);
/**
- * \brief Free the resources allocated for the query operation promise object
- * \param prm The pointer to the object that has been initialised using
- * \c prne_resolv_init_prm()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_resolv_free_prm (prne_resolv_prm_t *prm);
/**
- * \brief Initialise the query operation future object
- * \note Initialises the members of \p fut to initial values. Prepares \p fut so
- * that it can be freed using \c prne_free_resolv_fut()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_resolv_fut (prne_resolv_fut_t *fut);
/**
- * \brief Free the resources allocated for the query operation future object
- * \param fut The pointer to the object that has been initialised using
- * \c prne_init_resolv_fut()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_resolv_fut (prne_resolv_fut_t *fut);
/**
- * \brief Initialise the query resource record
- * \note Initialises the members of \p rr to initial values. Prepares \p rr so
- * that it can be freed using \c prne_free_resolv_rr()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_resolv_rr (prne_resolv_rr_t *rr);
/**
- * \brief Free the resources allocated for the query resource record
- * \param rr The pointer to the object that has been initialised using
- * \c prne_init_resolv_rr()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_resolv_rr (prne_resolv_rr_t *rr);
diff --git a/src/rnd.h b/src/rnd.h
index b414081..5287f1c 100644
--- a/src/rnd.h
+++ b/src/rnd.h
@@ -47,15 +47,13 @@ typedef struct prne_rnd prne_rnd_t;
/**
- * \brief Initialise the PRNG engine object
- * \note Initialises the members of \p p to initial values. Prepares \p p so
- * that it can be freed using \c prne_free_rnd()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_rnd (prne_rnd_t *p);
/**
- * \brief Free the resources allocated for the PRNG engine object
- * \param p The pointer to the object that has been initialised using
- * \c prne_init_rnd()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_rnd (prne_rnd_t *p);
/**
diff --git a/src/strmap.h b/src/strmap.h
index 74a6956..634fdbf 100644
--- a/src/strmap.h
+++ b/src/strmap.h
@@ -47,15 +47,13 @@ struct prne_strmap_tuple {
};
/**
- * \brief Initialise the string map object
- * \note Initialises the members of \p map to initial values. Prepares \p map so
- * that it can be freed using \c prne_free_strmap()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_init_strmap (prne_strmap_t *map);
/**
- * \brief Free the resources allocated for the string map object
- * \param map The pointer to the object that has been initialised using
- * \c prne_init_strmap()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
void prne_free_strmap (prne_strmap_t *map);
diff --git a/src/util_ct.h b/src/util_ct.h
index a58f170..2c2af1b 100644
--- a/src/util_ct.h
+++ b/src/util_ct.h
@@ -1,3 +1,11 @@
+/** \file
+ * \brief Compile-time utility and convenience functions
+ * \note \c _Static_assert() instead of \c static_assert() is used because some
+ * cross compilers do not support it. The use of \c _Static_assert() is
+ * still standard compliant.
+ * \note The expressions and values involved must be determinable during compile
+ * time! Basically, write what can be written using constexpr in C++.
+ */
/*
* Copyright (c) 2019-2021 David Timber <mieabby@gmail.com>
*
@@ -32,28 +40,98 @@
#include <errno.h>
#endif
+/* Log levels
+ * The default level is 1. Using the value 1(PRNE_VL_ERR or PRNE_VL_INFO) will
+ * filter out all the log levels higher than 1 showing only info, err and fatal
+ * errors only.
+ * Generally, the native uint type is used. Note that minimum width of int for C
+ * is 16-bit.
+ */
+/* Fatal error
+ * The process cannot proceed further due to a serious error. The message
+ * must be the last message the process prints before calling abort()
+ */
#define PRNE_VL_FATAL 0
+/* General error
+ * An operation or a work unit failed due to an error
+ */
#define PRNE_VL_ERR 1
+/* Info
+ * The message carries essential information. The value is the same as
+ * PRNE_VL_ERR. This is intentional - this log level should only be used for
+ * essential info messages.
+ */
#define PRNE_VL_INFO 1
+/* Warning
+ * The message is about a warning that needs the user's attention.
+ */
#define PRNE_VL_WARN 2
+/* Debug Level 0
+ * This level is the lowest possible debug log level. Use higher debug levels
+ * for more detailed data like raw packet data and diagnostic info.
+ */
#define PRNE_VL_DBG0 3
+/**
+ * \brief Limit the number of enums using static_assert()
+ */
#define PRNE_LIMIT_ENUM(t,x,l) _Static_assert((x) <= (l),"enum overflow: "#t)
+/**
+ * \brief Do \c static_assert(). This is a workaround for the problem where some
+ * compilers don't have static_assert() exposed.
+ */
#define prne_static_assert(expr, msg) _Static_assert((expr), msg)
+/**
+ * \brief Pick the smallest expression
+ */
#define prne_op_min(a, b) ((a) < (b) ? (a) : (b))
+/**
+ * \brief Pick the biggest expression
+ */
#define prne_op_max(a, b) ((a) > (b) ? (a) : (b))
+/**
+ * \brief The spaceship operator - compare \p a and \p b and return -1 if \p b
+ * is the biggest, return 1 if \p a is the biggest, return 0 if \p a and \p b
+ * are equal.
+ */
#define prne_op_spaceship(a, b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
+/**
+ * \brief Align the byte length \p x to the alignment \p align - calculate the
+ * multiple of \p align required to store the \p x bytes of data (much like
+ * ceiling function)
+ * \note Consider using APIs like \c posix_memalign() where suits. This macro is
+ * only for computation of byte size
+ */
#define prne_salign_next(x, align) \
(((x) % (align) == 0) ? (x) : ((x) / (align) + 1) * (align))
-#define prne_salign_at(x, align) \
- (((x) % (align) == 0) ? (x) : ((x) / (align)) * (align))
#if PRNE_DEBUG
+/*
+ * These macros have effect only on debug builds. The macros are disabled for
+ * release builds to prevent info leak.
+ */
+
+/**
+ * \brief The debug print function. Print the formatted message on the standard
+ * error. Effective only in debug.
+ */
#define prne_dbgpf(...) fprintf(stderr, __VA_ARGS__)
+/**
+ * \brief The \c perror() function only effective in debug.
+ */
#define prne_dbgperr(str) perror(str)
+/**
+ * \brief \c assert() macro - use \c assert() directly in debug, use \c abort()
+ * in release so the expression is not printed on the standard error.
+ */
#define prne_assert(expr) assert(expr)
+/**
+ * \brief \c assert() macro, but instead of using the expression for the error
+ * message, use the formatted message instead. The messages will not be built
+ * into release builds.
+ */
#define prne_massert(expr, ...)\
if (!(expr)) {\
fprintf(stderr, "*** ");\
@@ -61,8 +139,21 @@
fprintf(stderr, "\n");\
abort();\
}
+/**
+ * \brief Do \c assert() only in debug. This macro has no effect in release
+ * builds.
+ */
#define prne_dbgast(expr) prne_assert(expr)
+/**
+ * \brief Do \c prne_massert() only in debug. This macro has no effect in
+ * release builds.
+ */
#define prne_dbgmast(expr, ...) prne_massert(expr, __VA_ARGS__)
+/**
+ * \brief The debug trap macro. In debug mode, this macro simply acts as
+ * \c assert() In release mode, the expression is simply executed without its
+ * result evaluated by \c assert(). The macro is for non-critical assertions.
+ */
#define prne_dbgtrap(expr) prne_assert(expr)
#else
#define prne_dbgpf(...)
@@ -77,10 +168,21 @@
#define prne_dbgtrap(expr) (expr)
#endif
+/**
+ * \brief Convenience macro for assigning value to the optional parameter
+ * pointer. Dereference the pointer \p l to assign the value \p r to it only if
+ * the pointer is not NULL.
+ */
#define prne_chk_assign(l, r) \
if ((l) != NULL) {\
*(l) = (r);\
}
-// include <errno.h> if you get compilation errors
+/**
+ * \brief Test if the expression is one of the "non-blocking" errors. Include
+ * <errno.h> to use this macro. The macro is a workaround for the issue where
+ * some platforms define \c EAGAIN and \c EWOULDBLOCK as seperate values. On
+ * platforms where they represent the same value, the compiler will optimise the
+ * expression into a single equality comparison operation.
+ */
#define prne_is_nberr(expr) ((expr) == EAGAIN || (expr) == EWOULDBLOCK)
diff --git a/src/util_rt.c b/src/util_rt.c
index 95f117f..692b5ed 100644
--- a/src/util_rt.c
+++ b/src/util_rt.c
@@ -36,12 +36,11 @@
#include <pthsem.h>
-void prne_empty_func (void) {}
-
-void prne_close (const int fd) {
+int prne_close (const int fd) {
if (fd >= 0) {
- close(fd);
+ return close(fd);
}
+ return 0;
}
void prne_shutdown (const int fd, const int how) {
@@ -59,9 +58,18 @@ int prne_chfd (const int old, const int ny) {
int ret;
if (old == ny) {
+ /*
+ * dup2() will do nothing if both are same. This is not desired because
+ * the function will end up closing the original fd!
+ */
return old;
}
+ /*
+ * Be careful if you're changing this to dup3()! Using the same fd on dup2()
+ * is no op whereas dup3() considers this an invalid use case(EINVAL). The
+ * behaviour of dup2() is desired for this function.
+ */
ret = dup2(old, ny);
if (ret < 0) {
return ret;
@@ -152,15 +160,7 @@ char *prne_redup_str (char *old, const char *str) {
}
void prne_sfree_str (char *s) {
- char *p;
-
- if (s == NULL) {
- return;
- }
-
- for (p = s; *p != 0; p += 1) {
- *p = 0;
- }
+ prne_strzero(s);
prne_free(s);
}
@@ -254,6 +254,8 @@ char *prne_strnchr (const char *p, const char c, const size_t n) {
return (char*)p + i;
}
else if (p[i] == 0) {
+ // c == 0 is a valid use
+ // stop at a null terminator
return NULL;
}
}
@@ -261,27 +263,6 @@ char *prne_strnchr (const char *p, const char c, const size_t n) {
return NULL;
}
-size_t prne_str_shift_spaces (char *str, const size_t len) {
- size_t i, ret = len;
-
- for (i = 0; i < ret; ) {
- if (prne_cisspace(str[i])) {
- if (i + 1 >= ret) {
- // last trailing whitespace
- ret -= 1;
- break;
- }
- memmove(str + i, str + i + 1, ret - i - 1);
- ret -= 1;
- }
- else {
- i += 1;
- }
- }
-
- return ret;
-}
-
bool prne_chkcstr (const char *str, bool(*chk_f)(const char)) {
bool ret = true;
diff --git a/src/util_rt.h b/src/util_rt.h
index b60bedd..48af5b6 100644
--- a/src/util_rt.h
+++ b/src/util_rt.h
@@ -1,3 +1,6 @@
+/** \file
+ * \brief Runtime utility and convenience functions
+ */
/*
* Copyright (c) 2019-2021 David Timber <mieabby@gmail.com>
*
@@ -32,29 +35,183 @@
#include <mbedtls/ctr_drbg.h>
-void prne_empty_func (void);
-void prne_close (const int fd);
+/**
+ * \brief Call \c close() only if the \p fd is zero or greater to preserve
+ * \c errno
+ * \retval 0 if \p fd is less than zero (no op)
+ * \return the value returned from \c close() otherwise
+ * \see \c close()
+ * \see [/doc/impl.md#Resource Allocation Hook](/doc/impl.md#resource_allocation_hook)
+ */
+int prne_close (const int fd);
+/**
+ * \brief Call \c shutdown() only if the \p fd is zero or greater to preserve
+ * \c errno
+ * \see \c shutdown()
+ */
void prne_shutdown (const int fd, const int how);
/* prne_sck_fcntl(fd)
*
* Sets FD_CLOEXEC and O_NONBLOCK. Failure to set FD_CLOEXEC is ignored.
*/
+
+/**
+ * \brief Set the commmon socket flags associated with the fd. The common flags
+ * are \c FD_CLOEXEC and \c O_NONBLOCK
+ * \retval true if the mission critial flags(O_NONBLOCK) are successfully set
+ * \retval false otherwise. \c errno is set by \c fcntl()
+ * \warning The error occurred setting \c FD_CLOEXEC is ignored as the flag is
+ * considered non mission critial.
+ * \see \c fcntl()
+ */
bool prne_sck_fcntl (const int fd);
+/**
+ * \brief Convenience function for changing the fd to a new fd using \c dup2()
+ * Upon successful \c dup2() call, the old fd is closed and the new fd is
+ * returned.
+ * \param old The old fd
+ * \param ny The desired value for the new fd
+ * \retval -1 on error
+ * \return The new fd returned by \c dup2()
+ * \see \c dup2()
+ * \warning This function assumes that as long as the new fd stays open, closing
+ * the old fd won't block the calling thread. There might be cases where close()
+ * fails or blocks regardless?
+ * \note As per the behaviour of \c dup2(), the new fd is silently closed if if
+ * is a valid fd. Use this function if you're absolutely sure that the new fd is
+ * not used. Like setting up a pipe as standard IO(fd 0, 1 and 2).
+ */
int prne_chfd (const int old, const int ny);
+/**
+ * \brief Zero-fill the region of memory - call \c memset() with zero
+ */
void prne_memzero(void *addr, const size_t len);
-void *prne_malloc (const size_t se, const size_t cnt);
+/**
+ * \brief Safe \c malloc() - do overflow check and return NULL for zero length
+ * allocation
+ * \param se the size of an element
+ * \param cnt the number of elements
+ * \retval NULL if the size calculated is zero. \c errno left untouched
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer returned from \c malloc()
+ * \note The purpose of the functions including \c prne_realloc()
+ * \c prne_calloc() is following.
+ * - To have a version of \c malloc() that always returns NULL for zero-length
+ * allocation. A valid pointer is returned on most platforms and NULL is
+ * returned on some platforms.
+ * - Integer overflow check (especially for 16-bit machines)
+ * - To implement a memory allocation event system in the future. Valgrind might
+ * not be a suitable candidate to debug Proone and a different approach(like
+ * the one chosen for MSVCRT) could be desired.
+ * \see \c malloc()
+ */
+void *prne_malloc (const size_t se, const size_t cnt);\
+/**
+ * \brief Do \c reallocarray() See \c prne_malloc()
+ * \param ptr the pointer to the previously dynamically allocated memory
+ * acceptable by \c realloc()
+ * \param se the size of an element
+ * \param cnt the number of elements
+ * \retval NULL if the size calculated is zero. \c errno is left untouched. If
+ * \p ptr is not NULL, free() has been performed to free the memory.
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer returned from \c realloc()
+ * \note Unlike \c realloc() using this function with \p ptr to dynamically
+ * allocated memory and either of \p se or \p cnt zero has the same effect as
+ * \c free()
+ * \see \c prne_malloc()
+ */
void *prne_realloc (void *ptr, const size_t se, const size_t cnt);
+/**
+ * \brief Call \c calloc() but ensure that NULL is always returned for
+ * zero-length allocation
+ * \param se the size of an element
+ * \param cnt the number of elements
+ * \retval NULL if the size calculated is zero. \c errno left untouched
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer returned from \c calloc()
+ * \see \c prne_malloc()
+ */
void *prne_calloc (const size_t se, const size_t cnt);
+/**
+ * \brief Dynamically allocate memory for a string of the specified length. This
+ * is a convenience function for performing \c malloc(strlen(str)+1)
+ * \param len the byte length of the string excluding the null-terminator
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer to the dynamically allocated memory for storing the
+ * string of the specified length
+ * \see \c prne_realloc_str()
+ * \note Implemented using \c prne_realloc_str()
+ */
char *prne_alloc_str (const size_t len);
+/**
+ * \brief Dynamically allocate memory for a string of the specified length. This
+ * is a convenience function for performing \c realloc(ptr,strlen(str)+1)
+ * \param old the pointer to the previously dynamically allocated memory
+ * \param len the new byte length of the string excluding the null-terminator
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer to the newly dynamically allocated memory for storing the
+ * string of the specified length
+ * \note Unlike \c prne_realloc() calling this function with zero \p len won't
+ * free \p old since the length of the new string is calculated as len + 1
+ */
char *prne_realloc_str (char *old, const size_t len);
+/**
+ * \brief Make a new copy of the string. This is a convenience function for
+ * performing \c malloc(strlen(str)+1) and then \c strcpy()
+ * \retval NULL on memory allocation error, \c errno set to \c ENOMEM
+ * \return The pointer to the new copy of the string
+ * \see \c prne_redup_str()
+ * \note Implemented using \c prne_redup_str()
+ */
char *prne_dup_str (const char *str);
+/**
+ * \brief Make a new copy of the string. This is a convenience function for
+ * performing \c realloc(ptr,strlen(str)+1) and then \c strcpy()
+ * \retval NULL on memory allocation error, \c errno set to \c ENOMEM
+ * \return The pointer to the new copy of the string
+ * \see \c prne_redup_str()
+ * \note Implemented using \c prne_redup_str()
+ */
char *prne_redup_str (char *old, const char *str);
+/**
+ * \brief Scrub and free the string. For freeing strings containing sensitive
+ * data
+ */
void prne_sfree_str (char *s);
+/**
+ * \brief Do \c free()
+ * \see [/doc/impl.md#Resource Allocation Hook](/doc/impl.md#resource_allocation_hook)
+ */
void prne_free (void *ptr);
+/**
+ * \brief Do \c sysconf(_SC_PAGESIZE) Call \c abort() on failure
+ */
size_t prne_getpagesize (void);
+/**
+ * \brief Assume the ownership of the memory by doing \c realloc() if necessary.
+ * If \p ownership is unset, the function allocates new memory and copies the
+ * content of the original memory to the new memory, leaving the original memory
+ * intact. The \p ownership will always be set upon successful operation. If the
+ * flag is set, calling the function is equivalent to calling \c realloc()
+ *
+ * \param p The pointer to the pointer holding the address
+ * \param ownership The pointer to the the current ownership flag
+ * \param se The byte size of each element
+ * \param old The current number of elements
+ * \param req The number of elements requested
+ * \retval true if the operation was successful
+ * \retval false otherwise, \c errno set
+ * \see [/doc/impl.md#Ownership of Dynamically Resources](/doc/impl.md#ownership_of_dynamically_resources)
+ */
bool prne_own_realloc (
void **p,
bool *ownership,
@@ -62,101 +219,323 @@ bool prne_own_realloc (
size_t *old,
const size_t req);
-/* Locale "C" character category functions
-*/
+/* Locale "C" character category functions */
+/**
+ * \brief The POSIX locale \c toupper() that does not use any global
+ */
char prne_ctoupper (const char c);
+/**
+ * \brief The POSIX locale \c tolower() that does not use any global
+ */
char prne_ctolower (const char c);
+/**
+ * \brief The POSIX locale \c isspace() that does not use any global
+ */
bool prne_cisspace (const char c);
+/**
+ * \brief The POSIX locale \c isprint() that does not use any global
+ */
bool prne_cisprint (const char c);
-
+/**
+ * \brief Test if \p c is zero
+ */
bool prne_ciszero (const char c);
+/**
+ * \brief Test if two strings are equal, treating a null pointer as an empty
+ * string
+ */
bool prne_nstreq (const char *a, const char *b);
+/**
+ * \brief Calculate the number of non-zero characters in the string. A null
+ * pointer is treated as an empty string
+ */
size_t prne_nstrlen (const char *s);
+/**
+ * \brief Find the first occurence of a character in the string
+ *
+ * \param p The string
+ * \param c The character to look for. A null character is valid
+ * \param n The number of characters in the string
+ * \return The pointer to the original string offset to the first character
+ * found in the string
+ * \retval NULL if the character is not found in the string or a null terminator
+ * was encountered
+ */
char *prne_strnchr (const char *p, const char c, const size_t n);
-size_t prne_str_shift_spaces (char *str, const size_t len);
+/**
+ * \brief Test the string with \p chk_f
+ *
+ * \param str The string
+ * \param chk_f The test function
+ * \retval true if \p chk_f returned true for all characters in the string
+ * \retval false otherwise
+ */
bool prne_chkcstr (const char *str, bool(*chk_f)(const char));
+/**
+ * \brief Test the memory with \c chk_f
+ *
+ * \param m The memory
+ * \param len The byte length of the memory
+ * \param chk_f The test function
+ * \retval true if \p chk_f returned true for all bytes in the memory
+ * \retval false otherwise
+ */
bool prne_chkcmem (const void *m, size_t len, bool(*chk_f)(const char));
+/**
+ * \brief Transform the string using \p trans_f
+ */
void prne_transstr (char *str, int(*trans_f)(int));
+/**
+ * \brief Transform the string using \p trans_f
+ */
void prne_transcstr (char *str, char(*trans_f)(char));
+/**
+ * \brief Transform the memory using \p trans_f
+ */
void prne_transmem (void *m, size_t len, int(*trans_f)(int));
+/**
+ * \brief Transform the memory using \p trans_f
+ */
void prne_transcmem (void *m, size_t len, char(*trans_f)(char));
+/**
+ * \brief Find the last occurrence of the character in the memory
+ *
+ * \param haystack The memory
+ * \param c The character
+ * \param hs_len The byte length of the memory
+ * \return The pointer to the original string offset to the last character found
+ * in the string
+ * \retval NULL if the character is not found in the string
+ */
void *prne_memrchr (
const void *haystack,
const int c,
const size_t hs_len);
+/**
+ * \brief Find the last occurrence of the data in the memory
+ *
+ * \param haystack The memory
+ * \param hs_len The byte length of the memory
+ * \param needle The data
+ * \param n_len The byte length of the data
+ * \return The pointer to the original memory offset to the last occurrence of
+ * the data found in the memory
+ * \retval NULL if the data is not found in the memory
+ */
void *prne_memrmem (
const void *haystack,
const size_t hs_len,
const void *const needle,
const size_t n_len);
+/**
+ * \brief Find the first occurrence of the data in the memory
+ *
+ * \param haystack The memory
+ * \param hs_len The byte length of the memory
+ * \param needle The data
+ * \param n_len The byte length of the data
+ * \return The pointer to the original memory offset to the first occurrence of
+ * the data found in the memory
+ * \retval NULL if the data is not found in the memory
+ */
void *prne_memmem (
const void *haystack,
const size_t hs_len,
const void *const needle,
const size_t n_len);
+/**
+ * \brief Concatenate strings to build a new string
+ *
+ * \param arr The pointer to the array of null-terminated strings
+ * \param cnt The number of elements in \p arr
+ * \return The new string
+ * \retval NULL on error, \c errno set
+ * \see \c prne_rebuild_str()
+ */
char *prne_build_str (const char **const arr, const size_t cnt);
+/**
+ * \brief Concatenate strings to build a new string, doing \c realloc() if
+ * necessary
+ *
+ * \param arr The pointer to the array of null-terminated strings
+ * \param cnt The number of elements in \p arr
+ * \return The new/reallocated string
+ * \retval NULL on error, \c errno set
+ * \see \c prne_build_str()
+ */
char *prne_rebuild_str (void *prev, const char **const arr, const size_t cnt);
+/**
+ * \brief Scrub the string. Do nothing if \p str is NULL
+ */
void prne_strzero (char *str);
+/**
+ * \brief Parse an \c uint8_t from the hex characters
+ *
+ * \param str The pointer to an array of characters at least 2 in length
+ * \param out The output
+ * \retval true on success
+ * \retval false if the array contains invalid characters, \c errno set to
+ * \c EINVAL
+ */
bool prne_hex_fromstr (const char *str, uint_fast8_t *out);
+/**
+ * \brief Convert an \c uint8_t to hex characters
+ *
+ * \param in The value
+ * \param out The pointer to an array of characters at least 2 in length
+ * \param upper The uppercase flag. If set, uppercase characters will be used.
+ * Lowercase characters will be used otherwise.
+ */
void prne_hex_tochar (const uint_fast8_t in, char *out, const bool upper);
-/*
-* \param str: at least 36 bytes
-* \param out: at least 16 bytes
-*/
+/**
+ * \brief Parse a UUID from the string
+ *
+ * \param str The string containing a UUID, at least 36 characters long
+ * \param out The output memory, at least 16 bytes long
+ * \retval true on success
+ * \retval false on format error, \c errno set to EINVAL
+ */
bool prne_uuid_fromstr (const char *str, uint8_t *out);
-/*
-* \param in: at least 16 bytes
-* \param out: at least 37 bytes (null-terminated)
-*/
+/**
+ * \brief Convert the UUID to a null-terminated string
+ *
+ * \param in The memory of the UUID, at least 16 bytes long
+ * \param out The preallocated string for output, at least 37 characters long
+ */
void prne_uuid_tostr (const uint8_t *in, char *out);
+/**
+ * \brief Compare two UUIDs
+ *
+ * \param a The pointer to memory at least 16 bytes long
+ * \param b The pointer to memory at least 16 bytes long
+ * \return an integer less than, equal to, or greater than zero if \p a is found
+ * respectively, to be less than, to match, or be greater than \p b
+ */
int prne_cmp_uuid_asc (const void *a, const void *b);
+/**
+ * \brief Reverse function of \c prne_cmp_uuid_asc()
+ * \see \c prne_cmp_uuid_asc()
+ */
int prne_cmp_uuid_desc (const void *a, const void *b);
+/**
+ * \brief Calculate the addition of two timespec structures
+ */
struct timespec prne_add_timespec (
const struct timespec a,
const struct timespec b);
+/**
+ * \brief Calculate the subtraction of two timespec structures
+ */
struct timespec prne_sub_timespec (
const struct timespec a,
const struct timespec b);
+/**
+ * \brief Convert the timespec structure to seconds
+ */
double prne_real_timespec (const struct timespec ts);
+/**
+ * \brief Convert the timespec structure to milliseconds
+ */
long prne_timespec_ms (const struct timespec ts);
+/**
+ * \brief Construct a timespec structure from milliseconds
+ */
struct timespec prne_ms_timespec (const long ms);
+/**
+ * \brief Compare two timespec strucrures
+ * \return an integer less than, equal to, or greater than zero if \p a is found
+ * respectively, to be less than, to match, or be greater than \p b
+ */
int prne_cmp_timespec (const struct timespec a, const struct timespec b);
+/**
+ * \brief Return the timespec structure with the smallest value
+ */
struct timespec prne_min_timespec (
const struct timespec a,
const struct timespec b);
+/**
+ * \brief Return the timespec structure with the largest value
+ */
struct timespec prne_max_timespec (
const struct timespec a,
const struct timespec b);
+/**
+ * \brief Do \c clock_gettime() call, \c abort() on error
+ */
struct timespec prne_gettime (const clockid_t cid);
+/**
+ * \brief Convert a timespec structure to a timeval structure
+ */
struct timeval prne_ts2tv (const struct timespec ts);
+/**
+ * \brief Construct a timeval structure from milliseconds
+ */
struct timeval prne_ms_timeval (const long ms);
+/**
+ * \brief Encode data in Base64 in memory. Allocates memory for output
+ *
+ * \param data The data to encode
+ * \param size The byte length of the data
+ * \return The pointer to a newly allocated string containing encoded data
+ */
char *prne_enc_base64_mem (const uint8_t *data, const size_t size);
+/**
+ * \brief Decode the base64 string. Allocates memory for output
+ *
+ * \param str The input string containing base64 encoded data
+ * \param str_len The length of the input string
+ * \param data The pointer for output data
+ * \param size The pointer for the byte length of the output data
+ * \retval true on success
+ * \retval false on memory error(ENOMEM) or parsing error(EINVAL)
+ */
bool prne_dec_base64_mem (
const char *str,
const size_t str_len,
uint8_t **data,
size_t *size);
-// getrandom polyfill
+/**
+ * \brief Read \c /dev/urandom directly.
+ *
+ * \param buf The pointer to memory for output
+ * \param len The number of bytes to read
+ * \return The value returned from \c read() function. \c errno set to the value
+ * from the \c read() function
+ * \note This function is made to avoid the use of \c getrandom() which can
+ * potentially block the caller thread in the event of insufficient entropy
+ */
ssize_t prne_geturandom (void *buf, const size_t len);
+/**
+ * \brief Output the result of bitwise AND operation of the contents of two byte
+ * arrays to \p c
+ */
void prne_bitop_and (
const uint8_t *a,
const uint8_t *b,
uint8_t *c,
const size_t len);
+/**
+ * \brief Output the result of bitwise OR operation of the contents of two byte
+ * arrays to \p c
+ */
void prne_bitop_or (
const uint8_t *a,
const uint8_t *b,
uint8_t *c,
const size_t len);
+/**
+ * \brief Output the result of bitwise NOT operation of the contents of the byte
+ * array \p x to \p y
+ */
void prne_bitop_inv (
const uint8_t *x,
uint8_t *y,
diff --git a/templates/doxygen b/templates/doxygen
index 7129842..0e5293b 100644
--- a/templates/doxygen
+++ b/templates/doxygen
@@ -11,16 +11,15 @@
*/
/**
- * \brief Initialise the
- * \note Initialises the members of \p x to initial values. Prepares \p x so
- * that it can be freed using \c ff()
+ * \brief Initialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
/**
- * \brief Free the resources allocated for the
- * \param x The pointer to the object that has been initialised using
- * \c if()
+ * \brief Deinitialisation function
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
+
/**
* \brief The equality operator of the
* \retval true if the contents of both \p a and \p b are identical
@@ -38,6 +37,7 @@
* \param x The byte length required for the
* \return true if allocation was successful
* \return false on failure and \c errno set to \c ENOMEM
+ * \see [/doc/impl.md#Resource Allocation](/doc/impl.md#resource_allocation)
*/
/**