StreamLinkforC  7.0.3-308369
StreamLinkforC Documentation

Overview

StreamLink for C (SL4C) is a C API that allows a native application to exchange real-time financial data and trade messages with a Caplin Liberator server via the Web or other TCP/IP network.

SL4C provides the following capabilities:

  • Record subscriptions (including type 2 and type 3 data)
  • Container subscriptions
  • Permission subscriptions
  • Connection status notification
  • Reconnection
  • Publish data to record subjects
  • Creating and deleting objects on the Liberator
  • Throttling of individual subjects
  • Throttling of the entire session
  • Snapshot requests for supported subject types

Getting Started

It is recommended that you read the Caplin StreamLink Overview to gain an understanding of:

  • What StreamLink is, and how it can be used.
  • Fundamental StreamLink concepts and features.
  • How StreamLink can integrate with your own client application software to provide a streaming data display and support online trading of financial instruments.

Using StreamLink for C

Linking StreamLink for C into your application

StreamLink for C is distributed as a static library. Depending on the platform you are compiling for, there are a number of 3rd party libraries that it depends upon.

Linking StreamLink on Linux: -lstreamlink -levent -lssl -lcrypto -lpthread -lrt

Linking StreamLink on Windows: -lstreamlink -levent -lssl -lcrypto -lpthread -lrt

Linking StreamLink on macOS: -lstreamlink -framework Foundation -framework Security -framework CoreServices -framework CoreFoundation

OpenSSL is used to provide cryptographic facilities such as encrypted connection support.

LibEvent is used as an event loop library. StreamLink for C can be easily integrated with alternate event loop libraries, however at present the API method to allow this is not exposed.

Threading Model

By default, StreamLink for C spawns a single background thread for all communication with the Liberator. The background thread supplies sl_subscription handles to the StreamLink API (a blocking call), and executes callbacks to subscription listeners (sl_subscriptionlistener).

Because the background thread is responsible for executing subscription listener callbacks, you are advised to keep callback code as short and efficient as possible. Hogging the background thread's time in a callback can result in connection loss.

Memory Model

The memory model for StreamLink for C is as follows:

  • String parameters are owned by your code. SL4C will not deallocate them.
  • The ownership of sl_subscription_parameters objects are passed from user to library when they are passsed into sl_subscribe()
  • All objects passed on callbacks (bar any ctx pointers) are owned by the library

Creating a StreamLink instance and connecting to Liberator

You create a new StreamLink instance using the sl_new() function call. The parameters are overloaded, and allow complete configuration of the StreamLink library and connection strategies.

The following example creates a new StreamLink instance, registers a sl_connection_listener to listen for changes in connection status, and then connects to the Liberator.

#include <stdio.h>
#include <unistd.h>
#include "sl4c.h"
static void connection_status(streamlink *client, void *ctx, const char *server_uri, sl_connectionstatus status, intptr_t extra);
static void connection_source_status(streamlink *client, void *context, const char *server_uri, const char *sourcename, sl_sourcestatus status);
static void connection_service_status(streamlink *client, void *context, const char *server_uri, const char *servicename, sl_servicestatus status);
static sl_connectionlistener conn_listener = {
.status = connection_status,
.source_status = connection_source_status,
.service_status = connection_service_status
};
int main()
{
streamlink *sl = sl_new("http://localhost:8080", sl_create_password_credentialsprovider("admin", "admin"));
sl_add_connection_listener(sl, &conn_listener, NULL);
// Loop to prevent us exiting
while ( 1 )
sleep(1);
}
static void connection_status(streamlink *client, void *ctx, const char *server_uri, sl_connectionstatus status, intptr_t extra)
{
printf("Server <%s> Connection status is now %s (%d) %s\n",server_uri, sl_get_connectionstatusstring(status),status,
status == sl_CONN_CREDENTIALS_RETRIEVED ? (char*)extra : "");
}
static void connection_source_status(streamlink *client, void *context, const char *server_uri, const char *sourcename, sl_sourcestatus status)
{
char *statstr = "Unknown";
switch ( status ) {
case sl_SOURCE_AVAILABLE:
statstr = "Available";
break;
case sl_SOURCE_UNAVAILABLE:
statstr = "Unavailable";
break;
}
printf("DataSource <%s> is now %s\n", sourcename, statstr);
}
static void connection_service_status(streamlink *client, void *context, const char *server_uri, const char *servicename, sl_servicestatus status)
{
char *statstr = "Unknown";
switch ( status ) {
case sl_SERVICE_OK:
statstr = "Ok";
break;
case sl_SERVICE_LIMITED:
statstr = "Limited";
break;
case sl_SERVICE_DOWN:
statstr = "Down";
break;
}
printf("Data service <%s> is now %s\n", servicename, statstr);
}

The callbacks on the sl_connection_listener are for informational purposes; StreamLink for C manages the connection to the Liberator and does not require any intervention from your application.

Subscribing to data and receiving updates

To subscribe to data and receive updates to the data you need to:

  • implement (code) some protocols from the API User Layer,
  • call various methods from the API User Layer to connect to a Liberator and set up the subscription.

The following example demonstrates how to subscribe and receive updates for a record:

#include <stdio.h>
#include <unistd.h>
#include "sl4c.h"
static void connection_status(streamlink *client, void *ctx, const char *server_uri, sl_connectionstatus status, intptr_t extra);
static void record_updated(streamlink *client, void *ctx, const char *subject, sl_fieldlist *fields, char isimage);
static void subject_error(streamlink *client, void *ctx, const char *subject, sl_subjecterror error, sl_error_reason reason);
static void subject_status(streamlink *client, void *ctx, const char *subject, sl_subjectstatus status, sl_fieldlist *fields);
static sl_connectionlistener conn_listener = {
.status = connection_status
};
static sl_subjectlistener subject_listener = {
.record_updated = record_updated,
.status = subject_status,
.error = subject_error
};
int main()
{
streamlink *sl = sl_new("http://localhost:8080", sl_create_password_credentialsprovider("admin", "admin"));
sl_add_connection_listener(sl, &conn_listener, NULL);
sl_subscribe(sl, "/RECORD", NULL, &subject_listener, NULL);
// Loop to prevent us exiting
while ( 1 )
sleep(1);
}
static void connection_status(streamlink *client, void *ctx, const char *server_uri, sl_connectionstatus status, intptr_t extra)
{
printf("Server <%s> Connection status is now %s (%d) %s\n",server_uri, sl_get_connectionstatusstring(status),status,
status == sl_CONN_CREDENTIALS_RETRIEVED ? (char*)extra : "");
}
static void record_updated(streamlink *client, void *ctx, const char *subject, sl_fieldlist *fields, char isimage)
{
for ( int i = 0; i < fields->num; i++ ) {
printf("RecordUpdated: <%s> - %s = %s\n",subject, fields->fields[i].name, fields->fields[i].value);
}
}
static void subject_status(streamlink *client, void *ctx, const char *subject, sl_subjectstatus status, sl_fieldlist *fields)
{
char *text = "Unknown";
switch ( status ) {
text = "Ok";
break;
text = "Limited";
break;
text = "Stale";
break;
default:
break;
}
printf("SubjectStatus: Received status of <%s> (%d) for <%s>\n",text,status,subject);
}
static void subject_error(streamlink *client, void *ctx, const char *subject, sl_subjecterror error, sl_error_reason reason)
{
const char *text = sl_get_subjecterrorstring(error);
const char *reason_txt = sl_get_errorreasonstring(reason);
printf("SubjectError: Received error <%s> (%d) <%s> (%d) for <%s>\n",text,error,reason_txt,reason, subject);
}

Note that the listeners are "sparse" - an implementation for every callback is not required.

Handling responses

The API operates asynchronously. This means that when the client application code issues a subscription request or a command to SL4C, the response is not returned immediately through the method used to issue the request or command. Instead, you must set up a listener object (sl_subscriptionlistener) containing one or more callback methods. You then supply this listener to SL4C. SL4C calls the appropriate callback method(s) on the listener object to communicate data and command responses back to the client code.


Generated on Tue Oct 16 2018 12:25:43 for StreamLinkforC