Appwebsocket client

The appwebsocket client is used to establish a websocket connection to an app with the appwebsocket authentication protocol.
You can enable automatic reconnecting with exponential backoff by setting the autoReconnect flag in the Connect call.

File information

Filecommon/interface/appwebsocket_client.h

Classes IAppWebsocketClient
UAppWebsocketClient

Examples AppWebsocketClient usage

Logging

To enable logging for IAppWebsocketClient, the flag LOG_APP_WEBSOCKET must be set in the managers diagnostic settings.
For further logging enable the LOG_WEBSOCKET_CLIENT flag, as the websocket client is used by the appwebsocket client.

Classes

IAppWebsocketClient

class IAppWebsocketClient {
public:
    static IAppWebsocketClient * Create(class IIoMux * const iomux,
                                        class UAppWebsocketClient * const user,
                                        class ISocketProvider * const tcpSocketProvider,
                                        class ISocketProvider * const tlsSocketProvider,
                                        class IDns * const dns,
                                        class IInstanceLog * const log);

    void Connect(const char * websocketUri, const char * password, const char * app, const char * domain, const char * sip, const char * guid, const char * dn, bool autoReconnect = false);
    void Connect(const char * websocketUri, const char * app, class IAppWebsocketAuthenticator * authenticator, bool autoReconnect = false);
    void MessageComplete();
    void MessageSend(class json_io & msg, char * buffer);
    void MessageSendText(const char * buffer);
    void Encrypt(const char * seed, const char * data, char * out, size_t outLen);
    void Decrypt(const char * seed, const char * data, char * out, size_t outLen);
    void Hash(const char * seed, const char * data, char * out, size_t outLen);
    void Close();
};

Public functions

IAppWebsocketClient::Create (static)
This function creates a new instance of IAppWebsocketClient.

Parameters

class IIoMux * const iomux A pointer to the IIoMux class.
class UAppWebsocketClient * const user A pointer to the UAppWebsocketClient class which will receive the callbacks.
class ISocketProvider * const tcpSocketProvider A pointer to the ISocketProvider class for TCP sockets.
class ISocketProvider * const tlsSocketProvider A pointer to the ISocketProvider class for TLS sockets.
class IDns * const dns A pointer to the IDns class. Can be a nullptr.
IInstanceLog * log An IInstanceLog pointer to the logging interface.
Connect with string parameters
This function connects to the given endpoint.

Parameters

const char *websocketUri The websocket URI, e.g. wss://mydomain.com/websocket/uri
const char *password
const char *app
const char *domain
const char *sip
const char *guid
const char *dn
bool autoReconnect Default false. If true, the client tries to reconnect with an exponential backoff to avoid request flooding. The minimum reconnection timeout is 1s and the maximum 60s. The timeout is just resetted to minimum timeout again after a successfull login.

Remarks autoReconnect

With autoReconnect enabled, you might get multiple AppWebsocketClientConnectComplete callbacks for every successfull connect. Instead of receiving a AppWebsocketClientClose, you'll get an AppWebsocketClientDisconnected callback, so that your application knows that the client is currently disconnected.
Connect with IAppWebsocketAuthenticator
This function connects to the given endpoint.

Parameters

const char *websocketUri The websocket URI, e.g. wss://mydomain.com/websocket/uri
const char *app
class IAppWebsocketAuthenticator * const authenticator A pointer to the IAppWebsocketAuthenticator class.
bool autoReconnect Default false. If true, the client tries to reconnect with an exponential backoff to avoid request flooding. The minimum reconnection timeout is 1s and the maximum 60s. The timeout is just resetted to minimum timeout again after a successfull login.

Remarks

See the remarks of the previous Connect overload too.
If you set autoReconnect, the reconnect mechanism just works as long as the authenticator object is valid. This object might be closed due to configuration changes or connection issues between the PBX and another App object.
In such a case you might get an AppWebsocketClientClosed callback even if you didn't call Close yourself.
MessageComplete
Call this function to receive the next message.
MessageSend
This function sends a JSON message.

Parameters

class json_io &msg A json_io class which contains the message JSON.
char *buffer A buffer which will be used to encode the message into. Must be big enough to avoid buffer overflows!
MessageSendText
This function sends a text message.

Parameters

const char *buffer The buffer which will be sent.
Encrypt
Can be used to encrypt a text send on the AppWebsocket connection, using the session key

Parameters

const char * seedseed Seed, which can be used so that the result of the encryption is different even if the data is the same.
const char * data Buffer containing the data to be encrypted as zero terminated string
char * out Buffer for the encrypted output as hex string.
size_t outLen Length of the buffer for the output. Must be 2 times the length of the data string.
Decrypt
Can be used to dencrypt a text send on the AppWebsocket connection, using the session key

Parameters

const char * seedseed Seed, which can be used so that the result of the encryption is different even if the data is the same.
const char * data Buffer containing the hex string of encryped data
char * out Buffer for the decrypted output
size_t outLen Length of the buffer for the output. Must be half the length of the data string.
Hash
Calculate a SHA256 hash using the session key

Parameters

const char * seedseed Seed, which can be used so that the result of the encryption is different even if the data is the same.
const char * data Buffer containing a zero terminated string over which the hash shall be calculated
char * out Buffer for the hash
size_t outLen Length of the buffer for the output. Must be 64 bytes, 2* HASH_SIZE_SHA256
Close
Closes the appwebsocket client connection. This also disables automatic reconnecting.

UAppWebsocketClient

class UAppWebsocketClient {
public:
    virtual void AppWebsocketClientConnectComplete(class IAppWebsocketClient * appWebsocketClient) = 0;
    virtual void AppWebsocketClientMessage(class IAppWebsocketClient * appWebsocketClient, class json_io & msg, word base, const char * mt, const char * src) = 0;
    virtual void AppWebsocketClientSendResult(class IAppWebsocketClient * appWebsocketClient) = 0;
    virtual void AppWebsocketClientClosed(class IAppWebsocketClient * appWebsocketClient) = 0;
    virtual void AppWebsocketClientDisconnected(class IAppWebsocketClient * appWebsocketClient) {};
};

Overview

This is the user for an IAppWebsocketClient. The parent class needs to implement the functions below.

Public functions

AppWebsocketClientConnectComplete
Will be called from the IAppWebsocketClient instance after a successfull connect.

Parameters

class IAppWebsocketClient * appWebsocketClientThe calling IAppWebsocketClient instance.
AppWebsocketClientMessage
Will be called from the IAppWebsocketClient instance when a new message is received.

Parameters

class IAppWebsocketClient * appWebsocketClientThe calling IAppWebsocketClient instance.
class json_io &msgThe json_io class which contains the message JSON.
word baseThe JSON base.
const char * mtThe message type string.
const char * srcThe message source string.
AppWebsocketClientSendResult
Will be called from the IAppWebsocketClient instance if a message has been sent.

Parameters

class IAppWebsocketClient * appWebsocketClientThe calling IAppWebsocketClient instance.
AppWebsocketClientClosed
Will be called from the IAppWebsocketClient instance if the connection has been closed.

Parameters

class IAppWebsocketClient * appWebsocketClientThe calling IAppWebsocketClient instance.
AppWebsocketClientDisconnected
Will be called from the IAppWebsocketClient instance if the connection has been closed and the autoReconnect flag has been set in the Connect call.
After this callback the IAppWebsocketClient instance itself tries to reconnect with an exponential backoff timeout.

Parameters

class IAppWebsocketClient * appWebsocketClientThe calling IAppWebsocketClient instance.

Code Example

class Test : public UAppWebsocketClient {
    class IAppWebsocketClient * awsClient;
    void AppWebsocketClientConnectComplete(class IAppWebsocketClient * appWebsocketClient) override;
    void AppWebsocketClientMessage(class IAppWebsocketClient * appWebsocketClient, class json_io & msg, word base, const char * mt, const char * src) override;
    void AppWebsocketClientSendResult(class IAppWebsocketClient * appWebsocketClient) override;
    void AppWebsocketClientClosed(class IAppWebsocketClient * appWebsocketClient) override;
    
public:
    Test(class IIoMux * const iomux,
          class ISocketProvider * const tcpSocketProvider,
          class ISocketProvider * const tlsSocketProvider,
          class IDns * const dns,
          class IInstanceLog * const log);
};
    
Test::Test(class IIoMux * const iomux,
          class ISocketProvider * const tcpSocketProvider,
          class ISocketProvider * const tlsSocketProvider,
          class IDns * const dns,
          class IInstanceLog * const log)
{
    this->awsClient = IAppWebsocketClient::Create(iomux, this, tcpSocketProvider, tlsSocketProvider, dns, log);
    this->awsClient->Connect("wss://mydomain.com/websocket/uri", "myapp", "mydomain.com", "sip", "...", "DN");
}

void Test::AppWebsocketClientConnectComplete(class IAppWebsocketClient * appWebsocketClient) 
{
    char buffer[1024];
    class json_io json(buffer);
    word base = json.add_object(JSON_ID_ROOT, nullptr);
    json.add_string(base, "mt", "SendHello");
    this->awsClient->MessageSend(json, buffer);
    this->awsClient->MessageComplete();
}

void Test::AppWebsocketClientMessage(class IAppWebsocketClient * appWebsocketClient, class json_io & msg, word base, const char * mt, const char * src) 
{
    debug->printf("Test::AppWebsocketClientMessage received mt:%s", mt);
    this->awsClient->Close();
}

void Test::AppWebsocketClientSendResult(class IAppWebsocketClient * appWebsocketClient) 
{
    debug->printf("Test::AppWebsocketClientSendResult message sent");
}

void Test::AppWebsocketClientClosed(class IAppWebsocketClient * appWebsocketClient) 
{
    debug->printf("Test::AppWebsocketClientClosed");
    delete this->awsClient;
    this->awsClient = nullptr;
    // do other cleanup, e.g. call TryClose()
}