ZeroTier Global Area Networking

repository·dev·Indexed 12 days ago

https://github.com/zerotier/zerotierone

A programmable, secure, peer-to-peer Ethernet virtualization layer that allows disparate devices and environments to communicate as if they were on the same local network. Documentation includes details on building manual pages, ARM NEON 32-bit ASM implementations of Salsa20/12, and the ZeroTier Central Controller Docker image.

Tokens
74.5K
Snippets
208
Records
304
Agent score
95%

What's inside ZeroTier

  1. Overview of Hiredis

    dev

    Hiredis is a minimalistic C client library for the Redis database. It provides a high-level, printf-like API for sending commands and receiving replies while maintaining a minimal code base. It supports the binary-safe Redis protocol (RESP) for Redis versions >= 1.2.0. The library offers three main APIs:

    1. Synchronous API: For blocking command execution.
    2. Asynchronous API: For non-blocking operations.
    3. Reply Parsing API: A decoupled stream parser designed for easy reusability (e.g., in higher-level language bindings).
  2. Overview of X64 ASM Salsa20/12 implementation

    dev

    The ext/x64-salsa2012-asm extension provides a high-performance X64 assembly implementation of the Salsa20/12 stream cipher. It is used within ZeroTier for packet encode/decode operations on 64-bit Linux and Mac builds.

    Note that this implementation is specialized for single-stream encryption and differs from the standard Salsa20 C++ class in that it does not support processing multiple blocks in a single call; it is designed to take a key and a single stream to perform encryption.

  3. Overview of nlohmann/json design goals

    dev

    nlohmann/json is designed for:

    • Intuitive syntax: Uses C++ operator overloading to make JSON feel like a first-class data type, similar to Python.
    • Trivial integration: Consists of a single header file (json.hpp) with no dependencies or complex build systems.
    • Serious testing: Heavily unit-tested (100% coverage), checked with Valgrind and Clang Sanitizers, and subjected to 24/7 Google OSS-Fuzz testing.

    Note on performance: While not the fastest library available, it prioritizes development speed and ease of use. It uses std::string for strings, int64_t/uint64_t/double for numbers, std::map for objects, std::vector for arrays, and bool for Booleans by default. You can customize these by templating the basic_json class.

  4. Overview of redis-plus-plus

    dev
    redis-plus-plus is a C++ client library for Redis built on top of hiredis. It provides an STL-like interface and supports C++11, C++14, and C++17 standards. It is designed to be thread-safe (unless otherwise stated) and includes support for advanced Redis features like connection pooling, scripting, clustering, and Sentinel.
  5. Use ARM NEON (32-bit) ASM implementation of Salsa20/12

    dev

    The ext/arm32-neon-salsa2012-asm extension provides a high-performance ARM NEON (32-bit) assembly implementation of the Salsa20/12 stream cipher. This implementation is significantly faster than the naive C implementation and is sourced from the supercop project by Daniel J. Bernstein.

    Usage and Availability:

    • This implementation is automatically included in 32-bit Linux ARM builds of ZeroTier.
    • Compatibility Warning: This code is specifically designed for 32-bit ARM. It is not compatible with 64-bit ARM (AArch64) architectures and will require porting to work on 64-bit platforms (such as modern mobile devices).
  6. Use the ZeroTier Node API

    dev
    The ZeroTier Node API is a platform-agnostic, plain C interface that wraps the core Node class. It allows developers to interact with the ZeroTier network virtualization engine from external applications. This API provides a consistent way to control the network engine regardless of the underlying operating system.
  7. What is the ZeroTier Network Controller?

    dev

    The Network Controller is a microservice responsible for managing ZeroTier virtual networks. Its primary duties include:

    • Admitting members to a network.
    • Issuing certificates.
    • Issuing default configuration information.

    This implementation is the reference controller used by ZeroTier's hosted services. It uses a filesystem-based JSON backend where data is stored in the controller.d directory within the ZeroTier working directory.

    Warning: Do not modify files in controller.d in place while the controller is running, as this may cause data loss. It is strongly recommended to use the Controller API for all management tasks.

  8. Core concepts of libpqxx: Connection, Transaction, and Result

    dev

    The libpqxx library is built around three primary abstractions that manage the lifecycle of a database interaction:

    1. pqxx::connection: Represents the connection to the database. The constructor parses connection options using the same format as libpq's PQconnectdb/PQconnect.
    2. pqxx::transaction: An object that operates on a connection. You will typically use the pqxx::work variety.
      • Commitment: You must explicitly call .commit() to make changes permanent. If the transaction object is destroyed without calling .commit(), the work is automatically rolled back.
      • Execution: Use the transaction's .exec(), .exec1(), .query_value(), or .stream() functions to execute SQL statements passed as strings.
    3. pqxx::result: Returned by most exec functions, this acts as a container of pqxx::row objects. Each row acts as a container of pqxx::field objects.

    Once a transaction is closed, the connection is available for a new transaction, though pqxx::result objects can generally be kept around for use after the transaction or connection is closed.

    #include <pqxx/pqxx>
    
    // Conceptual flow:
    pqxx::connection c;
    pqxx::work w(c);
    pqxx::result r = w.exec("SELECT 1");
    w.commit();
  9. Manage thread safety in libpqxx

    dev

    libpqxx does not include internal locking to protect objects from simultaneous modification. Users are responsible for ensuring that no conflicting operations occur concurrently in multi-threaded programs.

    Core Principles

    • Immutable Result Sets: Result sets are immutable and can be safely shared between multiple threads.
    • The "World" Concept: Treat a connection and all objects related to it (transactions, cursors, etc.) as a single isolated "world". You must ensure that no other thread accesses this "world" while you are performing non-const (modifying) operations within it.
    • Avoid Conflicting Operations: Do not perform concurrent operations on the same connection context, such as:
      • Issuing a query on a transaction while simultaneously opening a subtransaction.
      • Accessing a cursor while a commit operation is in progress.
    • Cursor Caution: Cursors are particularly sensitive. Because it is easy to accidentally perform a non-const operation, you should use very conservative locking if you intend to share cursors or cursor-related objects across threads.
  10. Handle Redis return types and Optional values

    dev

    Commands in redis-plus-plus return different types based on the Redis operation:

    • Void: For commands like save().
    • Standard Types: Returns std::string, bool, long long, or double directly.
    • Optional<T>: For commands that might return a NULL REPLY (e.g., GET on a non-existent key, SPOP on an empty set, or BLPOP on timeout), the library returns an Optional<T> (e.g., OptionalString, OptionalLongLong, OptionalDouble). You should check if the object is truthy before dereferencing.
    • Output Iterators: Many commands allow you to pass an output iterator (like std::back_inserter or std::inserter) to parse results directly into a container (e.g., mget, lrange, hgetall, smembers).
    // Handling an Optional return
    auto os = redis.get("kk");
    if (os) {
        std::cout << *os << std::endl;
    } else {
        std::cerr << "key doesn't exist" << std::endl;
    }
    
    // Using output iterators
    std::vector<std::string> s_vec;
    redis.lrange("list", 0, -1, std::back_inserter(s_vec));
  11. Handle binary data and zero bytes in parameters

    dev

    When passing strings as parameters to prepared statements, libpqxx treats them as text. Any string containing a null byte (\0) will be truncated at the first occurrence of that byte.

    To pass data containing zero bytes, you must treat the data as a binary string (SQL BYTEA type) rather than a text string.

    In libpqxx, represent binary data using a contiguous range of std::byte. Recommended types include:

    • std::basic_string<std::byte>
    • std::basic_string_view<std::byte>
    • std::vector<std::byte>