# 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

File | common/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, const char * usr = NULL, const char * appObj = NULL);
        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.
  const char *user | Information can be used on the server to find the account
  const char *appObj | Information can be used on the server to find the account

  #### 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 * appWebsocketClient | The calling IAppWebsocketClient instance.

AppWebsocketClientMessage
  Will be called from the IAppWebsocketClient instance when a new message is received.

  #### Parameters

  class IAppWebsocketClient * appWebsocketClient | The calling IAppWebsocketClient instance.
  class json_io &msg | The json_io class which contains the message JSON.
  word base | The JSON base.
  const char * mt | The message type string.
  const char * src | The message source string.

AppWebsocketClientSendResult
  Will be called from the IAppWebsocketClient instance if a message has been sent.

  #### Parameters

  class IAppWebsocketClient * appWebsocketClient | The calling IAppWebsocketClient instance.

AppWebsocketClientClosed
  Will be called from the IAppWebsocketClient instance if the connection has been closed.

  #### Parameters

  class IAppWebsocketClient * appWebsocketClient | The 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 * appWebsocketClient | The 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()
    }