Appservice

Interfaces to handle app services and app instances.
Basically each App has one class which is derived from the base class AppService. This base class establishes a unix domain socket connection to the manager app, which controlls the creation, starting and stopping of instances.
Each instance itself is derived from AppInstance and gets its own AppInstanceArgs.

File information

Filecommon/lib/appservice.h

Classes AppService
AppInstance
AppServiceApp
AppInstancePlugin
AppServiceSocket
UAppServiceSocket

Data types ServiceAlarmSeverity
ServiceAlarmType
AppServiceArgs
AppInstanceArgs

Examples Example

Logging

To enable logging for apps, the flag LOG_APP must be set in the managers diagnostic settings.

Classes

AppService

The service class of the App must be derived from the class AppService and implement the neccessary virtual functions.

class AppService : public UAppServiceSocket, public IInstanceLog {    
public:
    AppService(class IIoMux * const iomux, class ISocketProvider * const localSocketProvider, AppServiceArgs * serviceArgs);
    
    virtual class AppInstance * CreateInstance(AppInstanceArgs * args) = 0;
    virtual void AppServiceApps(istd::list * appList) = 0;
    virtual void AppInstancePlugins(istd::list * pluginList) {};

    void AppStart(AppInstanceArgs * args) override;
    void AppStopped(class AppInstance * instance);
    const char * GetAppServiceId() const;
    const char * GetAppPlatformDNSName() const;
    const char * GetAppPlatformTimeZoneString() const;
    void SetAllInstancesLogFlags(ulong64 logFlags);
};

Public functions

AppService
Constructor

Parameters

class IIoMux * const iomux An IIoMux pointer to the IIoMux class.
ISocketProvider * const localSocketProvider An ISocketProvider pointer to a local socket provider.
AppServiceArgs * serviceArgs An AppServiceArgs pointer to the service arguments struct.
CreateInstance
You must override this function inside your class which implements the AppService class.
This function creates an object of the instance class of the App which must be derived from the class AppInstance.
If this object is stopped and has finished stopping, it must call AppStopped, see below.

Parameters

AppInstanceArgs * args An AppInstanceArgs pointer to the instance arguments.

Return value

The created AppInstance object.
AppServiceApps
You must override this function inside your class which implements the AppService class.
Push your provided apps to the appList. Each app has to be an instance of class AppServiceApp. An app of an AppService might be configured inside the PBX App object.

Parameters

istd::list<AppServiceApp> * appList A list to add all AppServiceApps.
AppInstancePlugins
You can override this function inside your class which implements the AppService class if your app provides app instance plugins (PBX manager plugins).
Push your provided plugins to the pluginList. Each app has to be an instance of class AppInstancePlugin.
See publish manager plugins for further reference.

Parameters

istd::list<AppInstancePlugin> * pluginList A list to add all AppInstancePlugins.
AppStart
You can start an own app instance, e.g. inside your app-main.cpp, if you want to start an instance outside of the manager control.

Parameters

AppInstanceArgs * args An AppInstanceArgs pointer to the instance arguments.
AppStopped
Call this function when your app stopped.

Parameters

AppInstance * instance An AppInstance pointer to the instance object.
GetAppServiceId

Return value

The service id of the app service.
GetAppPlatformDNSName

Return value

The app platform DNS name which can be configured inside the manager settings.
GetAppPlatformTimeZoneString

Return value

The app platform timezone string which can be configured inside the manager settings.
SetAllInstancesLogFlags
Call this function if you want to set the logFlags of all instances to a certain value.

Parameters

ulong64 logFlags The logFlags to set.

AppInstance

The instance class of an App must be derived from AppInstance and implement the neccessary virtual functions.

class AppInstance : public IInstanceLog {    
public:
    AppInstance(class AppService * appService, AppInstanceArgs * args)
    const char * GetAppServiceId() const;
    const char * GetAppName() const;
    const char * GetAppDomain() const;
    const char * GetKey() const;
    void SetLogFlags(ulong64 logFlags);
    static char * GenerateKey(const char * appName, const char * appDomain);
    void LogV(const char * format, va_list ap);
    void Log(const char * format, ...);
    void HexDump(const void * buffer, size_t size);
    void SetAlarm(word code, ServiceAlarmSeverity severity, char * text, char * details);
    void ClearAlarm(word code, ServiceAlarmSeverity severity, char * text, char * details);
    void SendEvent(word code, ServiceAlarmSeverity severity, char * text, char * details);
    virtual void Stop() = 0;
    virtual void ServerCertificateUpdate(const byte * cert, size_t certLen) {};
    virtual void SetAppDomain(const char * domain, const char * pwd) {};
};

Public functions

AppInstance
Constructor

Parameters

AppService * service An AppService pointer to the app service class.
AppInstanceArgs * instanceArgs An AppInstanceArgs pointer to the instance arguments struct.
GetAppServiceId

Return value

The app service id.
GetAppName

Return value

The app name.
GetAppDomain

Return value

The app domain.
GetKey

Return value

The unique key string which identifies the app instance: "appname@appdomain".
SetLogFlags
Call this function to set the logFlags of the instance.

Parameters

ulong64 logFlags The logFlags to set.
GenerateKey (static function)
Generates the unique string which identifies an intance.

Parameters

const char * appName The app name.
const char * appDomain The app domain.

Return value

The unique key string which identifies the app instance: "appname@appdomain". Must be freed by the caller!
LogV
Writes the log string to the debug output (e.g. file or debugging output).

Parameters

const char * format The format string.
va_list ap A variable argument list with all arguments which are used inside the format string.
Log
Writes the log string to the debug output (e.g. file or debugging output).

Parameters

const char * format The format string.
...Further arguments used inside format string.
HexDump
Writes a hexdump of the buffer to the debug output (e.g. file or debugging output).

Parameters

const void * buffer The buffer.
size_t sizeThe size to dump.
SetAlarm
Sets an alarm, which is sent to the manager (which again sends it to an alarm and events server). An alarm is active until it is cleared.

Parameters

word code A code to identify an alarm.
ServiceAlarmSeverity severity The severity.
char * text The text which identifies the alarm.
char * details Further details for the alarm.
ClearAlarm
Clears an alarm.

Parameters

See SetAlarm for parameter reference.
SendEvent
Sends an event.

Parameters

See SetAlarm for parameter reference.
Stop
You must override this function. It is called if the instance or service is stopped by the manager.
You must call AppService::AppStopped asynchronously if everything has been stopped.
ServerCertificateUpdate
You can override this function if you need to be notified about the webserver certificate. You can then pass the certificate to an ISocketContext.

Parameters

const byte * cert The certificate byte buffer.
size_t certLen The length of the byte buffer.
SetAppDomain
Shouldn't be used inside app code.

AppServiceApp

The class AppServiceApp is used to describe an app which is provided by an AppService. Each app has a (for the service) unique name, which will be later used inside the URL which points to the app of the AppService.
class AppServiceApp {    
public:
    AppServiceApp(const char * name, bool websocketOnly = false);
    const char * GetName();
    bool IsWebsocketOnly();
};

Public functions

AppServiceApp
Constructor

Parameters

const char * name The name describes the last URL part of the app.
bool websocketOnly An app which can be just used with a websocket connection.
GetName

Return value

The name.
IsWebsocketOnly

Return value

The websocketOnly value.

AppInstancePlugin

The class AppInstancePlugin is used to describe an app instance plugin.
class AppInstancePlugin {    
public:
    AppInstancePlugin(const char * plugin, const char * icon, const char * langFile, bool wildcard = false, const char * api = NULL);
    
    bool wildcard;

    const char * GetIcon();
    const char * GetApi();
    const char * GetPlugin();
    const char * GetLangFile();
};

Public functions

See publish manager plugins for further reference.

AppServiceSocket

This class is just used internally inside the manager and webserver.

UAppServiceSocket

This class is just used internally inside the manager and webserver.

Data types

ServiceAlarmSeverity

typedef enum {
    ALARM_SEVERITY_INDETERMINATE,
    ALARM_SEVERITY_MAJOR,
    ALARM_SEVERITY_CRITICAL
} ServiceAlarmSeverity;

Overview

The enum ServiceAlarmSeverity is used to determine the severity of an alarm.

ServiceAlarmType

typedef enum {
    ALARM_TYPE_SET,
    ALARM_TYPE_CLEAR,
    ALARM_TYPE_ERROR
} ServiceAlarmType;

Overview

The enum ServiceAlarmType is used to determine the alarm type.

AppServiceArgs

struct AppServiceArgs {
    void Parse(int argc, char ** argv, bool keepDefaults = true);
    const char * serviceID;
    const char * manager;
    const char * appPlatformDNSName;
    ulong64 logFlags;
    bool segfaulted;
    bool disableHexdumps;
    off_t logFileSize;
};

Overview

The struct AppServiceArgs holds the relevant app service arguments. App service arguments are defined inside the manager.
The AppService class gets them through command line arguments which are usually parsed inside the app-main.cpp.

Parameters

const char * serviceID
const char * manager The unix domain socket file of the manager.
const char * appPlatformDNSName
ulong64 logFlags
bool segfaulted Indicates if the service previously segfaulted.
bool disableHexdumps This is set to true if hexdumps are disabled.
off_t logFileSize The maximum log file size.

AppInstanceArgs

struct AppInstanceArgs {
    AppInstanceArgs();
    void Parse(int argc, char ** argv, bool keepDefaults = true);
    const char * appName;
    const char * appDomain;
    const char * appPassword;
    const char * webserver;
    const char * webserverPath;
    const char * dbHost;
    const char * dbName;
    const char * dbUser;
    const char * dbPassword;
    const char * workingPath;
    ulong64 logFlags;
};

Overview

The struct AppInstanceArgs holds the relevant app instance arguments. App instance arguments are defined inside the manager.
The AppService class gets them through the socket connection and uses them to create a new AppInstance class.

Parameters

const char * appName
const char * appDomain
const char * appPassword
const char * webserver The unix domain socket file which is used to connect to the webserver.
const char * webserverPath The relative path which is used to access the application via HTTP.
const char * dbHost Usually an empty string, as the connection is done with unix domain sockets to the local database server.
const char * dbName
const char * dbUser
const char * dbPassword
const char * workingPath
ulong64 logFlags

Code Example

class TestInstance : public AppInstance {
    ISocketContext * socketContext;
    ISocket * socket;
    void Stop() override;
    void ServerCertificateUpdate(const byte * cert, size_t certLen)  override;
    void TryStop();
public:
    TestInstance(class IIoMux * const iomux, class TestService * testService, class ISocketProvider * localSocketProvider, class IDatabaseProvider * databaseProvider, class IWebserverPluginProvider * webserverPluginProvider, AppInstanceArgs * instanceArgs);
    ~TestInstance();
};

class TestService : public AppService {
    class IIoMux * const iomux;
    class ISocketProvider * localSocketProvider;
    class ISocketProvider * tlsSocketProvider;
    class IDatabaseProvider * databaseProvider;
    class IWebserverPluginProvider * webserverPluginProvider;
public:
    TestService(class IIoMux * const iomux, class ISocketProvider * localSocketProvider, class ISocketProvider * tlsSocketProvider, class IDatabaseProvider * databaseProvider, class IWebserverPluginProvider * webserverPluginProvider, AppServiceArgs * serviceArgs);
    ~TestService();
    class AppInstance * CreateInstance(AppInstanceArgs * instanceArgs) override;
    void AppServiceApps(class json_io & json, word base) override;
};

TestService::TestService(class IIoMux * const iomux, class ISocketProvider * localSocketProvider, class ISocketProvider * tlsSocketProvider, class IDatabaseProvider * databaseProvider, class IWebserverPluginProvider * webserverPluginProvider,  AppServiceArgs * serviceArgs)
    : AppService(iomux, localSocketProvider, serviceArgs),
    iomux(iomux)
{
    this->databaseProvider = databaseProvider;
    this->localSocketProvider = localSocketProvider;
    this->tlsSocketProvider = tlsSocketProvider;
    this->webserverPluginProvider = webserverPluginProvider;
}

TestService::~TestService()
{
}

class AppInstance * TestService::CreateInstance(AppInstanceArgs * instanceArgs)
{
    return new class TestInstance(iomux, this, localSocketProvider, tlsSocketProvider, databaseProvider, webserverPluginProvider, instanceArgs);
}

void TestService::AppServiceApps(istd::list<AppServiceApp> * appList)
{
    appList->push_back(new AppServiceApp("devices"));
    appList->push_back(new AppServiceApp("sysclients", true));
}

TestInstance::TestInstance(class IIoMux * const iomux, class TestService * testService, class ISocketProvider * localSocketProvider, class ISocketProvider * tlsSocketProvider, class IDatabaseProvider * databaseProvider, class IWebserverPluginProvider * webserverPluginProvider, AppInstanceArgs * instanceArgs) :
AppInstance(testService, instanceArgs)
{
    this->iomux = iomux;
    this->databaseProvider = databaseProvider;
    this->webserverPlugin = webserverPluginProvider->CreateWebserverPlugin(iomux, localSocketProvider, this);
    this->socketContext = tlsSocketProvider->CreateSocketContext(this);
    this->socket = tlsSocketProvider->CreateSocket(iomux, NULL, this, false, socketContext);
    webserverPlugin->RegisterForPath(instanceArgs->webserver, instanceArgs->webserverPath);
    this->Log("TestInstance created");
}
TestInstance::~TestInstance()
{
    this->Log("TestInstance deleted");
}
void TestInstance::ServerCertificateUpdate(const byte * cert, size_t certLen)
{
    this->socketContext->SetServerCertificate(cert, certLen, NULL);
}
void TestInstance::Stop()
{
    TryStop();
}
void TestInstance::TryStop()
{
    // if everything has been closed, call AppStopped
    appService->AppStopped(this);
}