Squashed 'third_party/rawrtc/rawrtc-common/' content from commit aff7a3a3b

Change-Id: I2cb019410e8d0e1e0bf814577b0ef83aeb32c7fd
git-subtree-dir: third_party/rawrtc/rawrtc-common
git-subtree-split: aff7a3a3b9bbf49f7d2fc8b123edd301825b3e1c
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..6dc68c8
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,184 @@
+version: 2
+
+shared:
+  host: &shared-host
+    working_directory: ~/rawrtc-common
+    steps:
+      - checkout
+
+      # Configure library
+      - run:
+          name: Configure
+          command: |
+            mkdir build
+            meson build --prefix /tmp/prefix
+
+      # Build library
+      - run:
+          name: Build
+          command: |
+            cd build
+            ninja install
+
+  cross: &shared-cross
+    working_directory: ~/rawrtc-common
+    steps:
+      - checkout
+
+      # Configure library
+      - run:
+          name: Configure
+          command: |
+            mkdir build
+            meson build --prefix /tmp/prefix --cross-file ${CROSS_FILE_NAME}
+
+      # Build library
+      - run:
+          name: Build
+          command: |
+            cd build
+            ninja install
+
+
+jobs:
+   # Host: Ubuntu 14.04 LTS
+  trusty-gcc:
+    <<: *shared-host
+    docker:
+      - image: rawrtc/ci-image:trusty
+    environment:
+      CC: gcc
+  trusty-clang:
+    <<: *shared-host
+    docker:
+      - image: rawrtc/ci-image:trusty
+    environment:
+      CC: clang
+      
+  # Host: Ubuntu 16.04 LTS
+  xenial-gcc:
+    <<: *shared-host
+    docker:
+      - image: rawrtc/ci-image:xenial
+    environment:
+      CC: gcc
+  xenial-clang:
+    <<: *shared-host
+    docker:
+      - image: rawrtc/ci-image:xenial
+    environment:
+      CC: clang
+      
+  # Host: Ubuntu 18.04 LTS
+  bionic-gcc:
+    <<: *shared-host
+    docker:
+      - image: rawrtc/ci-image:bionic
+    environment:
+      CC: gcc
+  bionic-clang:
+    <<: *shared-host
+    docker:
+      - image: rawrtc/ci-image:bionic
+    environment:
+      CC: clang
+
+  # Host: Arch Linux
+  archlinux-gcc:
+    <<: *shared-host
+    docker:
+      - image: rawrtc/ci-image:archlinux
+    environment:
+      CC: gcc
+  archlinux-clang:
+    <<: *shared-host
+    docker:
+      - image: rawrtc/ci-image:archlinux
+    environment:
+      CC: clang
+
+  # Cross: Linux ARMv6
+  linux-armv6:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:linux-armv6
+
+  # Cross: Linux ARMv7
+  linux-armv7:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:linux-armv7
+
+  # Cross: Android API 16 ARM
+  android-16-arm:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:android-16-arm
+
+  # Cross: Android API 16 x86
+  android-16-x86:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:android-16-x86
+
+  # Cross: Android API 28 ARM
+  android-28-arm:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:android-28-arm
+
+  # Cross: Android API 28 ARM64
+  android-28-arm64:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:android-28-arm64
+
+  # Cross: Android API 28 x86
+  android-28-x86:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:android-28-x86
+
+  # Cross: Android API 28 x86_64
+  android-28-x86_64:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:android-28-x86_64
+
+  # Cross: Windows x86
+  windows-x86:
+    <<: *shared-cross
+    docker:
+      - image: rawrtc/cross-build:windows-x86
+
+  # Cross: Windows x64
+  #windows-x64:
+  #  <<: *shared-cross
+  #  docker:
+  #    - image: rawrtc/cross-build:windows-x64
+
+
+workflows:
+  version: 2
+
+  # Build all
+  build:
+    jobs:
+      - trusty-gcc
+      - trusty-clang
+      - xenial-gcc
+      - xenial-clang
+      - bionic-gcc
+      - bionic-clang
+      - archlinux-gcc
+      - archlinux-clang
+      - linux-armv6
+      - linux-armv7
+      - android-16-arm
+      - android-16-x86
+      - android-28-arm
+      - android-28-arm64
+      - android-28-x86
+      - android-28-x86_64
+      - windows-x86
+      #- windows-x64
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..97ce43f
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,74 @@
+---
+BasedOnStyle: LLVM
+Language: Cpp
+AlignAfterOpenBracket: AlwaysBreak
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: DontAlign
+AlignOperands: true
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Empty
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+BinPackArguments: true
+BinPackParameters: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Attach
+BreakBeforeTernaryOperators: true
+BreakInheritanceList: BeforeColon
+BreakStringLiterals: true
+ColumnLimit: 100
+CommentPragmas: '^ IWYU pragma:'
+ContinuationIndentWidth: 4
+DerivePointerAlignment: false
+DisableFormat: false
+ForEachMacros:
+  - LIST_FOREACH
+IncludeBlocks: Preserve
+IncludeCategories:
+  - Regex: '^"[^\.]+'
+    Priority: 1
+  - Regex: '^"\.\./'
+    Priority: 2
+  - Regex: '^<rawrtcc'
+    Priority: 3
+  - Regex: '^<re\.h'
+    Priority: 4
+  - Regex: '.*'
+    Priority: 5
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: true
+IndentPPDirectives: AfterHash
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 6000
+PointerAlignment: Left
+ReflowComments: true
+SortIncludes: true
+SpaceAfterCStyleCast: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+TabWidth: 4
+UseTab: Never
+...
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f332ef2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,47 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+
+# Var
+/var
+
+# Build folders
+/build*
+/docs/_build
+/docs/_xml
+
+# Generated files
+/docs/Doxyfile
+/docs/conf.py
+
+# Subprojects
+/subprojects/re
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..dd200dc
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,29 @@
+# Build matrix
+language: c
+matrix:
+  include:
+    # Mac OS 10.13 (default)
+    - os: osx
+      osx_image: xcode9.4
+      compiler: clang
+
+    # Mac OS 10.13 (latest)
+    - os: osx
+      osx_image: xcode10.1
+      compiler: clang
+
+# Dependencies
+addons:
+  homebrew:
+    packages:
+      - meson
+      - ninja
+    update: true
+
+# Build library
+script:
+  - |
+    mkdir build
+    meson build --prefix /tmp/prefix
+    cd build
+    ninja install
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..56c9808
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,24 @@
+# Changelog
+
+## [0.1.3] (2019-10-15)
+
+* Regression fix for defining the debug level
+
+## [0.1.2] (2019-08-15)
+
+* Fix overriding of the debug level via `RAWRTC_DEBUG_MODULE_LEVEL`
+
+## [0.1.1] (2019-03-10)
+
+* Remove unused struct
+
+## [0.1.0] (2019-03-02)
+
+* Initial release of common functionality required by RAWRTC and RAWRTCDC
+
+
+
+[0.1.3]: https://github.com/rawrtc/rawrtc-common/compare/v0.1.2...v0.1.3
+[0.1.2]: https://github.com/rawrtc/rawrtc-common/compare/v0.1.1...v0.1.2
+[0.1.1]: https://github.com/rawrtc/rawrtc-common/compare/v0.1.0...v0.1.1
+[0.1.0]: https://github.com/rawrtc/rawrtc-common/compare/f2e07ac61bc6947ba1466ea3a7e3e91758bb9ab2...v0.1.0
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..34a8d75
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+BSD 2-Clause License
+
+Copyright (c) 2018, Lennart Grahl
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1393680
--- /dev/null
+++ b/README.md
@@ -0,0 +1,48 @@
+# RAWRTCC
+
+[![CircleCI build status][circleci-badge]][circleci-url]
+[![Travis CI build status][travis-ci-badge]][travis-ci-url]
+[![Join our chat on Gitter][gitter-icon]][gitter]
+
+Contains common functionality required by both [RAWRTC][rawrtc] and
+[RAWRTCDC][rawrtcdc].
+
+## Prerequisites
+
+The following tools are required:
+
+* [git][git]
+* [meson][meson] >= 0.46.0
+* [ninja][ninja] >= 1.5
+* Optional: pkg-config (`pkgconf` for newer FreeBSD versions)
+
+## Build
+
+```bash
+cd <path-to-rawrtcc>
+mkdir build
+meson build
+cd build
+ninja
+```
+
+## Contributing
+
+When creating a pull request, it is recommended to run `format-all.sh` to
+apply a consistent code style.
+
+
+
+[circleci-badge]: https://circleci.com/gh/rawrtc/rawrtc-common.svg?style=shield
+[circleci-url]: https://circleci.com/gh/rawrtc/rawrtc-common
+[travis-ci-badge]: https://travis-ci.org/rawrtc/rawrtc-common.svg?branch=master
+[travis-ci-url]: https://travis-ci.org/rawrtc/rawrtc-common
+[gitter]: https://gitter.im/rawrtc/Lobby
+[gitter-icon]: https://badges.gitter.im/rawrtc/Lobby.svg
+
+[rawrtc]: https://github.com/rawrtc/rawrtc
+[rawrtcdc]: https://github.com/rawrtc/rawrtc-data-channel
+
+[git]: https://git-scm.com
+[meson]: https://mesonbuild.com
+[ninja]: https://ninja-build.org
diff --git a/RELEASING.md b/RELEASING.md
new file mode 100644
index 0000000..30100ec
--- /dev/null
+++ b/RELEASING.md
@@ -0,0 +1,39 @@
+# Release Process
+
+Signing key: https://lgrahl.de/pub/pgp-key.txt
+
+1. Set variables:
+
+   ```bash
+   export VERSION=<version>
+   export GPG_KEY=3FDB14868A2B36D638F3C495F98FBED10482ABA6
+   ```
+
+2. Update version number in `meson.build` and `CHANGELOG.md`. Also, update the
+   URL with the corresponding tags.
+
+3. Do a signed commit and signed tag of the release:
+
+   ```bash
+   git add meson.build CHANGELOG.md
+   git commit -S${GPG_KEY} -m "Release v${VERSION}"
+   git tag -u ${GPG_KEY} -m "Release v${VERSION}" v${VERSION}
+   ```
+
+4. Push.
+
+   ```bash
+   git push && git push --tags
+   ```
+
+5. Create a new release on GitHub.
+
+6. Prepare CHANGELOG.md for upcoming changes:
+
+   ```md
+    ## [Unreleased] (YYYY-MM-DD)
+
+    * ...
+   ```
+
+7. Pat yourself on the back and celebrate!
diff --git a/format-all.sh b/format-all.sh
new file mode 100755
index 0000000..ba846ae
--- /dev/null
+++ b/format-all.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+for dir in "include" "src"; do
+    pushd "${dir}" &>/dev/null
+    find . \
+        -type f \
+        \( -name "*.c" -o -name "*.h" \) \
+        -exec clang-format -i '{}' \;
+    popd &>/dev/null
+done
diff --git a/include/meson.build b/include/meson.build
new file mode 100644
index 0000000..6a4e5e9
--- /dev/null
+++ b/include/meson.build
@@ -0,0 +1,3 @@
+# Install headers
+install_headers(files('rawrtcc.h'))
+subdir('rawrtcc')
diff --git a/include/rawrtcc.h b/include/rawrtcc.h
new file mode 100644
index 0000000..fe6c26f
--- /dev/null
+++ b/include/rawrtcc.h
@@ -0,0 +1,6 @@
+#pragma once
+#include "rawrtcc/config.h"
+
+#include "rawrtcc/code.h"
+#include "rawrtcc/message_buffer.h"
+#include "rawrtcc/utils.h"
diff --git a/include/rawrtcc/code.h b/include/rawrtcc/code.h
new file mode 100644
index 0000000..08051e7
--- /dev/null
+++ b/include/rawrtcc/code.h
@@ -0,0 +1,64 @@
+#pragma once
+
+/// Return codes.
+///
+/// To make it easy to test for errors, the *success* return code's
+/// value will always be `0`. Therefore, you can test for errors
+/// in the following way:
+///
+///     enum rawrtc_code const error = rawrtc_some_function();
+///     if (error) {
+///        // Handle the error...
+///     }
+///
+/// **Important**: Add translations for new return codes in
+/// `utils/utils.c`!
+enum rawrtc_code {
+    /// An unknown (or non-translatable) error occurred.
+    RAWRTC_CODE_UNKNOWN_ERROR = -2,
+    /// The necessary functionality has not been implemented.
+    RAWRTC_CODE_NOT_IMPLEMENTED = -1,
+    /// Success! Nothing went wrong - you're fine to proceed.
+    RAWRTC_CODE_SUCCESS = 0,
+    /// Initialisation failed.
+    RAWRTC_CODE_INITIALISE_FAIL,
+    /// Invalid argument.
+    RAWRTC_CODE_INVALID_ARGUMENT,
+    /// Memory could not be allocated.
+    RAWRTC_CODE_NO_MEMORY,
+    /// Invalid state.
+    RAWRTC_CODE_INVALID_STATE,
+    /// Unsupported protocol.
+    RAWRTC_CODE_UNSUPPORTED_PROTOCOL,
+    /// Unsupported algorithm.
+    RAWRTC_CODE_UNSUPPORTED_ALGORITHM,
+    /// No value has been set.
+    /// @note This is often used for functions that change the value of
+    ///       a variable declared outside of the function to indicate
+    ///       that no change occurred.
+    RAWRTC_CODE_NO_VALUE,
+    /// Socket could not be found.
+    RAWRTC_CODE_NO_SOCKET,
+    /// Invalid certificate.
+    RAWRTC_CODE_INVALID_CERTIFICATE,
+    /// Invalid fingerprint.
+    RAWRTC_CODE_INVALID_FINGERPRINT,
+    /// Insufficient space.
+    RAWRTC_CODE_INSUFFICIENT_SPACE,
+    /// Target is still being used.
+    RAWRTC_CODE_STILL_IN_USE,
+    /// Invalid message.
+    RAWRTC_CODE_INVALID_MESSAGE,
+    /// Message is too long.
+    RAWRTC_CODE_MESSAGE_TOO_LONG,
+    /// Try again later.
+    /// @note This is semantically equivalent to `EAGAIN` and
+    ///       `EWOULDBLOCK`.
+    RAWRTC_CODE_TRY_AGAIN_LATER,
+    /// Stopped iterating (early).
+    RAWRTC_CODE_STOP_ITERATION,
+    /// Operation not permitted.
+    RAWRTC_CODE_NOT_PERMITTED,
+    /// An external function returned an error.
+    RAWRTC_CODE_EXTERNAL_ERROR,
+};
diff --git a/include/rawrtcc/config.h.in b/include/rawrtcc/config.h.in
new file mode 100644
index 0000000..852178e
--- /dev/null
+++ b/include/rawrtcc/config.h.in
@@ -0,0 +1,12 @@
+#pragma once
+
+/// Current version of the library.
+///
+/// Follows [Semantic Versioning 2.0.0](https://semver.org)
+#mesondefine RAWRTCC_VERSION
+#mesondefine RAWRTCC_VERSION_MAJOR
+#mesondefine RAWRTCC_VERSION_MINOR
+#mesondefine RAWRTCC_VERSION_PATCH
+
+/// Debug level
+#mesondefine RAWRTC_DEBUG_LEVEL
diff --git a/include/rawrtcc/debug.h b/include/rawrtcc/debug.h
new file mode 100644
index 0000000..c4c75de
--- /dev/null
+++ b/include/rawrtcc/debug.h
@@ -0,0 +1,29 @@
+// Module level overwrites global level if present
+#ifdef RAWRTC_DEBUG_MODULE_LEVEL
+#    define DEBUG_LEVEL 0
+#    if RAWRTC_DEBUG_MODULE_LEVEL == 1
+#        define DEBUG_LEVEL 1
+#    elif RAWRTC_DEBUG_MODULE_LEVEL == 2
+#        define DEBUG_LEVEL 2
+#    elif RAWRTC_DEBUG_MODULE_LEVEL == 3
+#        define DEBUG_LEVEL 3
+#    elif RAWRTC_DEBUG_MODULE_LEVEL == 4
+#        define DEBUG_LEVEL 4
+#    elif RAWRTC_DEBUG_MODULE_LEVEL == 5
+#        define DEBUG_LEVEL 5
+#    elif RAWRTC_DEBUG_MODULE_LEVEL == 6
+#        define DEBUG_LEVEL 6
+#    elif RAWRTC_DEBUG_MODULE_LEVEL == 7
+#        define DEBUG_LEVEL 7
+#    endif
+#else
+#    ifndef RAWRTC_DEBUG_LEVEL
+#        pragma message "RAWRTC_DEBUG_LEVEL is not defined!"
+#    endif
+#    define DEBUG_LEVEL RAWRTC_DEBUG_LEVEL
+#endif
+
+#include <re_dbg.h>
+
+// Undef for next module
+#undef RAWRTC_DEBUG_MODULE_LEVEL
\ No newline at end of file
diff --git a/include/rawrtcc/meson.build b/include/rawrtcc/meson.build
new file mode 100644
index 0000000..c62ee95
--- /dev/null
+++ b/include/rawrtcc/meson.build
@@ -0,0 +1,15 @@
+# Generate configuration header
+configure_file(
+    input: 'config.h.in',
+    output: 'config.h',
+    configuration: configuration,
+    install_dir: '/'.join([get_option('includedir'), 'rawrtcc']))
+
+# Install headers
+includes = files([
+    'code.h',
+    'debug.h',
+    'message_buffer.h',
+    'utils.h',
+])
+install_headers(includes, subdir: 'rawrtcc')
diff --git a/include/rawrtcc/message_buffer.h b/include/rawrtcc/message_buffer.h
new file mode 100644
index 0000000..2385770
--- /dev/null
+++ b/include/rawrtcc/message_buffer.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "code.h"
+#include <re.h>
+
+/// Handler for buffered messages.
+///
+/// Return `true` if the message has been handled successfully and can
+/// be unlinked, `false` to stop processing messages and keep the current
+/// message in the list.
+typedef bool(rawrtc_message_buffer_handler)(
+    struct mbuf* const buffer, void* const context, void* const arg);
+
+/// Create a message buffer and add it to a list.
+enum rawrtc_code rawrtc_message_buffer_append(
+    struct list* const message_buffer,
+    struct mbuf* const buffer,  // referenced
+    void* const context  // referenced, nullable
+);
+
+/// Apply a receive handler to buffered messages.
+///
+/// Will stop iterating and return `RAWRTC_CODE_STOP_ITERATION` in case
+/// the message handler returned `false`.
+enum rawrtc_code rawrtc_message_buffer_clear(
+    struct list* const message_buffer,
+    rawrtc_message_buffer_handler* const message_handler,
+    void* arg);
diff --git a/include/rawrtcc/utils.h b/include/rawrtcc/utils.h
new file mode 100644
index 0000000..8c798eb
--- /dev/null
+++ b/include/rawrtcc/utils.h
@@ -0,0 +1,19 @@
+#pragma once
+#include "code.h"
+
+/// Translate a rawrtc return code to a string.
+char const* rawrtc_code_to_str(enum rawrtc_code const code);
+
+/// Translate an re error to a rawrtc code.
+enum rawrtc_code rawrtc_error_to_code(const int code);
+
+/// Duplicate a string.
+/// `*destinationp` will be set to a copy of `source` and must be
+/// unreferenced.
+enum rawrtc_code rawrtc_strdup(
+    char** const destinationp,  // de-referenced
+    char const* const source);
+
+/// Print a formatted string to a dynamically allocated buffer.
+/// `*destinationp` must be unreferenced.
+enum rawrtc_code rawrtc_sdprintf(char** const destinationp, char* const formatter, ...);
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..421df4b
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,79 @@
+# Project definition
+project('rawrtcc', 'c',
+    version: '0.1.3',
+    default_options: ['c_std=c99'],
+    meson_version: '>=0.46.0')
+
+# Set compiler warning flags
+compiler = meson.get_compiler('c')
+compiler_args = compiler.get_supported_arguments([
+    '-Wall',
+    '-Wmissing-declarations',
+    '-Wmissing-prototypes',
+    '-Wstrict-prototypes',
+    '-Wbad-function-cast',
+    '-Wsign-compare',
+    '-Wnested-externs',
+    '-Wshadow',
+    '-Waggregate-return',
+    '-Wcast-align',
+    '-Wextra',
+    '-Wold-style-definition',
+    '-Wdeclaration-after-statement',
+    '-Wuninitialized',
+    '-Wshorten-64-to-32',
+    '-pedantic',
+])
+add_project_arguments(compiler_args, language: 'c')
+
+# Configuration
+configuration = configuration_data()
+
+# Dependency: re
+# Note: We need to force using our own fork until re has accepted all our patches
+re_dep = dependency('librawrre',
+    version: '>=0.6.0',
+    fallback: ['re', 're_dep'],
+    required: true)
+
+# Dependencies list
+dependencies = [
+    re_dep,
+]
+
+# Version
+version = meson.project_version()
+version_array = version.split('.')
+configuration.set_quoted('RAWRTCC_VERSION', version)
+configuration.set('RAWRTCC_VERSION_MAJOR', version_array[0])
+configuration.set('RAWRTCC_VERSION_MINOR', version_array[1])
+configuration.set('RAWRTCC_VERSION_PATCH', version_array[2])
+
+# Set debug level
+configuration.set('RAWRTC_DEBUG_LEVEL', get_option('debug_level'))
+
+# Includes
+include_dir = include_directories('include')
+subdir('include')
+
+# Sources
+subdir('src')
+
+# Build library
+rawrtcc = library(meson.project_name(), sources,
+    dependencies: dependencies,
+    include_directories: include_dir,
+    install: true,
+    version: version)
+
+# Declare dependency
+rawrtcc_dep = declare_dependency(
+    include_directories: include_dir,
+    link_with: rawrtcc)
+
+# Generate pkg-config file
+pkg = import('pkgconfig')
+pkg.generate(rawrtcc,
+    name: meson.project_name(),
+    description: 'Common code used in RAWRTC projects.',
+    url: 'https://github.com/rawrtc/rawrtc-common')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..c0c8d72
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,2 @@
+option('debug_level', type: 'integer', min: 0, max: 7, value: 5,
+    description: 'Global debug level', yield: true)
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..15aec96
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,4 @@
+sources = []
+
+subdir('message_buffer')
+subdir('utils')
diff --git a/src/message_buffer/buffer.c b/src/message_buffer/buffer.c
new file mode 100644
index 0000000..75004f1
--- /dev/null
+++ b/src/message_buffer/buffer.c
@@ -0,0 +1,99 @@
+#include <rawrtcc/code.h>
+#include <rawrtcc/message_buffer.h>
+#include <re.h>
+
+/*
+ * Message buffer.
+ */
+struct buffered_message {
+    struct le le;
+    struct mbuf* buffer;  // referenced
+    void* context;  // referenced, nullable
+};
+
+/*
+ * Destructor for an existing buffered message.
+ */
+static void rawrtc_message_buffer_destroy(void* arg) {
+    struct buffered_message* const buffered_message = arg;
+
+    // Un-reference
+    mem_deref(buffered_message->context);
+    mem_deref(buffered_message->buffer);
+}
+
+/*
+ * Create a message buffer and add it to a list.
+ *
+ * TODO: Add timestamp to be able to ignore old messages
+ */
+enum rawrtc_code rawrtc_message_buffer_append(
+    struct list* const message_buffer,
+    struct mbuf* const buffer,  // referenced
+    void* const context  // referenced, nullable
+) {
+    struct buffered_message* buffered_message;
+
+    // Check arguments
+    if (!message_buffer || !buffer) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Create buffered message
+    buffered_message = mem_zalloc(sizeof(*buffered_message), rawrtc_message_buffer_destroy);
+    if (!buffered_message) {
+        return RAWRTC_CODE_NO_MEMORY;
+    }
+
+    // Set fields
+    buffered_message->buffer = mem_ref(buffer);
+    buffered_message->context = mem_ref(context);
+
+    // Add to list
+    list_append(message_buffer, &buffered_message->le, buffered_message);
+    return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Apply a receive handler to buffered messages.
+ *
+ * Will stop iterating and return `RAWRTC_CODE_STOP_ITERATION` in case
+ * the message handler returned `false`.
+ */
+enum rawrtc_code rawrtc_message_buffer_clear(
+    struct list* const message_buffer,
+    rawrtc_message_buffer_handler* const message_handler,
+    void* arg) {
+    struct le* le;
+    bool unlink;
+
+    // Check arguments
+    if (!message_buffer || !message_handler) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Handle each message
+    le = list_head(message_buffer);
+    while (le != NULL) {
+        struct buffered_message* const buffered_message = le->data;
+
+        // Handle message
+        unlink = message_handler(buffered_message->buffer, buffered_message->context, arg);
+        if (unlink) {
+            list_unlink(le);
+        }
+
+        // Get next message
+        le = le->next;
+
+        // Remove message
+        if (unlink) {
+            mem_deref(buffered_message);
+        } else {
+            return RAWRTC_CODE_STOP_ITERATION;
+        }
+    }
+
+    // Done
+    return RAWRTC_CODE_SUCCESS;
+}
diff --git a/src/message_buffer/meson.build b/src/message_buffer/meson.build
new file mode 100644
index 0000000..c95a347
--- /dev/null
+++ b/src/message_buffer/meson.build
@@ -0,0 +1 @@
+sources += files('buffer.c')
diff --git a/src/utils/meson.build b/src/utils/meson.build
new file mode 100644
index 0000000..d82c551
--- /dev/null
+++ b/src/utils/meson.build
@@ -0,0 +1 @@
+sources += files('utils.c')
diff --git a/src/utils/utils.c b/src/utils/utils.c
new file mode 100644
index 0000000..d837a60
--- /dev/null
+++ b/src/utils/utils.c
@@ -0,0 +1,109 @@
+#include <rawrtcc/code.h>
+#include <rawrtcc/utils.h>
+#include <re.h>
+#include <stdarg.h>  // va_*
+
+/*
+ * Translate a rawrtc return code to a string.
+ */
+char const* rawrtc_code_to_str(enum rawrtc_code const code) {
+    switch (code) {
+        case RAWRTC_CODE_UNKNOWN_ERROR:
+            return "unknown error";
+        case RAWRTC_CODE_NOT_IMPLEMENTED:
+            return "not implemented";
+        case RAWRTC_CODE_SUCCESS:
+            return "success";
+        case RAWRTC_CODE_INITIALISE_FAIL:
+            return "failed to initialise";
+        case RAWRTC_CODE_INVALID_ARGUMENT:
+            return "invalid argument";
+        case RAWRTC_CODE_NO_MEMORY:
+            return "no memory";
+        case RAWRTC_CODE_INVALID_STATE:
+            return "invalid state";
+        case RAWRTC_CODE_UNSUPPORTED_PROTOCOL:
+            return "unsupported protocol";
+        case RAWRTC_CODE_UNSUPPORTED_ALGORITHM:
+            return "unsupported algorithm";
+        case RAWRTC_CODE_NO_VALUE:
+            return "no value";
+        case RAWRTC_CODE_NO_SOCKET:
+            return "no socket";
+        case RAWRTC_CODE_INVALID_CERTIFICATE:
+            return "invalid certificate";
+        case RAWRTC_CODE_INVALID_FINGERPRINT:
+            return "invalid fingerprint";
+        case RAWRTC_CODE_INSUFFICIENT_SPACE:
+            return "insufficient space";
+        case RAWRTC_CODE_STILL_IN_USE:
+            return "still in use";
+        case RAWRTC_CODE_INVALID_MESSAGE:
+            return "invalid message";
+        case RAWRTC_CODE_MESSAGE_TOO_LONG:
+            return "message too long";
+        case RAWRTC_CODE_TRY_AGAIN_LATER:
+            return "try again later";
+        case RAWRTC_CODE_STOP_ITERATION:
+            return "stop iteration";
+        case RAWRTC_CODE_NOT_PERMITTED:
+            return "not permitted";
+        case RAWRTC_CODE_EXTERNAL_ERROR:
+            return "external callback error-ed";
+        default:
+            return "(no error translation)";
+    }
+}
+
+/*
+ * Translate an re error to a rawrtc code.
+ * TODO: Add codes from trice_lcand_add
+ */
+enum rawrtc_code rawrtc_error_to_code(int const code) {
+    switch (code) {
+        case 0:
+            return RAWRTC_CODE_SUCCESS;
+        case EAGAIN:
+#if (EAGAIN != EWOULDBLOCK)
+        case EWOULDBLOCK:
+#endif
+            return RAWRTC_CODE_TRY_AGAIN_LATER;
+        case EAUTH:
+            return RAWRTC_CODE_INVALID_CERTIFICATE;
+        case EBADMSG:
+            return RAWRTC_CODE_INVALID_MESSAGE;
+        case EINVAL:
+            return RAWRTC_CODE_INVALID_ARGUMENT;
+        case EMSGSIZE:
+            return RAWRTC_CODE_MESSAGE_TOO_LONG;
+        case ENOMEM:
+            return RAWRTC_CODE_NO_MEMORY;
+        case EPERM:
+            return RAWRTC_CODE_NOT_PERMITTED;
+        default:
+            return RAWRTC_CODE_UNKNOWN_ERROR;
+    }
+}
+
+/*
+ * Duplicate a string.
+ * `*destinationp` will be set to a copy of `source` and must be
+ * unreferenced.
+ */
+enum rawrtc_code rawrtc_strdup(char** const destinationp, char const* const source) {
+    int err = str_dup(destinationp, source);
+    return rawrtc_error_to_code(err);
+}
+
+/*
+ * Print a formatted string to a dynamically allocated buffer.
+ * `*destinationp` must be unreferenced.
+ */
+enum rawrtc_code rawrtc_sdprintf(char** const destinationp, char* const formatter, ...) {
+    int err;
+    va_list args;
+    va_start(args, formatter);
+    err = re_vsdprintf(destinationp, formatter, args);
+    va_end(args);
+    return rawrtc_error_to_code(err);
+}
diff --git a/subprojects/re.wrap b/subprojects/re.wrap
new file mode 100644
index 0000000..329ac5a
--- /dev/null
+++ b/subprojects/re.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory = re
+url = https://github.com/rawrtc/re.git
+revision = 9384f3a5f38a03c871270fda566045b3bf57bbee