2.1. SDK core elements

This chapter outlines the common, core elements and conventions used throughout the SDK, for example errors, exceptions, and handling asynchronous operations.

2.1.1. Dependencies

The Proximie SDK minimises the use of external libraries for reasons of simplicity and mitigation of security/vulnerability risks. The C++ implementation uses various Boost libraries as they are highly respected, robust, well-tested and comprehensively assessed for vulnerabilities. The sections in this chapter will give details when they utilise Boost for features and functionality.

Note

Python users do not need to interact with Boost directly — the Python bindings handle these details internally.

2.1.2. Error handling

The two language bindings surface errors differently. In C++, a failure is returned as a value — an error code or a result type — that the caller inspects, and exceptions are reserved for truly exceptional conditions such as running out of memory. In Python, those same failures are raised as typed exceptions that the caller catches.

A function reports failure by returning an error code or a result type, or by passing an error code to a callback. The application inspects that value and decides how to proceed.

2.1.2.1. Error codes

Both bindings build on Boost’s extensible error reporting (see https://www.boost.org/doc/libs/release/libs/system/). An error code encapsulates an error category and a numeric value, letting domain-specific errors be defined and handled by the client application. In C++ the error code is returned, or supplied to a callback, directly; in Python the same information is carried on the raised exception, and error callbacks receive an equivalent error-code object.

Testing whether an error occurred:

void onCompleted(Proximie::error_code error) {
    if (!error) {
        // Successful, no error
        return;
    }

    // Handle error...
}

Identifying the category — every category defined in the SDK exposes a static method to obtain it, so a handler can test which category an error belongs to:

    if (error.category() == Proximie::PxMedia::PxMediaErrorCategory::category()) {
        // Handle media error...

Comparing against a specific error code, type-safely:

    if (error == Proximie::PxMedia::PxMediaErrorCode::InvalidSession) {
        // Handle invalid media session...

2.1.2.2. Results from function calls

Where a call can fail, each binding represents the outcome in the way that is idiomatic for the language:

The C++ SDK uses Boost’s Outcome library (see https://www.boost.org/doc/libs/release/libs/outcome/): a call returns a result type holding either a successful value or an error code. For example, given a result-returning function:

Proximie::outcome::result<int> getSomeIntResult();

The result is marked [[nodiscard]] so the compiler warns if the caller forgets to check it. There are several ways to check the result:

    auto result = getSomeIntResult();

    // Examine an outcome result with if
    if (result) {
        int value = result.value();
        // Do something with the value (using implicit bool conversion)...
    } else {
        Proximie::error_code error = result.error();
        // Handle the error...
    }

    // Examine an outcome result with has_error
    if (result.has_error()) {
        Proximie::error_code error = result.error();
        // Handle the error...
    }

    // Examine an outcome result with has_value
    if (result.has_value()) {
        int value = result.value();
        // Do something with the value...
    }

2.1.3. Object lifetimes

The SDK manages object lifetimes automatically. Objects such as feeds and sessions are created using static create factory methods. In C++ these return smart pointers (std::shared_ptr); in Python the binding layer manages the equivalent reference counting transparently.

Due to the asynchronous nature of the SDK, objects that instigate asynchronous operations are kept alive internally until those operations complete. This means the application can release its reference without causing in-flight operations to fail — the SDK will clean up once all pending work is done.

2.1.4. Asynchronous I/O

The SDK provides a broad set of features, many of which are asynchronous - e.g. HTTP requests, WebSockets, communication with various Proximie services and so on.

Underpinning the async functionality is Boost’s Asio library (see https://live.boost.org/doc/libs/release/doc/html/boost_asio.html). For the most part SDK clients do not need to be concerned by the underlying implementation.

For more details, see Async operations & threading.