#######
Library
#######

Overview
========

The :doc:`Stream Cache </prog_guide/viewing/data_model/stream_cache/overview>` Server library provides all the necessary functionality to build a custom Stream Cache Server application. This functionality encompasses the following features:

* Designating CAD model source directories to stream from.
* Determining if rendering should be allowed on the client, the server, or both.
* Controlling the logging output of the Stream Cache Server.
* Hosting a `WebSocket <https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API>`_ to communicate with the HOOPS Web Viewer.
* Streaming CAD model data to the HOOPS Web Viewer.

This functionality is also provided by the *ts3d_sc_server.exe* application that ships with |HCNOW|. This is our newer Stream Cache Server that works with our NodeJS based server system.

These applications may be sufficient for most streaming needs, but if custom behavior is required, then the Stream Cache Server library can be utilized as an alternative.


Building your application
=========================

To build an application with the Stream Cache Server library, you’ll need to include the header file (*sc_server.h*) and link the application against the dynamic library (*sc_server.dll*). Note that the library does depend on other dynamic libraries from within the same directory.

.. note::
  
  For more information on the location of these files in your |HCNOW| package, consult our :doc:`Package Description </overview/package-description>` page.


Using the library
=================

The typical steps for creating an application that uses the Stream Cache Server library are:

#. Create an instance of the configuration object ``SC::Server::StreamCacheServer::Config`` and set all configuration settings as needed for your environment.
#. Create an instance of ``SC::Server::StreamCacheServer``.
#. Call the ``SC::Server::StreamCacheServer.Init`` function of the Stream Cache Server object, passing it the Config object from step 2.
#. Loop until an exit condition has been determined. Each cycle of the loop should call the ``SC::Server::StreamCacheServer.Tick`` function on the Stream Cache Server object.
#. Exit the loop. Call the ``SC::Server::StreamCacheServer.Stop`` function on the Stream Cache Server object.  
#. Destroy the Stream Cache Server object 

Note that while the Stream Cache Server internally uses multiple threads, the Stream Cache Server class is not thread-safe, and therefore all steps as described above must be performed from the same thread.


Working example
===============

The following example shows a minimal but fully working version of a Stream Cache Server using the Stream Cache Server library. This example follows the steps outlined in the previous section.

The example sets the ``SC::Server::StreamCacheServer::Config.onDisconnect`` callback via the configuration settings to a lambda function that triggers the ``SC::Server::StreamCacheServer.Tick`` loop to exit. The function specified by ``SC::Server::StreamCacheServer::Config.onDisconnect`` will be called when the connected HOOPS Web Viewer is closed or encounters an inactivity timeout.

.. literalinclude:: /../../applications/converter/docs/test_stream_cache_server.cpp
	   :start-after: //! [sc_server_lib_ex_full_source]
	   :end-before: //! [sc_server_lib_ex_full_source]
		   

Configuration callbacks
=======================

The ``SC::Server::StreamCacheServer::Config`` includes members that hold callback functions for logging and other useful notifications. These members are optional and can be left unset. To utilize a callback, assign the configuration setting field to either a C++ lambda function or a std::function wrapper that matches the type signature of that function, as follows:

.. code-block:: cpp

  // Function signature used for the libwebsockets logging callback 

  using LwsLogCallback = std::function<void(int level, const char* message)>; 

  // Function signature used for Stream Cache logging callbacks  

  using MessageCallback = std::function<void(const std::string& message)>; 

  // Function signature used for Stream Cache data callbacks 

  using DataCallback = std::function<void(uint32_t rx, uint32_t tx)>; 

  // Function signature used for Stream Cache notification callbacks 

  using NotifyCallback = std::function<void()>;

This is an example that uses the ``SC::Server::StreamCacheServer::MessageCallback`` type with a C++ lambda to print any errors reported by the Stream Cache to stdout.

.. code-block:: cpp

	config.onError = [](const std::string& message) { 
	  std::cout << message << std::endl;  
	};

	
Configuration settings reference
================================

The following list details all configuration settings available in the ``SC::Server::StreamCacheServer::Config`` object. The server configuration is fixed upon calling the init() function, thus changing configuration values after initialization is not supported.

**port** - The networking port used for WebSocket communications with the HOOPS Web Viewer. This value must be in the range 1 <= port <= 32767. Default: 0

**enabledRenderingLocations** - Determines if the client and/or server rendering is allowed. It's valid to set either mode or both. The web-viewer will request the type of rendering when it first connects, and will only be successful if the matching type has been enabled with this setting. Default: RenderingLocationClient

**license** - A valid |HCNOW| license must be specified. Default: empty string

**memoryDevice** - An optional Stream Cache memory device which is used for sandboxing file I/O within application memory. See sc_store.h for the MemoryDevice type declarations. If this is set to a valid memory device, the paths defined by ``SC::Server::StreamCacheServer::Config.workspaceDir`` and ``SC::Server::StreamCacheServer::Config.modelSearchDirs`` must point to directories within this device. If it is nullptr, then those directories will be interpreted within the standard filesystem.Default: ``nullptr``

**workspaceDir** - An optional path to a directory that will be used for temporary storage. If this setting is the empty string, the current working directory will be used. Default: empty string

**modelSearchDirs** - A list of directory paths to be used when searching for a model file. This is a single string with each directory path concatenated and using a single semi-colon character to separate each path. Default: empty string

**modelFile** - An optional relative file path that, when set to a non-empty string, will override any model requested by the web-viewer client. This should be a model file name that exists within the specified SC::Server::StreamCacheServer::Config.modelSearchDirs setting. ie. "bnc". Default: empty string

**sessionToken** - An optional token that must be shared with the web-viewer client. The string is simply compared for equality against the session token provided by the client, thus there is no format specification. Default: empty string

**sslCertificateFile** - A file path to an SSL certificate, which is needed to support the 'wss' protocol. If this is the empty string, SSL is not used. Default: empty string

**sslPrivateKeyFile** - A file path to an SSL private key, which is needed to support the 'wss' protocol. If this is the empty string, SSL is not used. Default: empty string

**ssrGpuIndex** - Optional 0-based index for specifying which GPU to be used. If set to std::numeric_limits&lt;uint32_t&gt;::max(), then the server will use the default GPU.Default: std::numeric_limits::max()

**ssrEgl** - When this option is enabled, EGL will be used to create the GL context if performing ssr rendering.  Enabling this option removes the need for an X server to be running for hardware accelerated Server Side rendering.  This option is reccomended on headless server environments and is currently only supported on Linux.

**exitOnLoadFinish** - Indicates that the stream cache should exit after a model has been loaded and streamed to the HOOPS Web Viewer. Default: false

**tickTimeout** - Indicates the amount of time that the ``SC::Server::StreamCacheServer.Tick`` function will sleep for after performing a work cycle. The value here will set the internal default used by the tick() function when it is called with no arguments. This value can be overridden for any given tick() call by providing an explicit value to the timeout function parameter. A negative value will result in the tick() call not sleeping in any way after the work cycle. Default: 1 millisecond

**kickOnNewConnection** - When true, this indicates that this Stream Cache session should allow a new web-viewer connection to take priority over the existing connection. If this happens, the existing connection will be closed, and the new connection can proceed. When this is false, the existing connection will be unaffected and the new connection will be denied. Default: false

**verboseLogging** - If true, increased diagnostic messages will be sent to the onDebug callback. Default: false

**lwsLogLevel** - This will set the enabled log-levels for the internal libwebsocket library. It should be a bitwise-or of ``LwsLogCategory`` values. Default: ``LwsLogCategoryNone``

**onLwsMessage** - Optional function that will receive the libwebsocket log messages that were enabled by the lowLogLevel setting. Default: empty

**onError** - Optional function that will receive error-category log messages. Default: empty

**onWarning** - Optional function that will receive warning-category log messages. Default: empty

**onInfo** - Optional function that will receive info-category log messages. Default: empty

**onDebug** - Optional function that will receive debug-category log messages. Default: empty

**onTrace** - Optional function that will receive trace-category log messages. Default: empty

**onDisconnect** - Optional function that will be called when a client disconnects. The message indicates why the client disconnected. Conditions that can cause this include 1) the HOOPS Web Viewer browser window is closed or 2) the HOOPS Web Viewer encounters a timeout out due to inactivity. Default: empty

**onData** - Optional function that will be called periodically with incremental data transmit and receive statistics. Default: empty

**onInitialUse** - Optional function that will be called upon the initial HOOPS Web Viewer connection. Default: empty
