libjuice

repository·master·Indexed 20 days ago

https://github.com/paullouisageneau/libjuice

A lightweight, dependency-free, and cross-platform C library for UDP Interactive Connectivity Establishment (ICE), enabling NAT traversal for bidirectional UDP streams. It supports STUN, TURN relaying, IPv4/IPv6 dual-stack, SDP-based interfaces, and TCP candidates. The library provides a simplified implementation of the ICE protocol for both client and server sides, including support for ICE Consent freshness and ICE Patiently Awaiting Connectivity.

Tokens
1.8K
Snippets
8
Records
13
Agent score
70%

What's inside libjuice

  1. Overview of libjuice

    master

    libjuice is a C library designed for UDP Interactive Connectivity Establishment (ICE). It enables bidirectional UDP streams through Network Address Translator (NAT) traversal.

    Key features include:

    • A simplified implementation of the ICE protocol (client and server side).
    • Support for STUN (RFC5389 / RFC8489) and TURN relaying (RFC5766 / RFC8656).
    • IPv4 and IPv6 dual-stack support.
    • SDP-based interface (RFC8839).
    • Support for TCP candidates (RFC6544).
    • ICE Consent freshness (RFC7675) and ICE Patiently Awaiting Connectivity (RFC 8863).

    Limitations:

    • Only UDP is supported as a transport protocol.
    • Only one component is supported per session (sufficient for WebRTC Data Channels or multiplexed RTP+RTCP).
    • Only RFC8828 mode 2 is supported (default route + all local addresses).
  2. Install and build libjuice with CMake

    master

    You can build libjuice using CMake. The build produces two targets: libjuice (shared library) and libjuice-static (static library). When integrating with other CMake projects, use the namespaces LibJuice::LibJuice and LibJuice::LibJuiceStatic to link the library.

    POSIX-compliant systems (Linux, macOS)

    $ cmake -B build
    $ cd build
    $ make -j2

    Windows (Microsoft Visual C++)

    $ cmake -B build -G "NMake Makefiles"
    $ cd build
    $ nmake

    Windows (MinGW cross-compilation)

    $ cmake -B build -DCMAKE_TOOLCHAIN_FILE=/usr/share/mingw/toolchain-x86_64-w64-mingw32.cmake
    $ cd build
    $ make -j2
  3. Build the libjuice fuzzer with CMake

    master

    Use CMake to build the fuzzer. You must enable the FUZZER option and pass the environment variables configured in the previous step to the CMake command line to ensure correct instrumentation and linking.

    $ mkdir build
    $ cd build
    $ cmake -DCMAKE_BUILD_TYPE=Debug -DFUZZER=ON -DCMAKE_C_COMPILER=$CC \
    -DCMAKE_C_FLAGS=$CFLAGS -DCMAKE_EXE_LINKER_FLAGS=$CFLAGS \
    -DLIB_FUZZING_ENGINE=$LIB_FUZZING_ENGINE \
    ../
  4. Configure environment for building the libjuice fuzzer

    master

    To build the fuzzer with sanitizers enabled (AddressSanitizer and Fuzzer engine), you must export specific compiler and flag environment variables. This ensures the build system uses clang and applies the necessary instrumentation for fuzzing.

    export CC=clang
    export CXX=clang++
    export CFLAGS=-fsanitize=fuzzer-no-link,address
    export LIB_FUZZING_ENGINE=-fsanitize=fuzzer
    export LDFLAGS=-fsanitize=address
  5. Configure libjuice with Nettle for SHA algorithms

    master

    By default, libjuice uses an internal implementation for HMAC-SHA1. You can optionally use the Nettle library to provide SHA1 and SHA256 algorithms instead.

    # Using CMake
    $ cmake -B build -DUSE_NETTLE=1
    $ cd build
    $ make -j2
    
    # Using Make (Linux only)
    $ make USE_NETTLE=1
  6. Add credentials to the libjuice server

    master

    You can authorize users by adding credentials to the server. This allows the server to process TURN requests from specific users.

    • server_add_credentials(juice_server_t *server, const juice_server_credentials_t *credentials, timediff_t lifetime): Adds a set of credentials to the server's internal list. The lifetime parameter determines how long these credentials remain valid.
    juice_server_credentials_t creds = { ... };
    int result = server_add_credentials(server, &creds, lifetime_in_ms);
  7. Handle STUN and TURN protocol processing

    master

    The server API provides low-level functions to process incoming STUN/TURN messages. These are typically called within a server's main loop or dispatch mechanism to handle specific protocol methods:

    • server_dispatch_stun(...): Dispatches a buffer as a STUN message.
    • server_process_turn_allocate(...): Processes TURN allocation requests.
    • server_process_turn_create_permission(...): Processes TURN permission creation.
    • server_process_turn_channel_bind(...): Processes TURN channel binding.
    • server_process_turn_send(...): Processes TURN send requests.
    • server_process_channel_data(...): Processes incoming channel data.
  8. Send data and STUN messages from the server

    master

    The server provides methods to send raw data or structured STUN messages to specific destinations.

    • server_send(juice_server_t *agent, const addr_record_t *dst, const char *data, size_t size): Sends raw data to the destination address specified in dst.
    • server_stun_send(juice_server_t *server, const addr_record_t *dst, const stun_message_t *msg, const char *password): Sends a STUN message to the destination. The password can be NULL if no authentication is required for this specific message.
  9. Retrieve server port and nonces

    master

    Use these functions to interact with clients requesting identity or authentication information.

    • server_get_port(juice_server_t *server): Returns the UDP port the server is currently listening on.
    • server_get_nonce(juice_server_t *server, const addr_record_t *src, char *nonce): Generates and populates a nonce for the client at address src. This is used for STUN authentication.