---
source_url: https://www.pubnub.com/docs/sdks/c-core/api-reference/misc
title: Utility Methods API for C-Core SDK
updated_at: 2026-06-17T11:38:46.564Z
sdk_name: PubNub C/C++ Core SDK
sdk_version: 7.2.3
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Utility Methods API for C-Core SDK

PubNub C/C++ Core SDK, use the latest version: 7.2.3

The methods on this page are utility methods that don't fit into other categories.

## PubNub alloc

Returns an allocated context. After successful allocation, call `pubnub_init()` to prepare the context for regular use. Always obtain a context pointer by calling this function rather than creating one manually.

### Method(s)

```c
pubnub_t *pubnub_alloc(void)
```

### Sample code

```c
pubnub_t *ctx = pubnub_alloc();
if (NULL == ctx) {
    puts("Couldn't allocate a Pubnub context");
    return -1;
}
```

### Returns

| Type | Description |
| --- | --- |
| `pubnub_t*` | Context pointer on success, `NULL` on error. |

## PubNub free

Frees a previously allocated context if no transaction is in progress. If a transaction is active, the SDK cancels it (equivalent to calling `pubnub_cancel()`), but the cancellation may not complete during this call.

You don't need to free a context after every transaction. Free a context only when you're done with PubNub transactions for a significant period of time.

### Method(s)

```c
int pubnub_free(pubnub_t *pb);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | The PubNub context to free. |

### Sample code

```c
if (0 != pubnub_free(pbp)) {
    printf("Freeing PubNub context failed, cancel started.\n");
}
else {
    printf("Pubnub context freed.\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK, context freed. |
| `int` | `-1` | Context not freed, transaction cancel started. |

## Free a context, with waiting

Retries `pubnub_free()` in a tight loop until either it succeeds or the specified time elapses. This function waits for the current transaction to finish and then frees the context.

This function is most useful in the callback interface, especially after `pubnub_cancel()`. It is not useful in the sync interface if you use only one thread with the context.

### Method(s)

```c
int pubnub_free_with_timeout(pubnub_t* pbp, unsigned millisec);
```

| Parameter | Description |
| --- | --- |
| `pbp` *Type: `pubnub_t*` | The PubNub context to free. |
| `millisec` *Type: `unsigned` | Maximum time to wait for freeing to succeed, in milliseconds. |

### Sample code

```c
if (0 != pubnub_free_with_timeout(pbp, 1000)) {
    puts("Failed to free the context in due time");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | `pubnub_free()` succeeded. |
| `int` | `-1` | Failed to free within the specified time. |

## PubNub cancel

Cancels an ongoing API transaction. Once complete, the SDK closes the TCP/IP connection to PubNub. The outcome of any transaction in progress will be `PNR_CANCELLED`.

In the sync interface, cancellation may finish during this call, but there is no guarantee. In the callback interface, immediate completion is unlikely. Always check the result.

### Method(s)

```c
enum pubnub_cancel_res pubnub_cancel(pubnub_t* p);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The PubNub context for which to cancel the transaction. |

### Sample code

```c
pubnub_publish(ctx, "hello_world", "\"Hello from Pubnub C-core docs!\"");
if (PN_CANCEL_FINISHED == pubnub_cancel(ctx)) {
    puts("Cancel done");
}
else {
    /* await the result, for the sync interface, it would be: */
    pubnub_await(ctx);
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `enum pubnub_cancel_res` | `PN_CANCEL_STARTED` | Cancel started, await the outcome. |
| `enum pubnub_cancel_res` | `PN_CANCEL_FINISHED` | Cancelled, no need to await. |

## PubNub get

Returns a pointer to an arrived message or other element of the transaction response. Messages arrive after a subscribe or history operation. For other operations, this function provides access to the whole response or the next element. Each subsequent call returns the next message, if any.

### Method(s)

```c
char const * pubnub_get (pubnub_t *p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
pubnub_subscribe(ctx, "hello_world", NULL);
pbresult = pubnub_await(ctx);
if (pbresult != PNR_OK) {
    printf("Failed to subscribe, error %d\n", pbresult);
    pubnub_free(ctx);
    return -1;
}
else {
    char const *msg = pubnub_get(ctx);
    while (msg != NULL) {
        printf("Got message: %s\n", msg);
        msg = pubnub_get(ctx);
    }
}
pubnub_free(ctx);
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | Pointer to the message, or `NULL` if no more messages. |

## PubNub get channel

Returns a pointer to the next channel from a subscribe transaction's response. Each subsequent call returns the next channel, if any.

### Method(s)

```c
char const * pubnub_get_channel (pubnub_t *pb)
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to PubNub client context. Must not be `NULL`. |

### Sample code

```c
pubnub_subscribe(ctx, "hello_world", NULL);
pbresult = pubnub_await(ctx);
if (pbresult != PNR_OK) {
    printf("Failed to subscribe, error %d\n", pbresult);
    pubnub_free(ctx);
    return -1;
}
else {
    char const *msg = pubnub_get(ctx);
    char const *channel = pubnub_get_channel(ctx);
    while (msg != NULL) {
        printf("Got message: %s on channel %s\n", msg, (NULL == channel) ? "" : channel );
        msg = pubnub_get(ctx);
        channel = pubnub_get_channel(ctx);
    }
}
pubnub_free(ctx);
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | Pointer to the channel name, or `NULL` if no more channels. |

## PubNub last result

Returns the result of the last transaction in the given context. This may block when using blocking I/O and will not block when using non-blocking I/O.

Related methods:

* [pubnub_set_blocking_io](#set-blocking-io)
* [pubnub_set_non_blocking_io](#set-non-blocking-io)

### Method(s)

```c
int pubnub_last_result(pubnub_t *p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
pubnub_list_channel_group(ctx, "my_channel_group");
pbresult = pubnub_await(ctx);
printf("Last result %s\n", pubnub_res_2_string(pubnub_last_result(ctx)));
```

### Returns

| Type | Description |
| --- | --- |
| `enum pubnub_res` | Result of the last transaction in the context. |

## PubNub last HTTP code

Returns the HTTP reply code of the last transaction in the context.

### Method(s)

```c
enum pubnub_res int pubnub_last_http_code(pubnub_t *p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
pubnub_list_channel_group(ctx, "my_channel_group");
pbresult = pubnub_await(ctx);
printf("HTTP Status Code %d\n", pubnub_last_http_code(ctx));
```

### Returns

| Type | Description |
| --- | --- |
| `int` | HTTP reply code of the last transaction. |

## PubNub last publish result

Returns the result string of the last publish transaction as returned from PubNub. If the last transaction was not a publish or an error occurred, the function returns `NULL`. A successful publish returns `"Sent"`; otherwise, the function returns an error description.

### Method(s)

```c
char const *pubnub_last_publish_result(pubnub_t *p);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
pubnub_init(ctx, "demo", "demo");
pubnub_set_user_id(ctx, "MyUniqueUser_Id")
pbres = pubnub_publish(ctx, "hello_world", "\"Hello from Pubnub C-core docs!\"");
if (pbresult != PNR_OK) {
    printf("Failed to publish, error %d\n", pbresult);
    printf("String result of last publish %s\n", pubnub_last_publish_result(ctx));
    return -1;
}
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | Result string of the last publish transaction. |

## PubNub last time token

Returns the last received timetoken from a subscribe transaction on the context. After `pubnub_init()`, the value is `"0"`.

### Method(s)

```c
char const *pubnub_last_time_token(pubnub_t *p);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
printf("Last timetoken %s\n", pubnub_last_time_token(ctx));
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | String of the last received timetoken. |

## Parse publish result

Parses a publish result string. You typically obtain this string from `pubnub_last_publish_result()`.

### Method(s)

```c
enum pubnub_publish_res pubnub_parse_publish_result(char const *result)
```

| Parameter | Description |
| --- | --- |
| `result` *Type: `char const*` | Publish result string. |

### Sample code

```c
enum pubnub_res res;
pubnub_t *pbp = pubnub_alloc();
if (NULL == pbp) {
    printf("Failed to allocate Pubnub context!\n");
    return -1;
}
pubnub_init(pbp, "demo", "demo");
pubnub_set_user_id(pbp, "MyUniqueUser_Id")

res = pubnub_publish(pbp, chan, "\"Hello world from sync!\"");
if (res != PNR_STARTED) {
    printf("pubnub_publish() returned unexpected: %d\n", res);
    pubnub_free(pbp);
    return -1;
}
res = pubnub_await(pbp);

if (PNR_PUBLISH_FAILED == res) {
  enum pubnub_publish_res publ_res = pubnub_parse_publish_result(pubnub_last_publish_result(pbp));
  switch (publ_res) {
  case PNPUB_INVALID_JSON: printf("Invalid JSON was sent in the publish message\n"); break;
  default: break;
  }
}
```

### Returns

| Type | Description |
| --- | --- |
| `enum pubnub_publish_res` | Parsed result of the publish response. |

## PubNub res 2 string

Returns a human-readable string describing a `pubnub_res` enum value.

### Method(s)

```c
char const* pubnub_res_2_string(enum pubnub_res e)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `enum pubnub_res` | PubNub result enum value. |

### Sample code

```c
enum pubnub_res res;
pubnub_t *pbp = pubnub_alloc();
if (NULL == pbp) {
    printf("Failed to allocate Pubnub context!\n");
    return -1;
}
pubnub_init(pbp, "demo", "demo");
pubnub_set_user_id(pbp, "MyUniqueUser_Id")

res = pubnub_publish(pbp, chan, "\"Hello world from sync!\"");
if (res != PNR_STARTED) {
    printf("pubnub_publish() returned unexpected: %d\n", res);
    pubnub_free(pbp);
    return -1;
}
res = pubnub_await(pbp);
printf("Response %s\n",pubnub_res_2_string(res));
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | String describing the PubNub result. |

## Should a failed transaction be retried

Returns whether retrying a failed PubNub transaction makes sense. This is mostly useful for publishing but applies generally. It is least useful for subscribing, because you will most likely subscribe again later.

### Method(s)

```c
enum pubnub_tribool pubnub_should_retry(enum pubnub_res e);
```

| Parameter | Description |
| --- | --- |
| `e` *Type: `enum pubnub_res` | PubNub result to evaluate for retry. |

### Sample code

```c
for (i = 0; i < my_retry_limit; ++i) {
    res = pubnub_publish(pbp, chan, msg);
    if (res != PNR_STARTED) {
        printf("pubnub_publish() returned unexpected: %d\n", res);
        pubnub_free(pbp);
        return -1;
    }

    res = pubnub_await(pbp);
    switch (pubnub_should_retry(res)) {
        case pbccFalse:
        break;
        case pbccTrue:
            printf("Publishing failed with code: %d ('%s')\nRetrying...\n", res, pubnub_res_2_string(res));
        continue;
        case pbccNotSet:
            puts("Publish failed, but we decided not to retry");
        break;
    }

    break;
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `enum pubnub_tribool` | `pbccTrue` | Safe to retry, though success is not guaranteed. |
| `enum pubnub_tribool` | `pbccFalse` | Retrying the same transaction will not help. |
| `enum pubnub_tribool` | `pbccNotSet` | Retry might help but could also make things worse. For example, on `PNR_TIMEOUT`, the message may have been delivered but the response was lost, so retrying could duplicate the message. |

## PubNub leave

Initiates a leave transaction for the specified channel(s). Leave a channel when you want to subscribe to another channel on the same context to avoid losing messages. Leaving is also useful for tracking presence. You cannot leave if a transaction is already in progress on the context.

### Method(s)

```c
enum pubnub_res pubnub_leave (pubnub_t *p, const char *channel, const char *channel_group)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. Must not be `NULL`. |
| `channel`Type: `const char*` | Channel name or comma-delimited list of channel names to leave. |
| `channel_group`Type: `const char*` | Channel group name or comma-delimited list of channel group names to leave. |

### Sample code

```c
pubnub_leave(ctx, "hello_world", NULL);
pbresult = pubnub_await(ctx);
if (PNR_OK == pbresult) {
    printf("Leave successful\n");
}
pubnub_free(ctx);
```

### Returns

| Type | Description |
| --- | --- |
| `enum pubnub_res` | `PNR_STARTED` on success, an error otherwise. |

## Time

Returns a 17-digit precision Unix epoch timetoken from the PubNub server.

:::note Timetoken algorithm
```javascript
timetoken = (Unix epoch time in seconds) * 10000000
```
For example:
```javascript
08/19/2013 @ 9:20pm in UTC = 1376961606
timetoken = 1376961606 * 10000000
timetoken = 13769616060000000
```
:::

### Method(s)

```c
enum pubnub_res pubnub_time (pubnub_t *p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
pubnub_time(ctx);
pbresult = pubnub_await(ctx);
if (PNR_OK == pbresult) {
    char const *gotten_time = pubnub_get();
}
```

### Rest response from server

The `pubnub_time()` function returns a string timetoken:

```json

```

## Subscribe loop - callback

Creates a subscribe loop descriptor for the callback interface. Default values are used for descriptor fields not provided as parameters.

### Method(s)

```c
pubnub_subloop_t* pubnub_subloop_define(pubnub_t *p, char const *channel, struct pubnub_subscribe_options options, pubnub_subloop_callback_t cb);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The PubNub context to use for the subscribe loop. |
| `channel` *Type: `char const*` | The channel(s) to use in the subscribe loop. |
| `options` *Type: `struct pubnub_subscribe_options` | Subscribe options to use in the loop. |
| `cb` *Type: `pubnub_subloop_callback_t` | Callback called for each message received during the loop. |

### Sample code

```c
static void subloop_callback(char const* message, enum pubnub_res result) {
    if (PNR_OK == result) {
        printf("Received message '%s'\n", message);
    } else {
            printf("Subscribe failed with code: %d\n", result);
    }
}

pbsld = pubnub_subloop_define(pbp, chan, pubnub_subscribe_defopts(), subloop_callback);

if (NULL == pbsld) {
    printf("Defining a subscribe loop failed\n");
    pubnub_free(pbp);
    return -1;
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `pubnub_subloop_t*` | `NULL` | Failed to create a descriptor. |
| `pubnub_subloop_t*` | other | The descriptor created. |

## Subscribe loop - sync

Creates a subscribe loop descriptor for the sync interface, returned by value. Default values are used for descriptor fields not provided as parameters.

### Method(s)

```c
struct pubnub_subloop_descriptor pubnub_subloop_define(pubnub_t *p, char const *channel);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The PubNub context to use for the loop. |
| `channel` *Type: `char const*` | The channel(s) to subscribe to. |

### Sample code

```c
pbsld = pubnub_subloop_define(pbp, "hello_world");
```

### Returns

| Type | Description |
| --- | --- |
| `struct pubnub_subloop_descriptor` | The subscribe loop descriptor. |

## Start a callback subscribe loop

Starts a subscribe loop. The callback provided in `pubnub_subloop_define()` is called for each message received. A running subscribe loop takes over the context and receives all callbacks for it.

:::warning Context callback
Changing the callback on the context during a running subscribe loop will break the loop.
:::

:::warning Subscribe loop descriptor
Do not change the subscribe loop descriptor while the loop is running. Stop it first with `pubnub_subloop_stop()`.
:::

### Method(s)

```c
enum pubnub_res pubnub_subloop_start(pubnub_subloop_t* pbsld);
```

| Parameter | Description |
| --- | --- |
| `pbsld` *Type: `pubnub_subloop_t*` | The subscribe loop descriptor of the loop to start. |

### Sample code

```c
pubnub_subloop_start(pbsld);
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `enum pubnub_res` | `PNR_OK` | Subscribe loop started. |
| `enum pubnub_res` | other | Indicates the reason for failure. |

## Stop a callback subscribe loop

Stops a subscribe loop. If the loop is delivering messages through the callback, the stop completes once delivery finishes. After stopping, the context can be used normally and the original callback is restored.

### Method(s)

```c
void pubnub_subloop_stop(pubnub_subloop_t* pbsld);
```

| Parameter | Description |
| --- | --- |
| `pbsld` *Type: `pubnub_subloop_t*` | The subscribe loop descriptor of the loop to stop. |

### Sample code

```c
pubnub_subloop_stop(pbsld);
```

### Returns

None.

## Sync subscribe iteration

Fetches the next message in a sync subscribe loop, automatically subscribing if no messages remain. This function may block for a significant time while waiting for messages to arrive.

Changing the descriptor during the loop is possible, but changes may take several iterations to take effect.

### Method(s)

```c
enum pubnub_res pubnub_subloop_fetch(struct pubnub_subloop_descriptor const* pbsld, char const** message);
```

| Parameter | Description |
| --- | --- |
| `pbsld` *Type: `struct pubnub_subloop_descriptor const*` | The sync subscribe loop descriptor to use. |
| `message` *Type: `char const**` | The fetched message, or `NULL` if no message was fetched. |

### Sample code

```c
for (;;) {
    char const* msg;
    enum pubnub_res pbres = pubnub_subloop_fetch(&pbsld, &msg);
    if (PNR_OK != pbres) {
        printf("Exiting subscribe loop because of error: %d\n", pbres);
        break;
    }
    if (NULL == msg) {
        puts("Everything's OK, yet no message received");
    } else {
        printf("Got message '%s'\n", msg);
    }
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `enum pubnub_res` | `PNR_OK` | Message was fetched successfully. |
| `enum pubnub_res` | other | Indicates the reason for failure. |

## Release/free the callback subscribe loop descriptor

Releases the subscribe loop descriptor and its resources. Call this when you are done with the loop.

### Method(s)

```c
void pubnub_subloop_undef(pubnub_subloop_t* pbsld);
```

| Parameter | Description |
| --- | --- |
| `pbsld` *Type: `pubnub_subloop_t*` | The subscribe loop descriptor to release. |

### Sample code

```c
pubnub_subloop_undef(pbsld);
```

### Returns

None.

## PubNub register callback

Registers a callback function to be called when a transaction ends. Registering a `NULL` pointer (the initial value after `pubnub_init()`) means no callback will be called. Do not make assumptions about the thread on which this function is called.

### Method(s)

```c
enum pubnub_res pubnub_register_callback(pubnub_t *pb, pubnub_callback_t cb, void *user_data)
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | The PubNub context for which to set the callback. |
| `cb`Type: `pubnub_callback_t` | Pointer to the function to call on end of transaction. |
| `user_data`Type: `void*` | Pointer passed to the callback function. |

### Sample code

```c
pubnub_register_callback(ctx, sample_callback, &user_data);
```

### Returns

| Type | Description |
| --- | --- |
| `enum pubnub_res` | `PNR_OK` on success, an error value otherwise. |

## PubNub get user data

Returns the user data set with `pubnub_register_callback()`.

### Method(s)

```c
void *pubnub_get_user_data(pubnub_t *pb)
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | PubNub client context for which to return user data. |

### Sample code

```c
void* user_data = pubnub_get_user_data(ctx);
```

### Returns

| Type | Description |
| --- | --- |
| `void*` | User data set with `pubnub_register_callback`. |

## Set blocking IO

Enables blocking I/O for a context. If supported by the platform, blocking I/O is used unless another reason prevents it.

With blocking I/O, polling for a transaction outcome blocks the caller's thread until the outcome is reached. This results in simpler code but scales poorly.

### Method(s)

```c
int pubnub_set_blocking_io(pubnub_t *p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context to set blocking I/O for. |

### Sample code

```c
pubnub_t *ctx = pubnub_alloc();
if (NULL == ctx) {
  puts("Couldn't allocate a Pubnub context");
  return -1;
}
if (0 == pubnub_set_blocking_io(ctx)) {
  puts("Context set to blocking");
}
```

### Returns

| Type | Description |
| --- | --- |
| `int` | `0` on success; otherwise, blocking I/O is not supported. |

## Set non blocking IO

Enables non-blocking I/O for a context. If supported by the platform, non-blocking I/O is used unless another reason prevents it.

With non-blocking I/O, polling for a transaction outcome returns immediately with the current status, so you must poll repeatedly until the outcome is reached. This results in more complex code but scales better.

### Method(s)

```c
int pubnub_set_non_blocking_io(pubnub_t *p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context to set non-blocking I/O for. |

### Sample code

```c
pubnub_t *ctx = pubnub_alloc();
if (NULL == ctx) {
  puts("Couldn't allocate a Pubnub context");
  return -1;
}
if (0 == pubnub_set_non_blocking_io(ctx)) {
  puts("Context set to non blocking");
}
```

### Returns

| Type | Description |
| --- | --- |
| `int` | `0` on success; otherwise, non-blocking I/O is not supported. |

## PubNub use HTTP keep alive

Enables HTTP Keep-Alive (persistent connections) on the context. This is the default behavior. You can disable it with `pubnub_dont_use_http_keep_alive()`.

When active, connections to PubNub remain open after a transaction ends, making subsequent transactions faster. However, keep-alive has trade-offs:

* `pubnub_free()` does not work for contexts in a keep-alive state. Call `pubnub_cancel()` first.
* The PubNub server may close idle keep-alive connections, which could cause a transaction to fail due to a race condition.
* Keep-alive sockets remain allocated, consuming resources.

### Method(s)

```c
void pubnub_use_http_keep_alive (pubnub_t* p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
pubnub_use_http_keep_alive(pbp);
```

### Returns

None.

## PubNub do not use HTTP keep alive

Disables HTTP Keep-Alive (persistent connections) on the context. See [pubnub_use_http_keep_alive()](#pubnub-use-http-keep-alive) for details on the default behavior.

### Method(s)

```c
void pubnub_dont_use_http_keep_alive (pubnub_t* p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
pubnub_dont_use_http_keep_alive(pbp);
```

### Returns

None.

## PubNub use TCP keep alive

Enables TCP Keep-Alive probes on the context. TCP Keep-Alive sends periodic probes on an idle connection to detect if the remote peer is still reachable.

:::warning HTTP Keep-Alive required
This option works **only** together with HTTP Keep-Alive. Make sure HTTP Keep-Alive is enabled with `pubnub_use_http_keep_alive()` before using TCP Keep-Alive.
:::

Default values:

* `time`: 60 seconds (idle time before first probe)
* `interval`: 20 seconds (time between probes)
* `probes`: 3 (number of unanswered probes before the connection is deemed broken)

### Method(s)

```c
void pubnub_use_tcp_keep_alive(
    pubnub_t* pb,
    uint8_t   time,
    uint8_t   interval,
    uint8_t   probes);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `time` *Type: `uint8_t` | Seconds of idle time before the first keep-alive probe. |
| `interval` *Type: `uint8_t` | Seconds between keep-alive probes if the previous one was not acknowledged. |
| `probes` *Type: `uint8_t` | Number of unacknowledged probes before the connection is deemed broken. |

### Sample code

```c
// Enable HTTP keep-alive first
pubnub_use_http_keep_alive(pbp);

// Then enable TCP keep-alive with custom parameters:
// - Start probing after 30 seconds of idle
// - Send probes every 10 seconds
// - Give up after 5 unanswered probes
pubnub_use_tcp_keep_alive(pbp, 30, 10, 5);
```

### Returns

None.

## PubNub do not use TCP keep alive

Disables TCP Keep-Alive probes on the context.

### Method(s)

```c
void pubnub_dont_use_tcp_keep_alive(pubnub_t* pb);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |

### Sample code

```c
pubnub_dont_use_tcp_keep_alive(pbp);
```

### Returns

None.

## Set the transaction timeout

Sets the transaction timeout for the context. This applies to all subsequent transactions. If an ongoing transaction supports changing its timeout, the change takes effect immediately.

C-core does not distinguish between subscribe and other transaction timeouts to save space. If timer support is available, `pubnub_init()` sets a default timeout that is configurable at compile time.

#### Preconditions

* Call this after `pubnub_init()` on the context and before starting a transaction.
* Duration must be greater than `0`.

### Method(s)

```c
int pubnub_set_transaction_timeout(pubnub_t *p, int duration_ms)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |
| `duration_ms` *Type: `int` | Duration of the timeout, in milliseconds. |

### Sample code

```c
#include "pubnub_timers.h"
pubnub_set_transaction_timeout(pn, PUBNUB_DEFAULT_SUBSCRIBE_TIMEOUT);
```

### Returns

| Type | Description |
| --- | --- |
| `int` | `0` on success; otherwise, timers are not supported. |

## Get the transaction timeout

Returns the current transaction timeout for the context.

#### Preconditions

* Call this after `pubnub_init()` on the context.

### Method(s)

```c
int pubnub_transaction_timeout_get(pubnub_t *p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | Pointer to PubNub client context. |

### Sample code

```c
#include "pubnub_timers.h"
...
printf("Current transaction timeout: %d\n", pubnub_transaction_timeout_get(pn));
```

### Returns

| Type | Description |
| --- | --- |
| `int` | Current transaction timeout in milliseconds (always greater than `0`). |

## Get the current origin

Returns the origin used for the context. If setting a custom origin is not enabled, this returns the default origin.

### Method(s)

```c
char const* pubnub_get_origin(pubnub_t *p)
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | PubNub context to get the origin from. |

### Sample code

```c
printf("Current origin: %s\n", pubnub_get_origin(pn));
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | A read-only string of the origin used for the given context. |

## Configure proxy to be used from the system

Sets proxy configuration by reading from the system configuration. On some platforms (like Windows), there is a standard way of setting a proxy. On other platforms, C-core does its best.

This function can block for a significant time if the system is configured for proxy auto-discovery. Call it only at start, restart, wake-up, or similar events.

#### Preconditions

* Call this after `pubnub_init()` on the context.

### Method(s)

```c
int pubnub_set_proxy_from_system(pubnub_t *p, enum pubnub_proxy_type protocol);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context to set proxy configuration for. |
| `protocol` *Type: `enum pubnub_proxy_type` | Proxy protocol to use. |

### Sample code

```c
pubnub_set_proxy_from_system(pbp, pbpproxyHTTP_GET);
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | non-zero | Error: specified protocol not supported or system configuration unavailable. |

## Set proxy to be used

Sets the proxy configuration by explicitly specifying the protocol, server, and port. If proxy support is available, `pubnub_init()` defaults to no proxy.

#### Preconditions

* Call this after `pubnub_init()` on the context.
* If `protocol` is not `pbproxyNONE`, then `ip_address_or_url` must not be `NULL`.

### Method(s)

```c
int pubnub_set_proxy_manual(pubnub_t *p, enum pubnub_proxy_type protocol, char const *ip_address_or_url, uint16_t port);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context to set proxy configuration for. |
| `protocol` *Type: `enum pubnub_proxy_type` | Proxy protocol to use. |
| `ip_address_or_url` *Type: `char const*` | IP address or URL of the proxy server. |
| `port` *Type: `uint16_t` | Port number on the proxy. Port `3128` is commonly used. |

### Sample code

```c
pubnub_set_proxy_manual(pbp, pbpproxyHTTP_GET, "proxy.local", 3128);
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | non-zero | Error: specified protocol not supported or invalid address/URL. |

## Get current proxy protocol for a context

Returns the current proxy type/protocol for the context.

### Method(s)

```c
enum pubnub_proxy_type pubnub_proxy_protocol_get(pubnub_t *p);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The PubNub context to get the proxy protocol for. |

### Sample code

```c
enum pubnub_proxy_type proxy = pubnub_proxy_protocol_get(pbp);
```

### Returns

| Type | Description |
| --- | --- |
| `enum pubnub_proxy_type` | The proxy protocol used. Returns `pbpproxyNONE` if no proxy is set. |

## Get current proxy authentication scheme

Returns the current HTTP proxy authentication scheme for the context. The scheme is set dynamically during communication with the proxy.

### Method(s)

```c
enum pubnub_http_authentication_scheme pubnub_proxy_authentication_scheme_get(pubnub_t *p);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context to get the proxy authentication scheme for. |

### Sample code

```c
enum pubnub_http_authentication_scheme sch = pubnub_authentication_scheme_get(pbp);
switch (sch) {
    case pbhtauBasic:
        puts("Basic authentication scheme");
    break;
    case pbhtauDigest:
        puts("Digest authentication scheme");
    break;
    case pbhtauNTLM:
        puts("Microsoft NTLM authentication scheme");
    break;
    case pbhtauNone:
        puts("No authentication scheme");
    break;
}
```

### Returns

| Type | Description |
| --- | --- |
| `enum pubnub_http_authentication_scheme` | The authentication scheme used. Returns `pbhtauNone` if the proxy does not require authentication. |

## Set username and password for authenticating proxy

Sets the authentication credentials and scheme for proxy authentication. The default credentials are the currently logged-on username and password (if available at runtime), or C-core's built-in defaults.

#### Preconditions

* Call this after `pubnub_init()` on the context.

### Method(s)

```c
int pubnub_set_proxy_authentication_username_password(pubnub_t *p, char const *username, char const *password);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context to set proxy authentication for. |
| `username`Type: `char const*` | Authentication username. Use `NULL` to use the default. |
| `password`Type: `char const*` | Authentication password. Use `NULL` to use the default. |

### Sample code

```c
pubnub_set_proxy_authentication_username_password(pbp, "bond", "007");
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | non-zero | Error: setting username/password failed. |

## Reset username and password for authenticating proxy

Resets the context to not use any proxy authentication scheme. This is the default state, so you only need to call this function to reset a previously configured authentication scheme.

#### Preconditions

* Call this after `pubnub_init()` on the context.

### Method(s)

```c
int pubnub_set_proxy_authentication_none(pubnub_t *p);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context to reset proxy authentication for. |

### Sample code

```c
pubnub_set_proxy_authentication_none(pbp);
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | non-zero | Error: authentication scheme doesn't support reset. |

## Set the primary DNS server

Sets the primary DNS server IPv4 address (in binary, network order) for resolving the PubNub origin on a specific context. Applies to all subsequent DNS queries on that context.

The C-core DNS module is not always used. It is typically used for the callback interface because it works asynchronously. On platforms with asynchronous system resolvers, C-core can be configured to use those instead. If the DNS module is not used, this function has no effect.

### Method(s)

```c
int pubnub_dns_set_primary_server_ipv4(pubnub_t* pb, struct pubnub_ipv4_address ipv4);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `ipv4` *Type: `struct pubnub_ipv4_address` | The IPv4 address of the server to use. Set all bytes to `0` to disable. |

### Sample code

```c
struct pubnub_ipv4_address addr = { { 8, 8, 8, 8 } };
if (0 != pubnub_dns_set_primary_server_ipv4(pb, addr)) {
    printf("Setting primary DNS server failed\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used. |

## Set the primary DNS server by string

Sets the primary DNS server IPv4 address from a numbers-and-dots notation string for resolving the PubNub origin.

The DNS module in C-core is not always used, see [pubnub_dns_set_primary_server_ipv4()](#set-the-primary-dns-server).

### Method(s)

```c
int pubnub_dns_set_primary_server_ipv4_str(pubnub_t* pb, char const* ipv4_str);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `ipv4_str` *Type: `char const*` | The IPv4 address in numbers-and-dots notation. |

### Sample code

```c
if (0 != pubnub_dns_set_primary_server_ipv4_str(pb, "8.8.8.8")) {
    printf("Setting primary DNS server failed\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used. |

## Get the primary DNS server

Reads the currently set primary DNS server's IPv4 address, in binary form (network order).

The DNS module in C-core is not always used, see [pubnub_dns_set_primary_server_ipv4()](#set-the-primary-dns-server).

### Method(s)

```c
int pubnub_get_dns_primary_server_ipv4(pubnub_t* pb, struct pubnub_ipv4_address* o_ipv4);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `o_ipv4` *Type: `struct pubnub_ipv4_address*` | Pointer to the IPv4 address struct, allocated by the caller. |

### Sample code

```c
struct pubnub_ipv4_address addr;
if (0 != pubnub_get_dns_primary_server_ipv4(pb, &addr)) {
    printf("Getting primary DNS server failed\n");
}
else {
    printf("Primary DNS server: %d.%d.%d.%d\n", addr.ipv4[0], addr.ipv4[1], addr.ipv4[2], addr.ipv4[3]);
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used. |

## Set the secondary DNS server

Sets the secondary DNS server IPv4 address (in binary, network order) for resolving the PubNub origin on a specific context. The secondary server is used if a query to the primary server fails.

The DNS module in C-core is not always used, see [pubnub_dns_set_primary_server_ipv4()](#set-the-primary-dns-server).

### Method(s)

```c
int pubnub_dns_set_secondary_server_ipv4(pubnub_t* pb, struct pubnub_ipv4_address ipv4);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `ipv4` *Type: `struct pubnub_ipv4_address` | The IPv4 address of the server to use. Set all bytes to `0` to disable. |

### Sample code

```c
struct pubnub_ipv4_address addr = { { 8, 8, 4, 4 } }; // Google secondary DNS
if (0 != pubnub_dns_set_secondary_server_ipv4(pb, addr)) {
    printf("Setting secondary DNS server failed\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used. |

## Set the secondary DNS server by string

Sets the secondary DNS server IPv4 address from a numbers-and-dots notation string for resolving the PubNub origin. The secondary server is used if a query to the primary server fails.

The DNS module in C-core is not always used, see [pubnub_dns_set_primary_server_ipv4()](#set-the-primary-dns-server).

### Method(s)

```c
int pubnub_dns_set_secondary_server_ipv4_str(pubnub_t* pb, char const* ipv4_str);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `ipv4_str` *Type: `char const*` | The IPv4 address in numbers-and-dots notation. Set `"0.0.0.0"` to disable. |

### Sample code

```c
if (0 != pubnub_dns_set_secondary_server_ipv4_str(pb, "8.8.4.4")) {
    printf("Setting secondary DNS server failed\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used. |

## Get the secondary DNS server

Reads the currently set secondary DNS server's IPv4 address, in binary form (network order).

The DNS module in C-core is not always used, see [pubnub_dns_set_primary_server_ipv4()](#set-the-primary-dns-server).

### Method(s)

```c
int pubnub_get_dns_secondary_server_ipv4(pubnub_t* pb, struct pubnub_ipv4_address* o_ipv4);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `o_ipv4` *Type: `struct pubnub_ipv4_address*` | Pointer to the IPv4 address struct, allocated by the caller. |

### Sample code

```c
struct pubnub_ipv4_address addr;
if (0 != pubnub_get_dns_secondary_server_ipv4(pb, &addr)) {
    printf("Getting secondary DNS server failed\n");
}
else {
    printf("Secondary DNS server: %d.%d.%d.%d\n", addr.ipv4[0], addr.ipv4[1], addr.ipv4[2], addr.ipv4[3]);
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used. |

## Get a list of system DNS servers

Reads IPv4 DNS servers from the system configuration. Reads at most `n` servers, even if more are configured. On modern systems, this may return only one DNS server listening on the loopback address.

On POSIX systems, this reads from `/etc/resolv.conf`. On Windows, this uses system functions.

### Method(s)

```c
int pubnub_dns_read_system_servers_ipv4(pubnub_t* pb, struct pubnub_ipv4_address* o_ipv4, size_t n);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `o_ipv4` *Type: `struct pubnub_ipv4_address*` | Array to store the DNS server addresses, allocated by the caller for `n` elements. |
| `n` *Type: `size_t` | Number of elements allocated for `o_ipv4`. |

### Sample code

```c
struct pubnub_ipv4_address addr[MAX_DNS_SRV];
int c = pubnub_dns_read_system_servers_ipv4(pb, addr, MAX_DNS_SRV);
if (c < 0) {
    printf("Can't get list of system DNS servers!\n");
}
else {
    int i;
    for (i = 0; i < c; ++i) {
        printf("System DNS server %d.: %d.%d.%d.%d\n", i, addr[i].ipv4[0], addr[i].ipv4[1], addr[i].ipv4[2], addr[i].ipv4[3]);
    }
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `-1` | Error: cannot read system DNS servers. |
| `int` | `>= 0` | The number of DNS servers read. |

## Set the primary DNS server (IPv6)

Sets the primary DNS server IPv6 address (in binary, network order) for resolving the PubNub origin on a specific context. Applies to all subsequent DNS queries on that context.

:::note Availability
This function is only available when the SDK is built with both `PUBNUB_USE_IPV6` and `PUBNUB_SET_DNS_SERVERS` enabled. For more information, see [PUBNUB_USE_IPV6](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_use_ipv6-enable-ipv6-support) and [PUBNUB_SET_DNS_SERVERS](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_set_dns_servers-enable-dns-server-configuration).
:::

When IPv6 is enabled, the SDK tries user-provided IPv6 DNS servers first, then falls back to user-provided IPv4 servers, and finally falls back to well-known DNS providers.

### Method(s)

```c
int pubnub_dns_set_primary_server_ipv6(pubnub_t* pb, struct pubnub_ipv6_address ipv6);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `ipv6` *Type: `struct pubnub_ipv6_address` | The IPv6 address of the server to use. Set all bytes to `0` to disable. |

### Sample code

```c
struct pubnub_ipv6_address addr = { { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 } }; // Google IPv6 DNS
if (0 != pubnub_dns_set_primary_server_ipv6(pb, addr)) {
    printf("Setting primary IPv6 DNS server failed\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used or IPv6 not enabled. |

## Set the secondary DNS server (IPv6)

Sets the secondary DNS server IPv6 address (in binary, network order) for resolving the PubNub origin. The secondary server is used if a query to the primary server fails.

:::note Availability
This function is only available when the SDK is built with both `PUBNUB_USE_IPV6` and `PUBNUB_SET_DNS_SERVERS` enabled. For more information, see [PUBNUB_USE_IPV6](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_use_ipv6-enable-ipv6-support) and [PUBNUB_SET_DNS_SERVERS](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_set_dns_servers-enable-dns-server-configuration).
:::

### Method(s)

```c
int pubnub_dns_set_secondary_server_ipv6(pubnub_t* pb, struct pubnub_ipv6_address ipv6);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `ipv6` *Type: `struct pubnub_ipv6_address` | The IPv6 address of the server to use. Set all bytes to `0` to disable. |

### Sample code

```c
struct pubnub_ipv6_address addr = { { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x44 } }; // Google secondary IPv6 DNS
if (0 != pubnub_dns_set_secondary_server_ipv6(pb, addr)) {
    printf("Setting secondary IPv6 DNS server failed\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used or IPv6 not enabled. |

## Set the primary DNS server by string (IPv6)

Sets the primary DNS server IPv6 address from a numbers-and-colons notation string for resolving the PubNub origin.

:::note Availability
This function is only available when the SDK is built with both `PUBNUB_USE_IPV6` and `PUBNUB_SET_DNS_SERVERS` enabled.
:::

### Method(s)

```c
int pubnub_dns_set_primary_server_ipv6_str(pubnub_t* pb, char const* ipv6_str);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `ipv6_str` *Type: `char const*` | The IPv6 address in numbers-and-colons notation. Use `"::0"` to disable. |

### Sample code

```c
if (0 != pubnub_dns_set_primary_server_ipv6_str(pb, "2001:4860:4860::8888")) {
    printf("Setting primary IPv6 DNS server failed\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used or IPv6 not enabled. |

## Set the secondary DNS server by string (IPv6)

Sets the secondary DNS server IPv6 address from a numbers-and-colons notation string for resolving the PubNub origin.

:::note Availability
This function is only available when the SDK is built with both `PUBNUB_USE_IPV6` and `PUBNUB_SET_DNS_SERVERS` enabled. For more information, see [PUBNUB_USE_IPV6](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_use_ipv6-enable-ipv6-support) and [PUBNUB_SET_DNS_SERVERS](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_set_dns_servers-enable-dns-server-configuration).
:::

### Method(s)

```c
int pubnub_dns_set_secondary_server_ipv6_str(pubnub_t* pb, char const* ipv6_str);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `ipv6_str` *Type: `char const*` | The IPv6 address in numbers-and-colons notation. Use `"::0"` to disable. |

### Sample code

```c
if (0 != pubnub_dns_set_secondary_server_ipv6_str(pb, "2001:4860:4860::8844")) {
    printf("Setting secondary IPv6 DNS server failed\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used or IPv6 not enabled. |

## Get the primary DNS server (IPv6)

Reads the currently set primary DNS server's IPv6 address, in binary form (network order).

:::note Availability
This function is only available when the SDK is built with both `PUBNUB_USE_IPV6` and `PUBNUB_SET_DNS_SERVERS` enabled. For more information, see [PUBNUB_USE_IPV6](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_use_ipv6-enable-ipv6-support) and [PUBNUB_SET_DNS_SERVERS](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_set_dns_servers-enable-dns-server-configuration).
:::

### Method(s)

```c
int pubnub_get_dns_primary_server_ipv6(pubnub_t* pb, struct pubnub_ipv6_address* o_ipv6);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `o_ipv6` *Type: `struct pubnub_ipv6_address*` | Pointer to the IPv6 address struct, allocated by the caller. |

### Sample code

```c
struct pubnub_ipv6_address addr;
if (0 != pubnub_get_dns_primary_server_ipv6(pb, &addr)) {
    printf("Getting primary IPv6 DNS server failed\n");
}
else {
    printf("Primary IPv6 DNS server retrieved successfully\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used or IPv6 not enabled. |

## Get the secondary DNS server (IPv6)

Reads the currently set secondary DNS server's IPv6 address, in binary form (network order).

:::note Availability
This function is only available when the SDK is built with both `PUBNUB_USE_IPV6` and `PUBNUB_SET_DNS_SERVERS` enabled. For more information, see [PUBNUB_USE_IPV6](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_use_ipv6-enable-ipv6-support) and [PUBNUB_SET_DNS_SERVERS](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_set_dns_servers-enable-dns-server-configuration).
:::

### Method(s)

```c
int pubnub_get_dns_secondary_server_ipv6(pubnub_t* pb, struct pubnub_ipv6_address* o_ipv6);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `o_ipv6` *Type: `struct pubnub_ipv6_address*` | Pointer to the IPv6 address struct, allocated by the caller. |

### Sample code

```c
struct pubnub_ipv6_address addr;
if (0 != pubnub_get_dns_secondary_server_ipv6(pb, &addr)) {
    printf("Getting secondary IPv6 DNS server failed\n");
}
else {
    printf("Secondary IPv6 DNS server retrieved successfully\n");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Error: PubNub DNS module not used or IPv6 not enabled. |

## Get a list of system DNS servers (IPv6)

Reads IPv6 DNS servers from the system configuration. Reads at most `n` servers, even if more are configured.

On POSIX systems, this reads from `/etc/resolv.conf`. On Windows, this uses system functions.

:::note Availability
This function is only available when the SDK is built with both `PUBNUB_USE_IPV6` and `PUBNUB_SET_DNS_SERVERS` enabled. For more information, see [PUBNUB_USE_IPV6](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_use_ipv6-enable-ipv6-support) and [PUBNUB_SET_DNS_SERVERS](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_set_dns_servers-enable-dns-server-configuration).
:::

### Method(s)

```c
int pubnub_dns_read_system_servers_ipv6(pubnub_t* pb, struct pubnub_ipv6_address* o_ipv6, size_t n);
```

| Parameter | Description |
| --- | --- |
| `pb` *Type: `pubnub_t*` | Pointer to the PubNub context. |
| `o_ipv6` *Type: `struct pubnub_ipv6_address*` | Array to store the DNS server addresses, allocated by the caller for `n` elements. |
| `n` *Type: `size_t` | Number of elements allocated for `o_ipv6`. |

### Sample code

```c
#define MAX_DNS_SRV 4
struct pubnub_ipv6_address addr[MAX_DNS_SRV];
int c = pubnub_dns_read_system_servers_ipv6(pb, addr, MAX_DNS_SRV);
if (c < 0) {
    printf("Can't get list of system IPv6 DNS servers!\n");
}
else {
    printf("Found %d IPv6 DNS servers\n", c);
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `-1` | Error: cannot read system DNS servers. |
| `int` | `>= 0` | The number of DNS servers read. |

## Set CA verify locations

Sets the CA certificate locations for SSL/TLS verification. This function is only available on targets with a file system.

By default, both parameters are `NULL`, and C-core uses its built-in certificates. If built-in certificates expire, you can use this function with an up-to-date certificate store to avoid code changes.

Both parameters are stored as pointers, so the caller must keep the strings valid for the lifetime of the context or until they are set to `NULL`.

#### Preconditions

* The context must be valid.

### Method(s)

```c
int pubnub_set_ssl_verify_locations(pubnub_t *p, char const* sCAfile, char const* sCApath);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | PubNub context to set locations for. |
| `sCAfile`Type: `char const*` | Path to a certificate store file (may contain multiple CA certificates). Set to `NULL` to skip. |
| `sCApath`Type: `char const*` | Path to a certificate store directory (each file should contain one CA certificate). Set to `NULL` to skip. |

### Sample code

```c
if (0 != pubnub_set_ssl_verify_locations(pbp, "/etc/ssl/certs/ca-certificates.crt", "/usr/share/ca-certificates/mozilla")) {
    puts("Failed to set SSL verify locations");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | Failed to set certificate locations. |

## Set user defined / in-memory certificate

Sets a user-defined, in-memory PEM certificate for the context. This certificate is used in addition to other certificates. Copy the certificate from a `.pem` file into a string and pass it to this function.

Unlike other certificate-handling functions, this one is available on any platform, including deeply embedded ones. It is meant primarily for debugging with proxy debuggers (such as Fiddler or Charles). There is only one user-defined PEM certificate per context.

#### Preconditions

* The context must be valid.

### Method(s)

```c
void pubnub_ssl_set_usrdef_pem_cert(pubnub_t *p, char const *contents);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context to set the PEM certificate for. |
| `contents` *Type: `char const*` | String containing the PEM certificate. Must remain valid for the lifetime of the context. Use `NULL` to remove the certificate. |

### Sample code

```c
static char const my_cert[] = "-----BEGIN CERTIFICATE-----\n"
...
    "-----END CERTIFICATE-----\n";

pubnub_ssl_set_usrdef_pem_cert(pbp, my_cert);
```

### Returns

None.

## Set/enable use of system certificate store

Instructs C-core to use the system certificate store for the context. This is only available on targets with a system certificate store (such as Windows).

By default, the system certificate store is not used. When enabled, it takes precedence over other certificates. To disable it later, call `pubnub_ssl_dont_use_system_certificate_store()`.

#### Preconditions

* The context must be valid.

### Method(s)

```c
int pubnub_ssl_use_system_certificate_store(pubnub_t *p);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context for which to enable the system certificate store. |

### Sample code

```c
if (0 != pubnub_ssl_use_system_certificate_store(pbp)) {
    puts("Using system certificate store not supported");
}
```

### Returns

| Type | Value | Description |
| --- | --- | --- |
| `int` | `0` | OK. |
| `int` | `-1` | System certificate store not supported. |

## Unset/disable use of system certificate store

Disables the system certificate store for the context (this is also the default). Use this function only to reverse a previous call to `pubnub_ssl_use_system_certificate_store()`.

#### Preconditions

* The context must be valid.

### Method(s)

```c
void pubnub_ssl_dont_use_system_certificate_store(pubnub_t *p);
```

| Parameter | Description |
| --- | --- |
| `p` *Type: `pubnub_t*` | The context for which to disable the system certificate store. |

### Sample code

```c
pubnub_ssl_dont_use_system_certificate_store(pbp);
```

### Returns

None.

## Generate UUID random

Generates a UUID using the v4 algorithm (random-based). This algorithm needs no state but requires a random number generator of good quality, which may not be available on all platforms.

### Method(s)

```c
int pubnub_generate_uuid_v4_random(struct Pubnub_UUID *uuid)
```

| Parameter | Description |
| --- | --- |
| `uuid` *Type: `struct Pubnub_UUID*` | Pointer to store the generated UUID. |

### Sample code

```c
struct Pubnub_UUID uuid;
if (0 == pubnub_generate_uuid_v4_random(&uuid)) {
    puts("UUID generation unsuccessful");
}
```

### Returns

| Type | Description |
| --- | --- |
| `int` | `0`: generated successfully. Non-zero: random number generator not available. |

### Other examples

#### Subscribe to a channel with a unique name

```c
struct Pubnub_UUID uuid;
char channel_name;
if (0 == pubnub_generate_uuid_v4_random(&uuid)) {
    channel_name = pubnub_uuid_to_string(&uuid).uuid;
}
pubnub_t ctx = pubnub_alloc();
if (NULL == ctx) {
    puts("Couldn't allocate a Pubnub context");
    return -1;
}
pubnub_init(ctx, "demo", "demo");
pubnub_subscribe(ctx, channel_name, NULL);
pbresult = pubnub_await(ctx);
if (pbresult != PNR_OK) {
    printf("Failed to subscribe, error %d\n", pbresult);
    pubnub_free(ctx);
    return -1;
}
else {
    char const msg = pubnub_get(ctx);
    char const channel = pubnub_get_channel(ctx);
    while (msg != NULL) {
        printf("Got message: %s on channel %s\n", msg, (NULL == channel) ? "" : channel );
        msg = pubnub_get(ctx);
        channel = pubnub_get_channel(ctx);
    }
}
pubnub_free(ctx);
```

#### Create a unique authentication key for Access Manager

```c
struct Pubnub_UUID uuid;
char *auth_key;
if (0 == pubnub_generate_uuid_v4_random(&uuid)) {
    auth_key = pubnub_uuid_to_string(&uuid).uuid;
    pubnub_init(ctx, "demo", "demo");
    pubnub_set_auth(ctx, auth_key);
}
```

## Generate UUID MD5

Generates a UUID using the v3 algorithm (name-based with MD5 hash). MD5 may not be available on all platforms.

### Method(s)

```c
int pubnub_generate_uuid_v3_name_md5(struct Pubnub_UUID *uuid, struct Pubnub_UUID *nsid, void *name, unsigned namelen)
```

| Parameter | Description |
| --- | --- |
| `uuid` *Type: `struct Pubnub_UUID*` | Pointer to store the generated UUID. |
| `nsid` *Type: `struct Pubnub_UUID*` | UUID of the namespace. |
| `name` *Type: `void*` | Pointer to the data that defines the name for UUID generation. |
| `namelen` *Type: `unsigned` | Length of the name data. |

### Sample code

```c
char *name = "abcd";
struct Pubnub_UUID uuid;
struct Pubnub_UUID nsid =  { {'x', 'y', 'z', 0} };;
if (0 != pubnub_generate_uuid_v3_name_md5(&uuid, &nsid, name, 4)) {
    puts("UUID generation unsuccessful");
}
```

### Returns

| Type | Description |
| --- | --- |
| `int` | `0`: generated successfully. Non-zero: algorithm not available. |

## Generate UUID time

Generates a UUID using the v1 algorithm (time-based). This algorithm uses the MAC address (or another identifier) as the node identity, a 100-nanosecond timestamp since October 15, 1582, and a clock sequence.

On the first call, provide a random value in `io_clock_seq`. On subsequent calls, reuse the same variable; the function updates it as needed. If you don't have a random number generator, use any pseudo-random source (such as a timer tick) and mix the values with XOR.

While complex to use, this algorithm is highly portable and can work on virtually any platform without needing to obtain unique identifiers yourself.

### Method(s)

```c
int pubnub_generate_uuid_v1_time(struct Pubnub_UUID *o_uuid, uint16_t *io_clock_seq, uint8_t const i_timestamp[8], uint8_t const i_node[6]);
```

| Parameter | Description |
| --- | --- |
| `o_uuid` *Type: `struct Pubnub_UUID*` | Pointer to store the generated UUID. |
| `io_clock_seq` *Type: `uint16_t*` | Clock sequence. Initialize to a random value on first call, then reuse. |
| `i_timestamp` *Type: `uint8_t const[8]` | Count of 100-nanosecond intervals since 00:00:00.00, 15 October 1582. |
| `i_node` *Type: `uint8_t const[6]` | A 6-octet node identity (typically an IEEE 802 MAC address). |

### Sample code

```c
struct Pubnub_UUID uuid;
uint16_t clock_seq = 4443; /* some random value */
uint8_t timestamp[8]; /* get a time stamp somehow */
uint8_t node[6] = { 0x5F, 0x82, 0x11, 0x58, 0x02, 0x61 }; /* example MAC address */
if (0 != pubnub_generate_uuid_v1_time(&uuid, &clock_seq, timestamp, node)) {
    printf("Failed to generate a v1 (time based) UUID\n");
}
```

### Returns

| Type | Description |
| --- | --- |
| `int` | `0`: generated successfully. Non-zero: algorithm not available. |

## UUID compare

Compares two UUIDs and returns an integer indicating their relative order: `0` if equal, less than `0` if left is smaller, greater than `0` if left is larger.

### Method(s)

```c
int pubnub_uuid_compare(struct Pubnub_UUID const *left, struct Pubnub_UUID const *right)
```

| Parameter | Description |
| --- | --- |
| `left` *Type: `struct Pubnub_UUID const*` | First UUID to compare. |
| `right` *Type: `struct Pubnub_UUID const*` | Second UUID to compare. |

### Sample code

```c
struct Pubnub_UUID left;
struct Pubnub_UUID right;
if (0 != pubnub_generate_uuid_v4_random(&left) || 0 != pubnub_generate_uuid_v4_random(&right)) {
    puts("UUID generation unsuccessful");
}
int RC = pubnub_uuid_compare(left, right);
if (0 == RC) puts ("left == right");
else if (RC > 0) puts("left > right");
else puts ("left < right");
```

### Returns

| Type | Description |
| --- | --- |
| `int` | `0` if equal, <0 if left < right, >0 if left > right. |

## UUID to string

Returns a UUID as a standard hexadecimal string representation.

### Method(s)

```c
struct Pubnub_UUID_String pubnub_uuid_to_string(struct Pubnub_UUID const *uuid)
```

| Parameter | Description |
| --- | --- |
| `uuid` *Type: `struct Pubnub_UUID const*` | UUID to convert to string. |

### Sample code

```c
struct Pubnub_UUID uuid;
if (0 == pubnub_generate_uuid_v4_random(&uuid)) {
    printf("UUID generation successful. UUID is %s", pubnub_uuid_to_string(&uuid).uuid);
}
```

### Returns

| Type | Description |
| --- | --- |
| `struct Pubnub_UUID_String` | String representation of the UUID. |

## PubNub SDK name

Returns a string with the name of the PubNub SDK client.

### Method(s)

```c
char const *pubnub_sdk_name(void)
```

This method has no arguments.

### Sample code

```c
printf("SDK name  : %s", pubnub_sdk_name());
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | Name of the PubNub SDK client. |

## PubNub version

Returns a string with the version of the PubNub SDK client.

### Method(s)

```c
char const *pubnub_version(void)
```

This method has no arguments.

### Sample code

```c
printf("VERSION : %s", pubnub_version());
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | Version of the PubNub SDK client. |

## PubNub uname

Returns a URL-encoded string with the full identification of the SDK, including name, version, and possibly additional metadata.

### Method(s)

```c
char const *pubnub_uname(void)
```

This method has no arguments.

### Sample code

```c
printf("uname : %s", pubnub_uname());
```

### Returns

| Type | Description |
| --- | --- |
| `char const*` | URL-encoded string with full SDK identification. |

## PubNub SRAND time

Seeds the C standard `srand()` function using the time returned from PubNub's `time` operation. This is useful for systems without a Real-Time Clock (RTC) that need a high-fidelity time seed.

This function requires a round-trip to PubNub and assumes the sync interface (it uses `pubnub_await()` internally). Call it only once at program start.

### Method(s)

```c
int srand_from_pubnub_time(pubnub_t *pbp);
```

| Parameter | Description |
| --- | --- |
| `pbp` *Type: `pubnub_t*` | The PubNub context to use to get time. |

### Sample code

```c
printf("srand from pubnub time %s\n", srand_from_pubnub_time(ctx));
```

### Returns

| Type | Description |
| --- | --- |
| `int` | `0`: OK. `-1`: error (`srand()` was not called). |

## Enums

### pubnub_res

Result codes for functions and transactions.

| Member | Description |
| --- | --- |
| `PNR_OK` | Success. Transaction finished successfully. |
| `PNR_ADDR_RESOLUTION_FAILED` | PubNub host name resolution failed. Could not get an IP address from the PubNub host name (`origin`). Most often caused by a DNS error. |
| `PNR_CONNECT_FAILED` | Connecting to the PubNub server failed. Usually indicates a network outage. If using SSL/TLS, it could also be a TLS error. |
| `PNR_CONNECTION_TIMEOUT` | A timeout occurred in the network, typically because of a network outage while connected to the PubNub server. |
| `PNR_TIMEOUT` | Timeout before the request completed. Detected by the PubNub client itself, not the TCP/IP stack. |
| `PNR_ABORTED` | Connection to PubNub aborted (in most cases, a TCP reset was received). |
| `PNR_IO_ERROR` | Communication error (network or HTTP response format). |
| `PNR_HTTP_ERROR` | HTTP error. Call `pubnub_last_http_code()` to get the error code. |
| `PNR_FORMAT_ERROR` | Unexpected input in received JSON. |
| `PNR_CANCELLED` | Request cancelled by user. |
| `PNR_STARTED` | Transaction started. Await the outcome. |
| `PNR_IN_PROGRESS` | Transaction already ongoing. Cannot start a transaction while another is in progress. |
| `PNR_RX_BUFF_NOT_EMPTY` | Receive buffer (from previous transaction) not read; cannot start a subscription. |
| `PNR_TX_BUFF_TOO_SMALL` | The buffer is too small. Increase `PUBNUB_BUF_MAXLEN`. |
| `PNR_INVALID_CHANNEL` | Channel specification or name is invalid. |
| `PNR_PUBLISH_FAILED` | Publish transaction failed. Call `pubnub_last_publish_result()` to see the reason. |
| `PNR_CHANNEL_REGISTRY_ERROR` | Channel registry transaction failed. Get the value for key `message` from the JSON response for the error description, and key `status` for the numeric error code. |
| `PNR_REPLY_TOO_BIG` | Reply is too big to fit in the reply buffer (whether statically or dynamically allocated). |

### pubnub_trans

Type of PubNub operation/transaction.

| Member | Description |
| --- | --- |
| `PBTT_NONE` | No transaction. |
| `PBTT_SUBSCRIBE` | Subscribe operation. |
| `PBTT_PUBLISH` | Publish operation. |
| `PBTT_LEAVE` | Leave channel(s) operation. |
| `PBTT_TIME` | Time (get server time) operation. |
| `PBTT_HISTORY` | History V2 (get message history for a channel) operation. |
| `PBTT_HERENOW` | Here-now (get user IDs of users present in channel(s)) operation. |
| `PBTT_GLOBAL_HERENOW` | Global here-now (get user IDs of users present across all channels) operation. |
| `PBTT_WHERENOW` | Where-now (get channels where a user is present) operation. |
| `PBTT_SET_STATE` | Set state (for a user on channel(s)) operation. |
| `PBTT_STATE_GET` | Get state (for a user on channel(s)) operation. |
| `PBTT_REMOVE_CHANNEL_GROUP` | Remove a channel group operation. |
| `PBTT_REMOVE_CHANNEL_FROM_GROUP` | Remove a channel from a channel group operation. |
| `PBTT_ADD_CHANNEL_TO_GROUP` | Add a channel to a channel group operation. |
| `PBTT_LIST_CHANNEL_GROUP` | List all channels in a channel group operation. |

## IPv4 structure

IPv4 address in binary format.

### Method(s)

```c
struct pubnub_ipv4_address {uint8_t ipv4[4];};
```

### Members

| Member | Type | Description |
| --- | --- | --- |
| `ipv4` | `uint8_t[4]` | The four octets of the IPv4 address. |

## IPv6 structure

IPv6 address in binary format.

:::note Availability
This structure is only available when the SDK is built with `PUBNUB_USE_IPV6` enabled. For more information, see [PUBNUB_USE_IPV6](https://www.pubnub.com/docs/sdks/c-core/api-reference/configuration#pubnub_use_ipv6-enable-ipv6-support).
:::

### Method(s)

```c
struct pubnub_ipv6_address {uint8_t ipv6[16];};
```

### Members

| Member | Type | Description |
| --- | --- | --- |
| `ipv6` | `uint8_t[16]` | The 8 double octets (big endian) of the IPv6 address. |