Added API documentation, updated doxygen configuration.

This commit is contained in:
Thulinma 2014-05-02 12:19:54 +02:00
parent b1eebe7aaf
commit 6ade063756
6 changed files with 439 additions and 2 deletions

View file

@ -672,7 +672,7 @@ FILE_VERSION_FILTER =
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE =
LAYOUT_FILE = DoxygenLayout.xml
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib

195
DoxygenLayout.xml Normal file
View file

@ -0,0 +1,195 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.7 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="Human-readable topics" intro="This is a list of topics that contain human-readable text. Well, yes, the entire documentation is of course human-readable, but these parts assume a little more humanity than the others." />
<tab type="modules" visible="yes" title="" intro=""/>
<tab type="namespaces" visible="no" title="">
<tab type="namespacelist" visible="no" title="" intro=""/>
<tab type="namespacemembers" visible="no" title="" intro=""/>
</tab>
<tab type="classes" visible="yes" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="examples" visible="no" title="" intro=""/>
<tab type="user" visible="yes" title="Source code" url="https://github.com/DDVTECH" />
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<classes visible="yes" title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<classes visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>

View file

@ -1,6 +1,31 @@
/// \page api API calls
/// The controller listens for commands through a JSON-based API. This page describes the API in full.
///
/// A default interface implementing this API as a single HTML page is included in the controller itself. This default interface will be send for invalid API requests, and is thus triggered by default when a browser attempts to access the API port directly.
/// The default API port is 4242 - but this can be changed through both the API and commandline parameters.
///
/// To send an API request, simply send a HTTP request to this port for any file, and include either a GET or POST parameter called `"command"`, containing a JSON object as payload. Nearly all members of the request object are optional, and described below.
/// A simple example request logging in to the system would look like this:
///
/// GET /api?command={"authorize":{"username":"test","password":"941d7b88b2312d4373aff526cf7b6114"}} HTTP/1.0
///
/// Or, when properly URL encoded:
///
/// GET /api?command=%7B%22authorize%22%3A%7B%22username%22%3A%22test%22%2C%22password%22%3A%22941d7b88b2312d4373aff526cf7b6114%22%7D%7D HTTP/1.0
///
/// The server is quite lenient about not URL encoding your strings, but it's a good idea to always do it, anyway.
/// See the `"authorize"` section below for more information about security and logging in.
///
/// As mentioned above, sending an invalid request will trigger a response containing the default interface. As you may not want to receive a big HTML page as response to an invalid request, requesting the file `"/api"` (as done in the example above) will force a JSON response, even when the request is invalid.
///
/// You may also include a `"callback"` or `"jsonp"` HTTP variable, to trigger JSONP compatibility mode. JSONP is useful for getting around the cross-domain scripting protection in most modern browsers. Developers creating non-JavaScript applications will most likely not want to use JSONP mode, though nothing is stopping you if you really want to.
///
/// \brief Listing of all controller API calls.
/// \file controller.cpp
/// Contains all code for the controller executable.
#include <stdio.h>
//#include <io.h>
#include <iostream>
@ -66,6 +91,45 @@ namespace Controller {
///\param Request The request to be parsed.
///\param Response The location to store the generated response.
///\param conn The user to be checked for authorization.
///
/// \api
/// To login, an `"authorize"` request must be sent. Since HTTP does not use persistent connections, you are required to re-sent authentication with every API request made. To prevent plaintext sending of the password, a random challenge string is sent first, and then the password is hashed together with this challenge string to create a one-time-use string to login with.
/// If the user is not authorized, this request is the only request the server will respond to until properly authorized.
/// `"authorize"` requests take the form of:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// //username to login as
/// "username": "test",
/// //hash of password to login with. Send empty value when no challenge for the hash is known yet.
/// //When the challenge is known, the value to be used here can be calculated as follows:
/// // MD5( MD5("secret") + challenge)
/// //Where "secret" is the plaintext password.
/// "password": ""
/// }
/// ~~~~~~~~~~~~~~~
/// and are responded to as:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// //current login status. Either "OK", "CHALL", "NOACC" or "ACC_MADE".
/// "status": "CHALL",
/// //Random value to be used in hashing the password.
/// "challenge": "abcdef1234567890"
/// }
/// ~~~~~~~~~~~~~~~
/// The challenge string is sent for all statuses, except `"NOACC"`, where it is left out.
/// A status of `"OK"` means you are currently logged in and have access to all other API requests.
/// A status of `"CHALL"` means you are not logged in, and a challenge has been provided to login with.
/// A status of `"NOACC"` means there are no valid accounts to login with. In this case - and ONLY in this case - it is possible to create a initial login through the API itself. To do so, send a request as follows:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// //username to create, as plain text
/// "new_username": "test",
/// //password to set, as plain text
/// "new_password": "secret"
/// }
/// ~~~~~~~~~~~~~~~
/// Please note that this is NOT secure. At all. Never use this mechanism over a public network!
/// A status of `"ACC_MADE"` indicates the account was created successfully and can now be used to login as normal.
void Authorize(JSON::Value & Request, JSON::Value & Response, ConnectedUser & conn){
time_t Time = time(0);
tm * TimeInfo = localtime( &Time);
@ -113,6 +177,47 @@ namespace Controller {
///\brief Check the submitted configuration and handle things accordingly.
///\param in The new configuration.
///\param out The location to store the resulting configuration.
///
/// \api
/// `"config"` requests take the form of:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// "controller": { //controller settings
/// "interface": null, //interface to listen on. Defaults to all interfaces.
/// "port": 4242, //port to listen on. Defaults to 4242.
/// "username": null //username to drop privileges to. Defaults to root.
/// },
/// "protocols": [ //enabled connectors / protocols
/// {
/// "connector": "HTTP" //Name of the connector to enable
/// //any required and/or optional settings may be given here as "name": "value" pairs inside this object.
/// },
/// //above structure repeated for all enabled connectors / protocols
/// ],
/// "serverid": "", //human-readable server identifier, optional.
/// }
/// ~~~~~~~~~~~~~~~
/// and are responded to as:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// "controller": { //controller settings
/// "interface": null, //interface to listen on. Defaults to all interfaces.
/// "port": 4242, //port to listen on. Defaults to 4242.
/// "username": null //username to drop privileges to. Defaults to root.
/// },
/// "protocols": [ //enabled connectors / protocols
/// {
/// "connector": "HTTP" //Name of the connector to enable
/// //any required and/or optional settings may be given here as "name": "value" pairs inside this object.
/// "online": 1 //boolean value indicating if the executable is running or not
/// },
/// //above structure repeated for all enabled connectors / protocols
/// ],
/// "serverid": "", //human-readable server identifier, as configured.
/// "time": 1398982430, //current unix time
/// "version": "2.0.2/8.0.1-23-gfeb9322/Generic_64" //currently running server version string
/// }
/// ~~~~~~~~~~~~~~~
void CheckConfig(JSON::Value & in, JSON::Value & out){
for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
if (jit->first == "version" || jit->first == "time"){
@ -536,6 +641,14 @@ int main(int argc, char ** argv){
Response["conversion"]["status"] = myConverter.getStatus();
}
}
///
/// \api
/// `"save"` requests are always empty:
/// ~~~~~~~~~~~~~~~{.js}
/// {}
/// ~~~~~~~~~~~~~~~
/// Sending this request will cause the controller to write out its currently active configuration to the configuration file it was loaded from (the default being `./config.json`).
///
if (Request.isMember("save")){
if( Controller::WriteFile(Controller::conf.getString("configFile"), Controller::Storage.toString())){
Controller::Log("CONF", "Config written to file on request through API");
@ -554,6 +667,21 @@ int main(int argc, char ** argv){
Response["config"]["serverid"] = "";
}
//sent any available logs and statistics
///
/// \api
/// `"log"` responses are always sent, and cannot be requested:
/// ~~~~~~~~~~~~~~~{.js}
/// [
/// [
/// 1398978357, //unix timestamp of this log message
/// "CONF", //shortcode indicating the type of log message
/// "Starting connector: {\"connector\":\"HTTP\"}" //string containing the log message itself
/// ],
/// //the above structure repeated for all logs
/// ]
/// ~~~~~~~~~~~~~~~
/// It's possible to clear the stored logs by sending an empty `"clearstatlogs"` request.
///
Response["log"] = Controller::Storage["log"];
//clear log and statistics if requested
if (Request.isMember("clearstatlogs")){

View file

@ -51,6 +51,74 @@ namespace Controller {
///\brief Checks the capabilities of the system.
///\param capa The location to store the capabilities.
///
/// \api
/// `"capabilities"` requests are always empty:
/// ~~~~~~~~~~~~~~~{.js}
/// {}
/// ~~~~~~~~~~~~~~~
/// and are responded to as:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// "connectors": { // a list of installed connectors
/// "FLV": { //name of the connector. This is based on the executable filename, with the "MistIn" / "MistConn" prefix stripped.
/// "codecs": [ //supported combinations of codecs.
/// [["H264","H263","VP6"],["AAC","MP3"]] //one such combination, listing simultaneously available channels and the codec options for those channels
/// ],
/// "deps": "HTTP", //dependencies on other connectors, if any.
/// "desc": "Enables HTTP protocol progressive streaming.", //human-friendly description of this connector
/// "methods": [ //list of supported request methods
/// {
/// "handler": "http", //what handler to use for this request method. The "http://" part of a URL, without the "://".
/// "priority": 5, // priority of this request method, higher is better.
/// "type": "flash/7" //type of request method - usually name of plugin followed by the minimal plugin version, or 'HTML5' for pluginless.
/// }
/// ],
/// "name": "HTTP_Progressive_FLV", //Full name of this connector.
/// "optional": { //optional parameters
/// "username": { //name of the parameter
/// "help": "Username to drop privileges to - default if unprovided means do not drop privileges", //human-readable help text
/// "name": "Username", //human-readable name of parameter
/// "option": "--username", //command-line option to use
/// "type": "str" //type of option - "str" or "num"
/// }
/// //above structure repeated for all (optional) parameters
/// },
/// //above structure repeated, as "required" for required parameters, if any.
/// "socket": "http_progressive_flv", //unix socket this connector listens on, if any
/// "url_match": "/$.flv", //URL pattern to match, if any. The $ substitutes the stream name and may not be the first or last character.
/// "url_prefix": "/progressive/$/", //URL prefix to match, if any. The $ substitutes the stream name and may not be the first or last character.
/// "url_rel": "/$.flv" //relative URL where to access a stream through this connector.
/// }
/// //... above structure repeated for all installed connectors.
/// },
/// "cpu": [ //a list of installed CPUs
/// {
/// "cores": 4, //amount of cores for this CPU
/// "mhz": 1645, //speed in MHz for this CPU
/// "model": "Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz", //model identifier, for humans
/// "threads": 8 //amount of simultaneously executing threads that are supported on this CPU
/// }
/// //above structure repeated for all installed CPUs
/// ],
/// "load": {
/// "fifteen": 72,
/// "five": 81,
/// "memory": 42,
/// "one": 124
/// },
/// "mem": {
/// "cached": 1989, //current memory usage of system caches, in MiB
/// "free": 2539, //free memory, in MiB
/// "swapfree": 0, //free swap space, in MiB
/// "swaptotal": 0, //total swap space, in MiB
/// "total": 7898, //total memory, in MiB
/// "used": 3370 //used memory, in MiB (excluding system caches, listed separately)
/// },
/// "speed": 6580, //total speed in MHz of all CPUs cores summed together
/// "threads": 8 //total count of all threads of all CPUs summed together
/// }
/// ~~~~~~~~~~~~~~~
void checkCapable(JSON::Value & capa){
//capa.null();
capa.removeMember("cpu");

View file

@ -91,7 +91,7 @@ bool Controller::hasViewers(std::string streamName){
/// This takes a "clients" request, and fills in the response data.
///
/// \api
/// `"client"` requests take the form of:
/// `"clients"` requests take the form of:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// //array of streamnames to accumulate. Empty means all.

View file

@ -305,6 +305,52 @@ namespace Controller {
///\brief Parse a given stream configuration.
///\param in The requested configuration.
///\param out The new configuration after parsing.
///
/// \api
/// `"streams"` requests take the form of:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// "streamname_here": { //name of the stream
/// "source": "/mnt/media/a.dtsc" //full path to a VoD file, or "push://" followed by the IP or hostname of the machine allowed to push live data. Empty means everyone is allowed to push live data.
/// "DVR": 30000 //optional. For live streams, indicates the requested minimum size of the available DVR buffer in milliseconds.
/// },
/// //the above structure repeated for all configured streams
/// }
/// ~~~~~~~~~~~~~~~
/// and are responded to as:
/// ~~~~~~~~~~~~~~~{.js}
/// {
/// "streamname_here": { //name of the configured stream
/// "error": "Available", //error state, if any. "Available" is a special value for VoD streams, indicating it has no current viewers (is not active), but is available for activation.
/// "h_meta": 1398113185, //unix time the stream header (if any) was last processed for metadata
/// "l_meta": 1398115447, //unix time the stream itself was last processed for metadata
/// "meta": { //available metadata for this stream, if any
/// "format": "dtsc", //detected media source format
/// "tracks": { //list of tracks in this stream
/// "audio_AAC_2ch_48000hz_2": {//human-readable track name
/// "bps": 16043,
/// "channels": 2,
/// "codec": "AAC",
/// "firstms": 0,
/// "init": "\u0011Vå\u0000",
/// "lastms": 596480,
/// "rate": 48000,
/// "size": 16,
/// "trackid": 2,
/// "type": "audio"
/// },
/// //the above structure repeated for all tracks
/// },
/// "vod": 1 //indicates VoD stream, or "live" to indicated live stream.
/// },
/// "name": "a", //the stream name, guaranteed to be equal to the object name.
/// "online": 2, //online state. 0 = error, 1 = active, 2 = inactive.
/// "source": "/home/thulinma/a.dtsc" //source for this stream, as configured.
/// },
/// //the above structure repeated for all configured streams
/// }
/// ~~~~~~~~~~~~~~~
/// Through this request, ALL streams must always be configured. To remove a stream, simply leave it out of the request. To add a stream, simply add it to the request. To edit a stream, simply edit it in the request. The LTS edition has additional requests that allow per-stream changing of the configuration.
void CheckStreams(JSON::Value & in, JSON::Value & out){
//check for new streams and updates
AddStreams(in, out);