NabtoClientFuture type

DESCRIPTION

A Nabto future is used for all async funtions, we deliver some functions such that they can be handled blocking, but for an event driven architecture, the future must be handled using the callbacks. It’s up to the application to make the machinery that handles the callbacks.

DECLARATION

typedef struct NabtoClientFuture_ NabtoClientFuture

EXAMPLE

Example 1

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>

#include <nabto/nabto_client.h>

struct ClientContext {
    NabtoClient* client;
    NabtoClientConnection* connection;
    NabtoClientFuture* future;
};

static void connect();
static void cb_connected(NabtoClientFuture *future, NabtoClientError ec, void *data);
static void print_connection_info(struct ClientContext* ctx);
static void print_connection_type(struct ClientContext* ctx);
static void cleanup(struct ClientContext* ctx);

static int finished = 0;

int main(int argc, char** argv) {
    struct ClientContext* ctx = (struct ClientContext*)malloc(sizeof(struct ClientContext));
    memset(ctx, 0, sizeof(struct ClientContext));
    ctx->client = nabto_client_new();
    connect(ctx);
    while (!finished) {
        // do stuff here while the connect future asynchonously resolves - or use
        // nabto_client_future_wait for synchronous behavior instead of setting async callback
        sleep(1);
        print_connection_type(ctx);
    }
    nabto_client_free(ctx->client);
    return 0;
}

static void connect(struct ClientContext* ctx) {
    const char* clientPrivateKey =
        "-----BEGIN EC PARAMETERS-----"
        "BggqhkjOPQMBBw=="
        "-----END EC PARAMETERS-----"
        "-----BEGIN EC PRIVATE KEY-----"
        "MHcCAQEEIPzp7QHuqMZLXMmigdEtUsJ/sgE0IKRONnAHhmB1/OBdoAoGCCqGSM49"
        "AwEHoUQDQgAEHOb4U+Jervfn/cSe+zg7SdhdFbxVkYWZU35dsycrGYhsOcD8jyYI"
        "gvjMfjwJ6wNV3aFXyWdPdfY/brfP/dyjUw=="
        "-----END EC PRIVATE KEY-----";
    ctx->connection = nabto_client_connection_new(ctx->client);

    nabto_client_connection_set_private_key(ctx->connection, clientPrivateKey);
    nabto_client_connection_set_product_id(ctx->connection, "pr-xruwhj1");
    nabto_client_connection_set_device_id(ctx->connection, "de-1cgtwfm3");
    nabto_client_connection_set_server_url(ctx->connection, "https://pr-xruwhj1.clients.nabto.net");
    nabto_client_connection_set_server_key(ctx->connection, "sk-33c11dece0517aaa1837b5e49fe1bdd1");
    nabto_client_connection_set_application_name(ctx->connection, "DemoApp");
    nabto_client_connection_set_application_version(ctx->connection, "1.0.0");

    ctx->future = nabto_client_future_new(ctx->client);
    nabto_client_connection_connect(ctx->connection, ctx->future);
    nabto_client_future_set_callback(ctx->future, cb_connected, ctx);
}

static void cb_connected(NabtoClientFuture *future, NabtoClientError ec, void *data) {
    struct ClientContext* ctx = (struct ClientContext*)data;
    if (ec == NABTO_CLIENT_EC_OK) {
        printf("Connection attempt succeeded.\n");
        print_connection_info(ctx);
        print_connection_type(ctx);
        // TODO: use connection - for instance, open a stream or send a CoAP request, close connection when done
    } else {
        printf("Connection attempt failed, ec=%d.\n", ec);
        print_connection_info(ctx);
        cleanup(ctx);
    }
}

static void print_connection_info(struct ClientContext* ctx) {
    char* json;
    if (!ctx->connection) {
        return;
    }
    if (nabto_client_connection_get_options(ctx->connection, &json) == NABTO_CLIENT_EC_OK) {
        printf("Connection options: %s\n", json);
        nabto_client_string_free(json);
    } else {
        printf("Could not get connection options.\n");
    }
    if (nabto_client_connection_get_info(ctx->connection, &json) == NABTO_CLIENT_EC_OK) {
        printf("Connection info: %s\n", json);
        nabto_client_string_free(json);
    } else {
        printf("Could not get connection info.\n");
    }
}

static void print_connection_type(struct ClientContext* ctx) {
    if (!ctx->connection) {
        return;
    }
    NabtoClientConnectionType type;
    NabtoClientError ec = nabto_client_connection_get_type(ctx->connection, &type);
    const char* typeStr;
    if (ec == NABTO_CLIENT_EC_OK) {
        switch (type) {
        case NABTO_CLIENT_CONNECTION_TYPE_RELAY: typeStr = "RELAY"; break;
        case NABTO_CLIENT_CONNECTION_TYPE_DIRECT: typeStr = "DIRECT"; break;
        default: assert(!"Unexpected connection type");
        }
    } else {
        typeStr = "not determined";
    }
    printf("Connection type is currently %s\n", typeStr);
}

static void cleanup(struct ClientContext* ctx) {
    if (ctx->connection) {
        nabto_client_connection_close(ctx->connection, ctx->future);
        if (ctx->future) {
            nabto_client_future_wait(ctx->future);
        }
        nabto_client_connection_free(ctx->connection);
        ctx->connection = NULL;
    }
    if (ctx->future) {
        nabto_client_future_free(ctx->future);
        ctx->future = NULL;
    }
    finished = 1;
}

Example 2

NabtoClient* client = nabto_client_new();
NabtoClientConnection* connection = nabto_client_connection_new(client);

// now use connection - when done clean up:

NabtoClientFuture* future = nabto_client_future_new(client);
nabto_client_connection_close(connection, future);
nabto_client_future_wait(future);
nabto_client_future_free(future);
nabto_client_connection_free(connection);