Comms system
Most of the non-media IPC between MistServer processes is exchanged through the Comms system. It's based on RelAccX, and reading the documentation on that first is recommended before reading the rest of this document.
This system is designed to have a single controlling process that functions as (mainly) a reader for a data page, and multiple separate writing processes that "subscribe" to entries on the page as (mainly) a writer.
The controlling process generally makes use of the COMM_LOOP preprocessor directive defined in lib/comms.h to run a function on every entry (as well as clean up no longer used entries) periodically.
The controlling process creates (and later deletes) the associated page. The Comms::Comms base class does this in the destructor when the class is in "master" (controlling) mode. The various classes can be put in master mode manually through setMaster() but the various reload() functions also set the mode depending on how they are called, which means manual setting of the mode should in theory never be necessary.
Comms::Comms base class
The Comms::Comms base class implements all the basics that are required in all IPC of this kind within MistServer. Child classes based on it then extend the fields through overriding the virtual functions addFields() (which adds all fields to the RelAccX structure), nullFields() (which sets the field contents to default/empty) and fieldAccess() (which sets up a fast-access accessor for each field through Util::FieldAccX).
No code uses the base class directly, its only purpose is to be inherited by the more specialized classes (see below).
The base class only contains two fields, which are inherited by all other classes:
The status field
This field is used to exchange information about the current status of the entry. It contains a bitmask, with the following defined values:
COMM_STATUS_INVALID=0x0Entries set to zero are invalid and may be (re)used by new entries. This status is only set by the controlling process.COMM_STATUS_ACTIVE=0x1This flag is only set by the writing process. Entries with this flag are in active use ("claimed") and may not be (re)used by new entries (yet).COMM_STATUS_REQDISCONNECT=0x10This flag is only set by the controlling process. It indicates that the controlling process is requesting the writing process shut down.COMM_STATUS_DISCONNECT=0x20This flag is only set by the writing process. It indicates the writing process has finished writing data, and the entry may be read one last time and is then ready to be cleaned up by the controlling process. The controlling process will respond by null'ing the entire entry (settingCOMM_STATUS_INVALIDas the last step) after finishing the last read.COMM_STATUS_DONOTTRACK=0x40This flag is only set by the writing process. It indicates the entry should not keep count as "active use" in the current context. It's used to flag internal processes as non-viewers, for example, so the buffer will not stay active for non-viewers.COMM_STATUS_SOURCE=0x80This flag is only set by the writing process. It indicates the entry is a source in the current context. It helps the buffer identify the process pushing data into it and react accordingly when that process disconnects, for example.
The pid field
This field contains the PID of the writing process. It helps the controlling process detect unclean disconnects of writing processes because it can check if the PID listed is still running or not and clean up entries for processes that no longer exist on the system.
The Comms::Users class
The Comms::Users class extends Comms::Comms with fields needed by Output processes to make requests for data pages from Input processes. The controlling process for this is always a MistIn* binary, while the writing processes for this are MistOut* and/or MistProc* binaries.
The page name pattern for this class is MstUser{STREAMNAME} where {STREAMNAME} is the name of the stream the Input process is associated with.
It only adds two integer fields, one for track and one for keynum:
- track contrains the track index of the track that is being requested.
- keynum contains the key index in the metadata that is requested.
The writing process maintains an active entry on this page for every track it is interested in, so is generally connected more than once per viewer.
The controlling (MistIn*) process periodically reads out the entries and ensures that (if possible) the requested data point is (or continues to be) available in memory.
If the controlling process sets flag COMM_STATUS_REQDISCONNECT, the process on the other side will shut down as a result. Most MistIn* processes will do this during shut down, causing all connections that were using the stream to shut down in turn.
The Comms::Connections class
The Comms::Connections class extends Comms::Comms with fields needed by Outputs to report usage statistics back to MistController via MistSession. The controlling process is a MistSession binary while the writing processes for this are MistOut* and/or MistProc* binaries.
The page name pattern for this class is MstSession{SESSID} where {SESSSID} is the session ID of the session the connection belongs to.
It adds the following fields:
- now contains the seconds since system boot at time of last update of the data in this entry
- time contains how many seconds this entry has been active
- lastsecond contains the current playback position timestamp in seconds
- down contains the total bytes downloaded so far
- up contains the total bytes uploaded so far
- host contains the IPv4 or IPv6 address in raw binary form (16 bytes)
- stream contains the stream name as a null-terminated string
- connector contains the name of the connector used as a null-terminated string
- packetcount contains a counter of how many lossy packets have been transmitted (e.g. UDP packets)
- packetlostcount contains a counter of how many lossy packets were lost
- packetretransmitcount contains a counter of how may lossy packets were retransmitted
The writing process (MistOut* and/or MistProc*) maintains a single entry per active connection within the session, so for some protocols (like RTMP, RTSP, WebRTC) this is only one entry total for a session while for other protocols (like HLS, DASH) this might be potentially hundreds of entries.
The controlling (MistSession) process periodically reads out the entries and summarizes the statistics into per-session statistics, which it then reports to the controller through the Comms::Sessions class (see below).
If the controlling process sets flag COMM_STATUS_REQDISCONNECT, the process on the other side will shut down as a result. MistSession will do this during shut down, causing all connections that were part of the session to shut down in turn.
The Comms::Sessions class
The Comms::Sessions class extends Comms::Connections with fields needed by MistSession to report summarized usage statistics back to MistController. The controlling process is MistController and the writing processes are MistSession binaries.
The page name for this class is MstStat. (It is not a pattern but a hardcoded name, since only one MistController is ever active.)
It adds the following fields:
- sessid contains a null-terminated string with the session ID
- tags contains a null-terminated string of tags that apply to this session
The writing process (MistSession) maintains a single entry (one per session) as long as the session is active (has had any active connections in the last few seconds). If a field cannot be summarized because it's a string (connector, stream name, host) the field is set to an empty string if the values of the individual connections are non-identical. This means that if all connections have the same stream name, so will the stream name field in the session --- and the same goes for the connector and host --- but if any connection has a different entry, the corresponding field is blanked to indicate that it varies.
If the controlling process sets flag COMM_STATUS_REQDISCONNECT, the process on the other side will shut down as a result. MistController will do this when an API call is made to terminate a session, causing it and all related connections to be terminated accordingly.