Publish/Subscribe API for C-Core SDK (legacy)

New SDK available

C-Core (legacy) is still supported. If you are starting a new project, use the new C SDK.

The foundation of the PubNub service is the ability to send a message reliably and quickly. PubNub's publish-processing latency, the time to accept and acknowledge a publish request, is about 0.5 ms within the same region. Send a message to just one other person, or broadcast to thousands of subscribers at once.

For higher-level conceptual details on publishing and subscribing, refer to Connection Management and to Publish Messages.

Publish​

The pubnub_publish() function is used to send a message to all subscribers of a channel. To publish a message you must first specify a valid publish_key at initialization. A successfully published message is replicated across the PubNub Real-Time Network and sent simultaneously to all subscribed clients on a channel.

Messages in transit can be secured from potential eavesdroppers with SSL/TLS by setting ssl to true during initialization.

  • You must initialize PubNub with the publishKey.
  • You don't have to be subscribed to a channel to publish to it.
  • You cannot publish to multiple channels simultaneously.

Method(s)​

To Publish a message you can use the following method(s) in the C-Core (legacy) SDK:

1enum pubnub_res pubnub_publish (
2 pubnub_t *p,
3 const char *channel,
4 const char *message
5)
* required
ParameterDescription
p *
Type: pubnub_t*
Pointer to PubNub context. Can't be NULL
channel *
Type: const char*
Pointer to string with the channel ID (or comma-delimited list of channel IDs) to publish to.
message *
Type: const char*
Pointer to string containing message to publish in JSON format.
1enum pubnub_res pubnub_publishv2 (
2 pubnub_t *p,
3 const char *channel,
4 const char *message,
5 bool store_in_history,
6 bool eat_after_reading
7)
* required
ParameterDescription
p *
Type: pubnub_t*
Pointer to Pubnub Client Context
channel *
Type: const char*
Pointer to string with the channel ID (or comma-delimited list of channel IDs) to publish to.
message *
Type: const char*
Pointer to string containing message to publish in JSON format.
store_in_history *
Type: bool
If false, message will not be stored in history of the channel ID.
eat_after_reading *
Type: const char*
If true, message will not be stored for delayed or repeated retrieval or display.

Sample code​

Publish a message to a channel​

1pubnub_publish(ctx, "my_channel", "\"message\"");
2pbresult = pubnub_await(ctx);
3if (PNR_OK == pbresult) {
4 /* Published successfully */
5}
Subscribe to the channel

Before running the above publish example, either using the Debug Console or in a separate script running in a separate terminal window, subscribe to the same channel that is being published to.

Rest response from server​

The function returns the following formatted response:

1[1, "Sent", "13769558699541401"]

Other examples​

Publish a JSON serialized message

1

2pubnub_t *ctx = pubnub_alloc();
3if (NULL == ctx) {
4 puts("Couldn't allocate a Pubnub context");
5 return -1;
6}
7pubnub_init(ctx, "demo", "demo");
8pubnub_set_user_id(ctx, "MyUniqueUser_Id");
9pubnub_publish(ctx, "hello_world", "{\"msg\": \"Hello from Pubnub C-core docs!\"}");
10enum pubnub_res pbresult = pubnub_await(ctx);
11if (pbresult != PNR_OK) {
12 printf("Failed to publish, error %d\n", pbresult);
13 pubnub_free(ctx);
14 return -1;
15}

Publish with cipher key​

1res = pubnub_publish_encrypted(pbp, chan, "\"Hello world from crypto sync!\"", cipher_key);
2if (res != PNR_STARTED) {
3 printf("pubnub_publish() returned unexpected: %d\n", res);
4 pubnub_free(pbp);
5 return -1;
6}

Publish with cipher key using pubnub_publish_ex​

Using this method you can reuse the cipherKey from the options.

1struct pubnub_publish_options options = pubnub_publish_defopts();
2options.cipher_key = my_cipher_key;
3enum pubnub_res pbresult = pubnub_publish_ex(pn, "my_channel", "42", options);

Extended publish​

Extended publish options structure​

Holds all the options for extended publish.

Method(s)​

Declaration​

1struct pubnub_publish_options {
2 bool store;
3 char const *cipher_key;
4 bool replicate;
5 char const *meta;
6 enum pubnub_publish_method method;
7 char const* custom_message_type;
8}

Members​

MemberTypeDescription
storeboolIf true, the message is stored in history. If false, the message is not stored in history.
cipher_keychar const*If not NULL, the key used to encrypt the message before sending it to PubNub. Keep in mind that encryption is a CPU intensive task. Also, it uses more bandwidth, most of which comes from the fact that decrypted data is sent as Base64 encoded JSON string. This means that the actual amount of data that can be sent as encrypted in a message is at least 25% smaller (than un-encrypted). Another point to be made is that it also does some memory management (allocating and deallocating).
replicateboolIf true, the message is replicated, thus will be received by all subscribers. If false, the message is not replicated and will be delivered only to Function event handlers. Setting false here and false on store is referred to as a Fire (instead of a publish).
metachar const*An optional JSON object, used to send additional (meta) data about the message, which can be used for stream filtering.
methodenum pubnub_publish_methodDefines the method by which publish transaction will be performed. Can be HTTP GET or POST. If using POST, content can be GZIP compressed.
ttlsize_tHow many hours message should be kept and available in Storage.
custom_message_typechar const*A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes - and underscores _ are allowed. The value cannot start with special characters or the string pn_ or pn-.

Examples: text, action, poll.

Initialize extended publish options​

This returns the default options for publish V1 transactions. Will set:

Parameter
store
Default:
true
cipher_key
Default:
NULL
replicate
Default:
true
meta
Default:
NULL
method
Default:
pubnubPublishViaGET
custom_message_type
Default:
NULL

Method(s)​

Declaration​

struct pubnub_publish_options pubnub_publish_defopts(void);

Parameters​

This method doesn't take any argument.

Sample code​

1struct pubnub_publish_options opts = pubnub_publish_defopts();

Returns​

TypeValueDescription
struct pubnub_publish_optionsThe default options for publish.

Extended publish​

The extended publish V1. Basically the same as pubnub_publish(), but with added optional parameters in @p opts.

Method(s)​

Declaration​

1enum pubnub_res pubnub_publish_ex(
2 pubnub_t *p,
3 const char *channel,
4 const char *message,
5 struct pubnub_publish_options opts
6)

Parameters​

* required
ParameterDescription
p *
Type: pubnub_t*
The Pubnub context.
channel *
Type: char const*
The string with the channel ID to publish to.
message *
Type: char const*
The message to publish. It needs to be JSON encoded.
opts *
Type: struct pubnub_publish_options
The Publish options.

Sample code​

1struct pubnub_publish_options options = pubnub_publish_defopts();
2options.store = false;
3enum pubnub_res pbresult = pubnub_publish_ex(pn, "my_channel", "42", options);

Returns​

TypeValueDescription
enum pubnub_resPNR_STARTEDSuccess.
otherIndicates the type of error.

Signal​

Sends a signal @p message (in JSON format) on @p channel, using the @p pb context. This actually means "initiate a signal transaction".

It has similar behavior as publish, but unlike publish transaction, signal erases previous signal message on server (on a given channel,) and you can not send any metadata.

There can be only up to one signal message at the time. If it's not renewed by another signal, signal message disappears from channel history after a certain amount of time.

You can't (send a) signal if a transaction is in progress on @p pb context.

If transaction is not successful (@c PNR_PUBLISH_FAILED), you can get the string describing the reason for failure by calling pubnub_last_publish_result().

Keep in mind that the timetoken from the signal operation response is not parsed by the library, just relayed to the user. Only time-tokens from the subscribe operation are parsed by the library.

Also, for all error codes known at the time of this writing, the HTTP error will also be set, so the result of the PubNub operation will not be @c PNR_OK (but you will still be able to get the result code and the description).

By default, signals are limited to a message payload size of 64 bytes. This limit applies only to the payload, and not to the URI or headers. If you require a larger payload size, please contact support.

Method(s)​

Declaration​

1enum pubnub_res pubnub_signal(
2 pubnub_t* pb,
3 char const* channel,
4 char const* message
5)

Parameters​

* required
ParameterDescription
pb *
Type: pubnub_t*
The Pubnub context in which to parse the response.
channel *
Type: char const*
The string with the channel ID to signal to.
message *
Type: char const*
The string with the signal, expected to be in JSON format.

Sample code​

Signal a message to a channel​

1enum pubnub_res = pubnub_signal(pb, "my_channel", "\"signalling\"");

Returns​

TypeValueDescription
enum pubnub_resPNR_OKTransaction finished (signal sent).
PNR_STARTEDTransaction started (started to send signal), will finish later.
otherwiseError, value indicates the reason for failure.

Message type enumeration (enum pubnub_message_type)​

Defines the type of a message that is retrieved with subscribe V2:

SymbolValueDescription
pbsbPublished0Published message (sent via Publish transaction)
pbsbSignal1A signal message (sent via Signal transaction)

Extended signal​

Extended signal options structure​

Holds all the options for extended signal.

Method(s)​

Declaration​

1struct pubnub_signal_options {
2 char const* custom_message_type;
3};

Members​

MemberTypeDescription
custom_message_typechar const*A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes - and underscores _ are allowed. The value cannot start with special characters or the string pn_ or pn-.

Examples: text, action, poll.

Initialize extended signal options​

This returns the default options for signal transactions. Will set:

Parameter
custom_message_type
Default:
NULL

Method(s)​

Declaration​

struct pubnub_signal_options pubnub_signal_defopts(void);

Parameters​

This method doesn't take any argument.

Sample code​

1struct pubnub_signal_options options = pubnub_signal_defopts();
2options.custom_message_type = "test-message";
3enum pubnub_res pbresult = pubnub_signal_ex(ctx, "my_channel", "status:active", options);

Extended signal​

The extended signal V1. Basically the same as pubnub_signal(), but with added optional parameters in @p opts.

Method(s)​

Declaration​

1enum pubnub_res pubnub_signal_ex(
2 pubnub_t* pb,
3 const char* channel,
4 const char* message,
5 struct pubnub_signal_options opts);

Parameters​

* required
ParameterDescription
pb *
Type: pubnub_t*
The Pubnub context.
channel *
Type: char const*
The string with the channel ID to signal to.
message *
Type: char const*
The message to signal. It needs to be JSON encoded.
opts *
Type: struct pubnub_signal_options
The Signal options.

Sample code​

1struct pubnub_signal_options options = pubnub_signal_defopts();
2options.custom_message_type = "test-message";
3enum pubnub_res pbresult = pubnub_signal_ex(ctx, "my_channel", "status:active", options);

Returns​

TypeValueDescription
enum pubnub_resPNR_STARTEDSuccess.
otherIndicates the type of error.

Returns​

TypeValueDescription
struct pubnub_signal_optionsThe default options for signal.

Subscribe (new)​

The subscribe function creates an open TCP socket to PubNub and begins listening for messages and events on a specified entity or set of entities. To subscribe successfully, you must configure the appropriate subscribeKey at initialization.

Conceptual overview

For more general information about subscriptions, refer to Subscriptions.

Entities are first-class citizens that provide access to their encapsulated APIs. You can subscribe using the PubNub client object or directly on a specific entity:

A newly subscribed client receives messages after the subscribe() call completes. You can configure automatic retries to attempt to reconnect automatically and retrieve any available messages if a client gets disconnected.

Subscription scope​

Subscription objects provide an interface to attach listeners for various real-time update types. Your app receives messages and events via those event listeners. Two types of subscriptions are available:

  • Subscription, created from an entity with a scope of only that entity (for example, a particular channel)
  • SubscriptionSet, created from the PubNub client with a global scope (for example, all subscriptions created on a single pubnub object ). A subscription set can have one or more subscriptions.

The event listener is a single point through which your app receives all the messages, signals, and events in the entities you subscribed to. For information on adding event listeners, refer to Event listeners.

Create a subscription​

An entity-level Subscription allows you to receive messages and events for only that entity for which it was created. Using multiple entity-level Subscriptions is useful for handling various message/event types differently in each channel.

1// entity-based, local-scoped, with options
2pubnub_subscription_options_t options = pubnub_subscription_options_defopts();
3options.receive_presence_events = true;
4pubnub_subscription_t* subscription = pubnub_subscription_alloc(
5 entity,
6 &options);
7if (NULL == subscription) {
8 // Handle parameters error (missing entity or invalid PubNub context pointer) or insufficient memory.
9}
10
11// entity-based, local-scoped, without options
12pubnub_subscription_t* subscription = pubnub_subscription_alloc(entity, NULL);
13if (NULL == subscription) {
14 // Handle error for missing entity or invalid PubNub context pointer or insufficient memory.
15}
* required
ParameterDescription
options.receive_presence_events
Type: bool
Whether presence updates for userIds should be delivered through the listener streams.

For information on how to receive presence events and what those events are, refer to Presence Events.

Create a subscription set​

A client-level SubscriptionSet allows you to receive messages and events for all entities. A single SubscriptionSet is useful for similarly handling various message/event types in each channel.

1// client-based, general-scoped, with options
2pubnub_subscription_options_t options = pubnub_subscription_options_defopts();
3options.receive_presence_events = true;
4pubnub_subscription_set_t* subscription_set = pubnub_subscription_set_alloc_with_entities(
5 entities,
6 4,
7 &options);
8if (NULL == subscription_set) {
9 // Handle parameters error (missing entities or invalid entity's PubNub context pointer) or insufficient memory.
10}
11
12// client-based, general-scoped, without options
13pubnub_subscription_set_t* subscription_set = pubnub_subscription_set_alloc_with_entities(
14 entities,
15 4,
show all 19 lines
* required
ParameterDescription
entities *
Type: pubnub_entity_t**
Pointer to the array with PubNub entities object pointers which should be used in subscriptions set.
entities_count *
Type: int
The number of PubNub entities in array.
options *
Type: const pubnub_subscription_options_t*
Pointer to the subscription configuration options. Set to NULL if options are not required.

Method(s)​

Subscription and SubscriptionSet use the same subscribe() method.

Subscribe​

To subscribe, you can use the following method in the c SDK:

1enum pubnub_res pubnub_subscribe_with_subscription(
2 pubnub_subscription_t* sub,
3 const pubnub_subscribe_cursor_t* cursor);
* required
ParameterDescription
cursor
Type: const pubnub_subscribe_cursor_t
Timetoken from which to return any available cached messages. Message retrieval with timetoken is not guaranteed and should only be considered a best-effort service.

If the value is not a 17-digit number, the provided value will be ignored.
sub
Type: pubnub_subscription_t*
Pointer to the subscription, which should be used with the next subscription loop.
1// subscription cursor
2// timetoken is a pointer to the PubNub high-precision timetoken
3pubnub_subscribe_cursor_t pubnub_subscribe_cursor(
4 const char* timetoken);
Sample code​
enum pubnub_res rslt = pubnub_subscribe_with_subscription(subscription, NULL);
if (PNR_OK != rslt) {
// Handle subscription error (mostly because of parameters error).
}
Returns​

The subscribe() method doesn't have a return value.

Entities​

Entities are subscribable objects for which you can receive real-time updates (messages, events, etc).

Create channels​

This method returns a local Channel entity.

pubnub_channel_t* pubnub_channel_alloc(
pubnub_t* pb,
const char* name);
* required
ParameterDescription
pb *
Type: pubnub_t*
Pointer to the PubNub context used by the created entity to interact with PubNub REST API.
name *
Type: const char*
Pointer to the name of the channel to create.

Sample code​

pubnub_channel_t* channel = pubnub_channel_alloc(pb, "my_channel");

Create channel groups​

This method returns a local Channel Group entity.

pubnub_channel_group_t* pubnub_channel_group_alloc(
pubnub_t* pb,
const char* name);
* required
ParameterDescription
pb *
Type: pubnub_t*
Pointer to the PubNub context used by the created entity to interact with PubNub REST API.
name *
Type: const char*
Pointer to the name of the channel group to create.

Sample code​

pubnub_channel_group_t* group = pubnub_channel_group_alloc(pb, "my_group");

Create channel metadata​

This method returns a local Channel Metadata entity.

pubnub_channel_metadata_t* pubnub_channel_metadata_alloc(
pubnub_t* pb,
const char* id);
* required
ParameterDescription
pb *
Type: pubnub_t*
Pointer to the PubNub context used by the created entity to interact with PubNub REST API.
id *
Type: const char*
The String identifier of the channel metadata object to create.

Sample code​

pubnub_channel_metadata_t* metadata = pubnub_channel_metadata_alloc(pb, "channel_meta");

Create user metadata​

This method returns a local User Metadata entity.

pubnub_user_metadata_t* pubnub_user_metadata_alloc(
pubnub_t* pb,
const char* id);
* required
ParameterDescription
pb *
Type: pubnub_t*
Pointer to the PubNub context used by the created entity to interact with PubNub REST API.
id *
Type: const char*
The String identifier of the user metadata object to create a subscription of.

Sample code​

pubnub_user_metadata_t* metadata = pubnub_user_metadata_alloc(pb, "user_meta");

Event listeners​

Messages and events are received in your app using a listener. This listener allows a single point to receive all messages, signals, and events.

You can attach listeners to the instances of Subscription, Subscription Set, and, in the case of the connection status, the PubNub client.

No built-in event throttling

The PubNub SDK delivers every incoming event to your listener as it arrives — there is no built-in throttling or rate-limiting on the subscriber side. If you need to control how often your application processes events, wrap your listener callback with a throttle or debounce utility from your language or framework ecosystem.

To reduce the number of messages delivered to your client in the first place, use Subscribe Filters to filter messages server-side before they reach your listener.

Add listeners​

You can implement multiple listeners or register an event-specific listener that receives only a selected type, like message or file.

Method(s)​

// Add event-specific listeners

// reacts to all subscriptions on a given pubnub object
enum pubnub_res pubnub_subscribe_add_message_listener(
const pubnub_t* pb,
pubnub_subscribe_listener_type type,
pubnub_subscribe_message_callback_t callback
void* custom_data);

// reacts to a specific event type on a given subscription
enum pubnub_res pubnub_subscribe_add_subscription_listener(
const pubnub_subscription_t* subscription,
pubnub_subscribe_listener_type type,
pubnub_subscribe_message_callback_t callback
void* custom_data);
show all 58 lines
* required
ParameterDescription
pb *
Type: pubnub_t*
Pointer to the PubNub context used by the created entity to interact with PubNub REST API.
type *
Type: pubnub_subscribe_listener_type
Type of real-time update for which listener will be called. Available types include: LISTENER_ON_MESSAGE, LISTENER_ON_SIGNAL, LISTENER_ON_MESSAGE_ACTION, LISTENER_ON_OBJECTS, and LISTENER_ON_FILES.
callback *
Type: pubnub_subscribe_message_callback_t
Function to handle the listener status change.
custom_data
Type: void*
Pointer to the custom data that is passed to the callback function. Can be NULL if no data is required.

Add connection status listener​

The PubNub client has a listener dedicated to handling connection status updates.

Client scope

This listener is only available on the PubNub object.

Method(s)​

1// add status listener
2enum pubnub_res pubnub_subscribe_add_status_listener(
3 const pubnub_t* pb,
4 pubnub_subscribe_status_callback_t callback
5 void* custom_data);
6
7// remove status listener
8enum pubnub_res pubnub_subscribe_remove_status_listener(
9 const pubnub_t* pb,
10 pubnub_subscribe_status_callback_t callback
11 void* custom_data);
* required
ParameterDescription
pb *
Type: pubnub_t*
Pointer to the PubNub context used by the created entity to interact with PubNub REST API.
callback *
Type: pubnub_subscribe_message_callback_t
Function to handle the listener status change.
custom_data
Type: void*
Pointer to the custom data that is passed to the callback function. Can be NULL if no data is required.

Sample code​

1void subscribe_status_change_listener(
2 const pubnub_t* pb,
3 const pubnub_subscription_status status,
4 const pubnub_subscription_status_data_t status_data,
5 void* custom_data)
6
7{
8 // Handle new subscription status
9}
10
11// Add listener
12pubnub_subscribe_add_status_listener(pb, subscribe_status_change_listener, NULL);
13
14// Remove listener
15pubnub_subscribe_remove_status_listener(pb, subscribe_status_change_listener, NULL);
Add / remove listener with custom data​
void subscribe_status_change_listener(
const pubnub_t* pb,
const pubnub_subscription_status status,
const pubnub_subscription_status_data_t status_data,
void* custom_data)

{
// you need to cast custom_data to the correct type
if (NULL != data) {
printf("\t- data: %s\n", (char*)data);
}
// Handle new subscription status
}

char* custom_data = "custom user data";
show all 24 lines

Returns​

The subscription status. For information about available statuses, refer to SDK statuses.

Unsubscribe​

Stop receiving real-time updates from a Subscription or a SubscriptionSet.

Method(s)​

enum pubnub_res pubnub_unsubscribe_with_subscription(
pubnub_subscription_t** sub);

enum pubnub_res pubnub_unsubscribe_with_subscription_set(
pubnub_subscription_set_t** set);

Sample code​

1enum pubnub_res rslt = pubnub_unsubscribe_with_subscription(&subscription);
2if (PNR_OK != rslt) {
3 // handle unsubscription error (mostly because of parameters error).
4}

Returns​

None

Unsubscribe all​

Stop receiving real-time updates from all data streams and remove the entities associated with them.

Client scope

This method is only available on the PubNub object.

Method(s)​

1enum pubnub_res pubnub_unsubscribe_all(const pubnub_t* pb);

Sample code​

1enum pubnub_res rslt = pubnub_unsubscribe_all(pb);
2 if (PNR_OK != rslt) {
3 // handle unsubscribe all error
4 }

Returns​

None

Subscribe (old)​

This function causes the client to create an open TCP socket to the PubNub Real-Time Network and begin listening for messages on a specified channel. To subscribe to a channel the client must send the appropriate subscribe_key at initialization. By default a newly subscribed client will only receive messages published to the channel after the pubnub_subscribe() call completes.

Message retrieval

Typically, you will want two separate contexts for publish and subscribe. When changing the active set of subscribed channels, first call pubnub_leave() on the old set. The pubnub_subscribe() interface is essentially a transaction to start listening on the channel for arrival of next message. This has to be followed by pubnub_get() call to retrieve the actual message, once the subscribe transaction completes successfully. This needs to be performed every time it is desired to retrieve a message from the channel.

Unsubscribing from all channels

Unsubscribing from all channels, and then subscribing to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received timetoken and thus, there could be some gaps in the subscription that may lead to message loss.

Method(s)​

To Subscribe to a channel you can use the following method(s) in the C-Core (legacy) SDK:

1enum pubnub_res pubnub_subscribe(
2 pubnub_t *p,
3 const char *channel,
4 const char *channel_group
5)
* required
ParameterDescription
p *
Type: pubnub_t*
Pointer to PubNub client context. Can't be NULL.
channel
Type: const char*
The string with the channel ID (or comma-delimited list of channel IDs) to subscribe to.
channel_group
Type: const char*
The string with the channel group name (or comma-delimited list of channel group names) to subscribe to.

Sample code​

Subscribe to a channel:

1pubnub_subscribe(ctx, "my_channel", NULL);
2pbresult = pubnub_await(ctx);
3if (PNR_OK == pbresult) {
4 char const *message = pubnub_get(ctx);
5 while (message != NULL) {
6 message = pubnub_get(ctx);
7 }
8}

Rest response from server​

The output below demonstrates the response format to a successful call:

1[[], "Time Token"]

Other examples​

Subscribing to multiple channels​

It's possible to subscribe to more than one channel using the Multiplexing feature. The example shows how to do that using an array to specify the channel names.

Alternative subscription methods

You can also use Wildcard Subscribe and Channel Groups to subscribe to multiple channels at a time. To use these features, the Stream Controller add-on must be enabled on your keyset in the Admin Portal.

1pubnub_t *ctx = pubnub_alloc();
2if (NULL == ctx) {
3 puts("Couldn't allocate a Pubnub context");
4 return -1;
5}
6pubnub_init(ctx, "demo", "demo");
7pubnub_set_user_id(ctx, "MyUniqueUser_Id")
8pubnub_subscribe(ctx, "hello_world1,hello_world2,hello_world3", NULL);
9pbresult = pubnub_await(ctx);
10if (pbresult != PNR_OK) {
11 printf("Failed to subscribe, error %d\n", pbresult);
12 pubnub_free(ctx);
13 return -1;
14}
15else {
show all 24 lines
Subscribing to a Presence channel​
Requires Presence

This method requires that the Presence add-on is enabled for your key in the Admin Portal.

For information on how to receive presence events and what those events are, refer to Presence Events.

For any given channel there is an associated Presence channel. You can subscribe directly to the channel by appending -pnpres to the channel name. For example the channel named my_channel would have the presence channel named my_channel-pnpres.

1// Sync
2
3char *presence_channel = malloc(strlen(channel) + strlen(PUBNUB_PRESENCE_SUFFIX) + 1);
4strcpy(presence_channel, channel);
5strcat(presence_channel, PUBNUB_PRESENCE_SUFFIX);
6pubnub_subscribe(ctx, presence_channel, NULL);
7pbresult = pubnub_await(ctx);
8if (PNR_OK == pbresult) {
9 char const *presence_event = pubnub_get(ctx);
10 while (presnce_event != NULL) {
11 presence_event = pubnub_get(ctx);
12 }
13}
14
15// Callback
show all 44 lines
Sample Responses​
Join event​
1{
2 "action": "join",
3 "timestamp": 1345546797,
4 "uuid": "175c2c67-b2a9-470d-8f4b-1db94f90e39e",
5 "occupancy": 2
6}
Leave event​
1{
2 "action" : "leave",
3 "timestamp" : 1345549797,
4 "uuid" : "175c2c67-b2a9-470d-8f4b-1db94f90e39e",
5 "occupancy" : 1
6}
Timeout event​
1{
2 "action": "timeout",
3 "timestamp": 1345549797,
4 "uuid": "76c2c571-9a2b-d074-b4f8-e93e09f49bd",
5 "occupancy": 0
6}
State change event​
1{
2 "action": "state-change",
3 "uuid": "76c2c571-9a2b-d074-b4f8-e93e09f49bd",
4 "timestamp": 1345549797,
5 "data": {
6 "isTyping": true
7 }
8}
Interval event​
1{
2 "action":"interval",
3 "timestamp":1474396578,
4 "occupancy":2
5}

When a channel is in interval mode with presence_deltas pnconfig flag enabled, the interval message may also include the following fields which contain an array of changed user_ids since the last interval message.

  • joined
  • left
  • timedout

For example, this interval message indicates there were 2 new user_ids that joined and 1 timed out user_id since the last interval:

1{
2 "action" : "interval",
3 "occupancy" : <# users in channel>,
4 "timestamp" : <unix timestamp>,
5 "joined" : ["uuid2", "uuid3"],
6 "timedout" : ["uuid1"]
7}

If the full interval message is greater than 30 KB (since the max publish payload is ∼32 KiB), none of the extra fields will be present. Instead there will be a here_now_refresh boolean field set to true. This indicates to the user that they should do a hereNow request to get the complete list of users present in the channel.

1{
2 "action" : "interval",
3 "occupancy" : <# users in channel>,
4 "timestamp" : <unix timestamp>,
5 "here_now_refresh" : true
6}
Subscribe to a channel group​
Requires Stream Controller add-on

This method requires that the Stream Controller add-on is enabled for your key in the Admin Portal. See Enable the features your app calls.

1enum pubnub_res res;
2
3for (;;) {
4 res = pubnub_subscribe(pn, NULL, channel_group);
5 read_response(pn, res);
6}
Subscribe to the Presence channel of a channel group​
Requires Stream Controller and Presence add-ons

This method requires both the Stream Controller and Presence add-ons are enabled for your key in the Admin Portal. See Enable the features your app calls.

1enum pubnub_res res;
2
3for (;;) {
4 res = pubnub_subscribe(pn, NULL, "family-pnpres");
5 read_response(pn, res);
6}
Using cipherKey with subscribe​

For subscribe, you don't use the cipher key at subscribe, but, when you get the received messages after the subscribe transaction has finished:

1char msg[MAX_MSG_LEN];
2pbresult = pubnub_get_decrypted(pn, my_cipher_key, s, sizeof s);
3if (PNR_OK == pbresult) {
4 /* Use the message in `msg` */
5}

or, for a different usability/safety trade-off:

1pubnub_bymebl_t msg = pubnub_get_decrypted_alloc(pn, my_cipher_key);
2if (msg.ptr != NULL) {
3 /* use the message in `msg.ptr` */
4 free(msg.ptr);
5}

Extended subscribe (old)​

Extended subscribe options structure​

Holds all the options for extended subscribe.

Method(s)​

Declaration​
1struct pubnub_subscribe_options {
2 char const* channel_group;
3 unsigned heartbeat;
4}
Members​
MemberTypeDescription
channel_groupchar const*Channel group (a comma-delimited list of channel group names). If NULL, will not be used.
cipher_keychar const*The channel activity timeout, in seconds. If below the minimum value supported by Pubnub, the minimum value will be used (instead).

Initialize extended subscribe options​

This returns the default options for subscribe transactions. Will set channel_group = NULL and heartbeat to default heartbeat value.

Method(s)​

Declaration​
1struct pubnub_subscribe_options pubnub_subscribe_defopts(void)
Parameter​

This method doesn't take any arguments.

Sample code​

1struct pubnub_subscribe_options opts = pubnub_subscribe_defopts();

Returns​

TypeValueDescription
struct pubnub_subscribe_optionsThe default options for subscribe.

Extended subscribe​

The extended subscribe. Basically the same as pubnub_subscribe() but with options except @p channel given in @p opts.

Method(s)​

Declaration​
1enum pubnub_res pubnub_subscribe_ex(
2 pubnub_t* p,
3 const char* channel,
4 struct pubnub_subscribe_options opts
5)
Parameter​
* required
ParameterDescription
p *
Type: pubnub_t*
The Pubnub context.
channel *
Type: char const*
The string with the channel ID (or comma-delimited list of channel IDs) to subscribe for.
opts *
Type: struct pubnub_subscribe_options
Subscribe options.

Sample code​

1struct pubnub_subscribe_options opt = pubnub_subscribe_defopts();
2opt.heartbeat = 412;
3pbresult = pubnub_subscribe_ex(pn, "my_channel", opt);

Returns​

TypeValueDescription
enum pubnub_resPNR_STARTEDSuccess.
otherIndicates the type of error.

Subscribe v2 (old)​

Subscribe v2 options structure​

Holds all the options for subscribe v2.

Method(s)​

Declaration​
1struct pubnub_subscribe_v2_options {
2 char const* channel_group;
3 unsigned heartbeat;
4}
Members​
MemberTypeDescription
channel_groupchar const*Channel group (a comma-delimited list of channel group names). If NULL, will not be used.
heartbeatunsignedThe channel activity timeout, in seconds. If below the minimum value supported by Pubnub, the minimum value will be used (instead).
char const*filter_exprThe filter expression to apply. It's a predicate to apply to the metadata of a message. If it returns true, message will be received, otherwise, it will be skipped (as if not published). Syntax is not trivial, but can be described as mostly Javascript on the metadata (which is JSON, thus, "integrates well" with Javascript). For example, if your metadata is: {"zec":3}, then this filter _would_ match it: zec==3, while zec==4 would _not_.
If message doesn't have metadata, this will be ignored.
If NULL, will not be used.

Initialize extended subscribe v2 options​

This returns the default options for subscribe transactions. Will set channel_group = NULL, heartbeat to default heartbeat value and filter_expr = NULL.

Method(s)​

Declaration​
1struct pubnub_subscribe_v2_options pubnub_subscribe_v2_defopts(void)
Parameter​

This method doesn't take any arguments.

Sample code​

1struct pubnub_subscribe_v2_options opts = pubnub_subscribe_v2_defopts();

Returns​

TypeValueDescription
struct pubnub_subscribe_optionsThe default options for subscribe.

Subscribe v2​

The V2 subscribe. To get messages for subscribe V2, use pubnub_get_v2() - keep in mind that it can provide you with channel and channel group info.

Method(s)​

Declaration​
1enum pubnub_res pubnub_subscribe_v2(
2 pubnub_t *p,
3 const char *channel,
4 struct pubnub_subscribe_v2_options opts
5)
Parameter​
* required
ParameterDescription
p *
Type: pubnub_t*
The Pubnub context.
channel *
Type: char const*
The string with the channel ID (or comma-delimited list of channel IDs) to subscribe for.
opts *
Type: struct pubnub_subscribe_options
Subscribe V2 options.

Sample code​

1struct pubnub_subscribe_v2_options opt = pubnub_subscribe_v2_defopts();
2opt.heartbeat = 412;
3pbresult = pubnub_subscribe_v2(pn, "my_channel", opt);

Returns​

TypeValueDescription
enum pubnub_resPNR_STARTEDStarted.
PNR_OKFinished with a success (can only happen in the sync interface).
otherFailed, Indicates the type of error.

V2 message structure​

Pubnub V2 message has lots of data and here's how we express them for the pubnub_get_v2().

The "string fields" are expressed as Pascal strings, that is, a pointer with string length, and don't include a NUL character. Also, these pointers are actually pointing into the full received subscribe response, so, their lifetime is tied to the message lifetime and any subsequent transaction on the same context will invalidate them.

If a (string) field is not present, it will empty, meaning its size (length) will be zero and pointer (start) should be NULL (it might not be NULL, it's best to rely on size).

Method(s)​

Declaration​
struct pubnub_v2_message {
char const* channel_group;
unsigned heartbeat;
}
Parameter​
MemberTypeDescription
ttstruct pubnub_char_mem_blokThe timetoken of the message - when it was published.
regionintRegion of the message - not interesting in most cases.
flagsintMessage flags (indicators).
channelstruct pubnub_char_mem_blokChannel ID that message was published to.
match_or_groupstruct pubnub_char_mem_blokSubscription match or the channel group.
payloadstruct pubnub_char_mem_blokThe message itself (its contents, payload).
metadatastruct pubnub_char_mem_blokThe message metadata, as published.
message_typeenum pubnub_message_typeThe type of the message (published, signal).

Get V2 message​

Parse and return the next V2 message, if any.

Do keep in mind that you can use pubnub_get() to get the full message array in JSON, but, then you'll have to parse it yourself, and pubnub_channel() and pubnub_channel_group() would not work. On the other hand, this function will fail if you use it on subscribe v1 response.

If there are no more messages, this will return a struct memset to zero. It's best to check if payload is empty, as there has to be a payload, while other fields/attributes are mostly optional.

Method(s)​

Declaration​
1struct pubnub_v2_message pubnub_get_v2(pubnub_t* pbp)
Parameter​
* required
ParameterDescription
pbp *
Type: pubnub_t*
The Pubnub context from which to get the next message.
Sample code​
1struct pubnub_v2_message msg;
2for (msg = pubnub_get_v2(pbp); msg.payload.size > 0; msg = pubnub_get_v2(pbp)) {
3 puts("Received message:");
4 printf(" Channel = '%.*s'\n", (int)msg.channel.size, msg.channel.ptr);
5 printf(" Timetoken = '%.*s'\n", (int)msg.tt.size, msg.tt.ptr);
6 printf(" Metadata = '%.*s'\n", (int)msg.metadata.size, msg.metadata.ptr);
7 printf(" Payload = '%.*s'\n", (int)msg.payload.size, msg.payload.ptr);
8}

Returns​

TypeValueDescription
struct pubnub_v2_messageThe V2 message structure describing the next V2 message in the subscribe response. If there is no next message (response is empty, or subscribe V1, or some other transaction), the payload of the message will be empty.

Unsubscribe (old)​

To unsubscribe, you need to cancel a subscribe transaction.

  • If you configured SDK to be thread-safe, you can cancel at any time, but, the cancelling may actually fail - i.e., your thread may wait for another thread to finish working with the context, and by the time your cancel request gets processed, the transaction may finish.

  • If you configured SDK to not be thread-safe, the only safe way to do it is to use the sync interface and:

    1. Set the context to use non-blocking I/O
    2. Wait for the outcome in a loop, checking for pubnub_last_result() - rather than calling pubnub_await()
    3. If a condition occurs that prompts you to unsubscribe, call pubnub_cancel()
    4. Wait for the cancellation to finish (here you can call pubnub_await(), unless you want to do other stuff while you wait)
Unsubscribing from all channels

Unsubscribing from all channels, and then subscribing to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received timetoken and thus, there could be some gaps in the subscription that may lead to message loss.

Method(s)​

To Unsubscribe from a channel you can use the following method(s) in the C-Core (legacy) SDK:

* required
ParameterDescription
p *
Type: pubnub_t*
Pointer to Pubnub Client Context.

Sample code​

Unsubscribe from a channel:

1pbresult = pubnub_subscribe(ctx, "my_channel", NULL);
2/* If we don't set non-blocking I/O, we can't get out of a blocked read */
3pubnub_set_non_blocking_io(ctx);
4/* Can't use pubnub_await() here, it will block */
5while (PNR_STARTED == pbresult) {
6 pbresult = pubnub_last_result(ctx);
7 /* Somehow decide we want to quit / unsubscribe */
8 if (should_stop()) {
9 pubnub_cancel(ctx);
10 /* If we don't have anything else to do, it's OK to await now,
11 but you could again have a loop "against" pubnub_last_result()
12 */
13 pbresult = pubnub_await(ctx);
14 break;
15 }
show all 19 lines

Rest response from server​

The output below demonstrates the response to a successful call:

1{
2 "action" : "leave"
3}

Other examples​

Unsubscribing from a channel group​
1pbresult = pubnub_subscribe(ctx, NULL, "my_channel_group");
2/* If we don't set non-blocking I/O, we can't get out of a blocked read */
3pubnub_set_non_blocking_io(ctx);
4/* Can't use pubnub_await() here, it will block */
5while (PNR_STARTED == pbresult) {
6 pbresult = pubnub_last_result(ctx);
7 /* Somehow decide we want to quit / unsubscribe */
8 if (should_stop()) {
9 pubnub_cancel(ctx);
10 /* If we don't have anything else to do, it's OK to await now,
11 * but you could again have a loop "against" pubnub_last_result()
12 */
13 pbresult = pubnub_await(ctx);
14 break;
15 }
show all 19 lines

Was this page useful?

Last updated on