
                 Spreed WebRTC Channeling API v1.4.0
            =================================================
                          (c)2015 struktur AG

The server provides a Websocket connection end point as channeling API to
share peer information for peer to peer connectivity.


Quick signaling overview

  1. Establish websocket connection to /ws path of the
     channeling server. Optionally, add a token as request paramete
     t to reclaim an existing session (Example /ws?t=my-secret-token).

  2. Server sends Self document after connection was established.

  3. Send Hello document to the server.

  -- Channeling API is now established --

  4. Wait for incoming Offer and Candidate documents

     4.a. Process incoming Offer and Candidate documents Sdp data by
          submitting it to the peer connection implementation.

     4.b. If received an Offer, send Answer document with your own peer
          connection Sdp data as payload.

     4.c. Send out Candidates if not already sent in the Offer Sdp data.

  5. To initiate a call, get your peer connection Sdp data and send it
     and Offer document with Sdp payload.

     5.a. Send Offer.

     5.b. Send Candidates if not already sent in the Offer Sdp data.

     5.c. Wait for Answer and Candidates. When received put the Sdp data
          into your peer connection implementation.

  6. To close a call, send a Bye document.


In general all documents are JSON documents.


Sending vs receiving document data encapsulation

  All documents sent to the channeling server need to be wrapped in their
  own type once more for security reasons.

    {
        "Type": "Whatever",
        "Whatever": { /* your document */ },
        "Iid": "request-identifier-unique-to-client"
    }

    So any document you sent, you have to specify a Type key pointing
    to the key where the real document is to be found. The Iid field is
    optional and is returned back with the response wrapper document to
    match requests with response data when supported by the type.

  Received documents are wrapped by a special Document which provides
  additional information.

    {
        "From": "4",
        "To": "5",
        "Data": {},
        "Iid": "request-identifier-unique-to-client",
        "A": "attestation-session-token"
    }

  The Data key contains the real Document.

  Keys:

    From : The sending side Id as known to the server (uint64). Use this Id
           as To, to reply to things.
    To   : The Id, the server send this Document to. Should be the same as
           your current Self Id.
    Data : Contains the payload.
    Iid  : Request identifier to match this response to the calling
           request. Only available when sent by the client and the requested
           type implementation does support it (optional).
    A    : Session attestation token. Only available for incoming data
           created by other sessions (optional).

Error returns

  Calls providing an Iid which fail will receive an Error document with the
  following format:

    {
        "Type": "Error",
        "Code": "value_identifying_error",
        "Message": "A description of the error condition"
    }

  The following predefined error codes may implicitly be returned by any call
  which returns an error document:

    unknown: An internal server error, the message may provide more information.
    bad_request: The structure or content of the client's request was invalid,
                 the message may contain specifics.

Special purpose documents for channling

  Self

    {
        "Type": "Self",
        "Id": "4",
        "Sid": "5157",
        "Userid": "",
        "Suserid": "",
        "Token": "some-very-long-string",
        "Version": "server-version-number",
        "ApiVersion": 1.4,
        "Turn": {
          "username": "turn-username",
          "password": "turn-password",
          "ttl": 3600
          "urls": {
            "turn:213.203.211.154:3478?transport=udp",
            "turn:213.203.211.154:3479?transport=tcp",
            "turns:213.203.211.154:443?transport=tcp"
          }
        },
        "Stun": [
          "stun:213.203.211.154:443"
        ]
    }

    Self document is used by the server, to tell the client its own Id.

    Keys:

        Type       : Self (string)
        Id         : Public Session id for this connection (string).
        Sid        : Secure (non public) id for this session (string).
        Userid     : User id if this session belongs to an authenticated user.
                     Else empty.
        Suserid    : Secure (non public) user id if session has an user id.
                     Else empty.
        Token      : Security token (string), to restablish connection with the
                     same session. Pass the value as URL query parameter t, to
                     the websocket URL.
        Version    : Server version number. Use this to detect server upgrades.
        ApiVersion : Server channeling API base version. Use this version to select
                     client side compatibility with the connected server.
        Turn       : Mapping (interface{}) to contain TURN server details, like
                     urls, password and username. See
                     http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
                     and TURN REST API section in
                     https://code.google.com/p/rfc5766-turn-server/wiki/turnserver
                     for details.
        Stun       : Array with STUN server URLs.

    You can also send an empty Self document to the server to make the server
    transmit a fresh Self document (eg. to refresh when ttl was reached). Please
    note that you need to refresh before the ttl was reached - so add a grace
    period like 10% to the refresh timeout.

  Hello

    {
        Type: "Hello",
        Hello: {
            "Version": "1.0.0",
            "Ua": "Test client 1.0",
            "Name": "",
            "Type": "",
            "Credentials": {...}
        }
    }

    Hello document is to be send by the client after connection was established.
    If an Iid is provided, a Welcome document will be returned if joining the
    room with the given Id succeeds. Otherwise an Error document with one of the
    error codes listed below will be returned. Note that any previous room will
    have been left regardless of whether the response is successful.

    Keys under Hello:

      Version     : Channel protocol version (string).
      Ua          : User agent description (string).
      Name        : Room name. The default Room has the empty string name ("") (string).
      Type        : Room type. Use empty string to let the server select the
                    default type.
      Id          : Same as 'Name' (kept for compatibility).
      Credentials : An optional RoomCredentials document containing room
                    authentication information. See the Room document for
                    information on how such credentials should be handled after
                    a Welcome is received for the requested room. Note that
                    providing credentials while joining an existing room which
                    does not require them is an error, such requests should be
                    retried without credentials. In contrast, joining a
                    non-existent room with credentials will create the room
                    using the given credentials. Note that an error with a code
                    of authorization_not_required or invalid_credentials shall
                    cause the client to discard any cached room credentials.

    Error codes:

      default_room_disabled      : Joining the room "" is not allowed by this
                                   server.
      authorization_required     : Joining the given room requires credentials.
      authorization_not_required : No credentials should be provided for this
                                   room.
      invalid_credentials        : The provided credentials are incorrect.
      room_join_requires_account : Server configuration requires an
                                   authenticated user account to join this room.

  Welcome

    {
        "Type": "Welcome",
        "Welcome": {
            "Room": {...},
            "Users": []
        }
    }

    Welcome is sent in reply to a successful Hello, and contains all data
    needed to set up the initial room connection.

    Keys under Welcome:

      Room  : Contains the current state of the room, see the description of
              the Room document for more details.
      Users : Contains the user list for the room, see the description of
              the Users document for more details.

  RoomCredentials

    {
        "PIN": "my-super-sekrit-code"
    }

    RoomCredentials contains room authentication information, and is used as a
    child document when joining or updating a room.

    Keys under RoomCredentials:

      PIN : A password string which may be used by clients to authenticate
            themselves. Note that acceptable characters for this field may be
            constrained by the server based upon its configuration.

  Leave

    {
        Type: "Leave",
        Leave: {...}
    }

    A Leave document is to be sent by the client if a previously room should be
    left. Note that no confirmation will be returned by the server.

    Keys under Leave:

      Currently none.

  Room

    {
        "Type": "room-type",
        "Name": "room-name-here"
        "Credentials": {...}
    }

    Clients may send a Room document in order to update all room properties
    to the values given in the document. The room name must be given and match
    the currently joined room. Successful updates will receive an updated Room
    document as a reply, or an Error document if the update fails.

    Addtionally, the Room document is included in responses to initial joins
    and broadcast when room properties are updated.

    Keys under Room:

      Type        : The room type. This field should only be send to alter
                    the room type. It will always contain the type of the room
                    when returned by the server.
      Name        : The human readable name of the room.
      Credentials : Optional authentication information for the room, see the
                    documentation of the RoomCredentials document for more
                    details. This field shall only be present when sending or
                    receiving an update which alters room authentication data.
                    It should only be inferred that authentication is not
                    required if joining a room succeeds without credentials and
                    no updates containing credentials has been received.
                    Authentication may be disabled by sending a Room document
                    containing a RoomCredentials document with only empty
                    fields. Clients shall discard any cached authentication
                    information upon receiving such an update.

    Error codes:

      not_in_room : Clients may only update rooms which they have joined.

Peer connection documents

  Offer

    {
        "Type": "Offer",
        "Offer": {
            "To": "5",
            "Type": "Offer",
            "Offer": {
                "sdp": "v=0\r\no=- 8411189997130069027 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox\r\nm=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:4gu7jur9CAGKfnEb\r\na=ice-pwd:0OrfIpPc9DIv8RXnY+c63AEE\r\na=ice-options:google-ice\r\na=fingerprint:sha-256 39:DB:AA:8E:0F:09:23:93:C3:D0:4A:4D:31:E3:4E:42:B6:6D:B3:19:8D:08:4B:3C:6E:D9:A4:CE:4D:12:E9:4A\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=mid:audio\r\na=rtcp-mux\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:Zq8e3w5J2hcobT3tDQa4FeypkNI3D5P8dBlbkX3k\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:107 CN/48000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\na=ssrc:1804041269 cname:VOdXM2lXvKaANDCI\r\na=ssrc:1804041269 msid:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Ooxa0\r\na=ssrc:1804041269 mslabel:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox\r\na=ssrc:1804041269 label:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Ooxa0\r\nm=video 1 RTP/SAVPF 100 116 117\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:4gu7jur9CAGKfnEb\r\na=ice-pwd:0OrfIpPc9DIv8RXnY+c63AEE\r\na=ice-options:google-ice\r\na=fingerprint:sha-256 39:DB:AA:8E:0F:09:23:93:C3:D0:4A:4D:31:E3:4E:42:B6:6D:B3:19:8D:08:4B:3C:6E:D9:A4:CE:4D:12:E9:4A\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=sendrecv\r\na=mid:video\r\na=rtcp-mux\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:Zq8e3w5J2hcobT3tDQa4FeypkNI3D5P8dBlbkX3k\r\na=rtpmap:100 VP8/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack \r\na=rtcp-fb:100 goog-remb \r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\na=ssrc:2344329267 cname:VOdXM2lXvKaANDCI\r\na=ssrc:2344329267 msid:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Ooxv0\r\na=ssrc:2344329267 mslabel:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox\r\na=ssrc:2344329267 label:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Ooxv0\r\n",
                "type": "offer"
            }
        }
    }

    Send an Sdp offer to establish a new peer connection.

    Keys und Offer:

      To       : Id to send Offer to (string).
      Type     : Offer (string)
      Offer    : Sdp data mapping (keys sdp, type,
                 _conference, _token, _id) (interface{}).

    When receiving an offer for a conference, the Offer Sdp data mapping contains
    the additional key _conference (string), containing the conference id.

    When receiving an offer for token based peer to peer communication like
    file sharing or screen sharing, the Offer Sdp data mapping contains
    the additional keys _token (string) and _id (string).

  Candidate

    {
        "Type": "Candidate",
        "Candidate": {
            "To": "5",
            "Type": "Candidate",
            "Candidate": {
                "type": "candidate",
                "sdpMLineIndex": 0,
                "sdpMid": "audio",
                "candidate": "a=candidate:3326824476 1 udp 2113937151 10.1.1.201 44687 typ host generation 0\r\n"
            }
        }
    }

    Add candidates to a peer connection.

    Keys under Candidate:

      To        : Id to send Candidate to (string). Should be the same as
                  where the Offer was sent or received from.
      Type      : Candidate (string)
      Candidate : Candidate data mapping (keys, type, sdpMLineIndex,
                  sdpMid, candidate) (interface{})

  Answer

    {
        "Type": "Answer",
        "Answer": {
            "To": "4",
            "Type": "Answer",
            "Answer": {
                "sdp": "v=0\r\no=- 7479727536449706653 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7\r\nm=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:0+u7n7SbYfRSHWMy\r\na=ice-pwd:FGH2sGhPde6h75i0Wplzppp4\r\na=fingerprint:sha-256 D9:AD:F3:33:3D:4E:34:FF:19:CE:29:80:67:F2:18:34:D3:78:44:92:ED:C6:B3:50:D7:D3:EC:25:0B:10:3F:99\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=mid:audio\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:107 CN/48000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\na=ssrc:4175414086 cname:2fDX0nTtSszSeGlx\r\na=ssrc:4175414086 msid:KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7 KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7a0\r\na=ssrc:4175414086 mslabel:KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7\r\na=ssrc:4175414086 label:KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7a0\r\nm=video 1 RTP/SAVPF 100 116 117\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:0+u7n7SbYfRSHWMy\r\na=ice-pwd:FGH2sGhPde6h75i0Wplzppp4\r\na=fingerprint:sha-256 D9:AD:F3:33:3D:4E:34:FF:19:CE:29:80:67:F2:18:34:D3:78:44:92:ED:C6:B3:50:D7:D3:EC:25:0B:10:3F:99\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=sendrecv\r\na=mid:video\r\na=rtcp-mux\r\na=rtpmap:100 VP8/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack \r\na=rtcp-fb:100 goog-remb \r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\na=ssrc:1783464334 cname:2fDX0nTtSszSeGlx\r\na=ssrc:1783464334 msid:KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7 KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7v0\r\na=ssrc:1783464334 mslabel:KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7\r\na=ssrc:1783464334 label:KglGoKOAKjSEL6mVTQ2vQvV1VKFbpPo3Z4a7v0\r\n",
                "type": "answer"
            }
        }
    }

    Sends own Sdp data as an answer to a received Offer.

    Keys under Answer:

        To       : Id to send the Answer to (string). Should be the same as
                   where the Offer was received from.
        Type     : Answer (string).
        Answer   : Sdp data mapping (keys sdp and type) (interface{}).

  Bye

    {
        "Type": "Bye",
        "Bye": {
            "To": "5",
            "Type": "Bye",
            "Bye": {}
        }
    }

    Send hangup information. You do not need to wait for reply to close
    connectivity.

    Keys under Bye:

        To      : Id to send the Bye to (string). Should be the same as
                  the Id where the current connection is established to.
        Type    : Bye (string).
        Bye     : Bye JSON mapping (interface{}).

    Bye known keys:

        Reason  : Reason for sending bye. (string).
                  Possible reasons:
                    busy          : Called user is busy.
                    reject        : Called user has rejected call.
                    pickuptimeout : Called user did not pick up.
                    abort         : Calling user did hang up while calling.

    If you do not want to give a reason just send Bye as empty JSON mapping.


Additional types for session listing and notifications

  Left

    {
        "Type": "Left",
        "Id": "5"
    }

  Joined

    {
        "Type": "Joined",
        "Id": "7",
        "Userid": "u7",
        "Ua": "Chrome 28",
        "Status": null,
        "Prio": 100
    }

    Note: The Userid field is only present if that session belongs to a known user.

  Status

    {

        "Type": "Status",
        "Status": {
            "displayName": "Some name",
            "buddyPicture": "data:image/jpeg;base64,/9j/4..."
        },
        "Rev": 1

    }

    'buddyPicture' can be in next formats:
    1. Base64 encoded string of an image.
      Example: data:image/jpeg;base64,/9j/4...
    2. url subpath to query REST API. Please refer to REST API for more information
      Example: img:8nG33oDk8Yv8fvK6IphL/6vjI2NLigcET/picture.jpg

    Note: buddyPicture content needs to be in the format of HTML data urls'.

    Rev is the status update sequence for this status update entry. It
    is a positive integer. Higher numbers are later status updates.

  When the current session has successfully joined a room (see Hello for more
  details), a Users request will return a Users document containing session
  details for the current room. An Error document will be returned if no room
  has been joined or session information cannot be retrieved.

  Users (Request uses empty data)

    {
        "Type": "Users"
    }

  Users (Response with data)

    {
        "Type": "Users",
        "Users": [
            {
                "Type": "Online",
                "Id": "1",
                "Ua": "Firefox 27",
                "Status": {...},
                "Prio": 100
            },
            {
                "Type": "Online",
                "Id": "3",
                "Userid": "u3",
                "Ua": "Chrome 28",
                "Status": {...},
                "Prio": 100
            },
            {
                "Type": "Online",
                "Id": "4",
                "Userid": "u4",
                "Ua": "Chrome 28",
                "Status": {...},
                "Prio": 100
            }
        ]
    }

    Note: The Userid field is only present, if that session belongs to a known user.

    Error codes:

      not_in_room: Clients must join a room before requesting users.

  Alive

    {
        "Type": "Alive",
        "Alive": 1389190912092
    }

    Send an Alive document to the channeling server if you want to check if
    the connection is functional. The channeling server will send back their
    exact same Alive document immediately. With that it can be easily tested
    if the connection is still functional. You should only use the Alive
    check if nothing else was received from the channeling server for a
    while.

    The Alive value is a timestamp integer in milliseconds (unix time).


User authorization and session authentication

  The channeling API supports an Authentication document to bind and existing
  session to a given user. The required information to do this cannot be
  received through the channeling API. It depends on the server configuration
  how the Nonce and Userid are generated/validated.

  Authentication

    {
        "Type": "Authentication",
        "Authentication": {
            "Userid": "53",
            "Nonce": "nonce-for-this-session-and-userid"
        }
    }

    The Authentication document binds a userid to the current session. The
    Nonce and Userid need to be validateable by the server. If Authentication
    was successful, a new Self document will be sent. Otherwise an Error
    document will be returned describing why authentication failed. Note that
    the Nonce value can be generated by using the REST API (sessions end point).

    There is no way to undo authentication for a session. For log out, close
    the session (disconnect) and forget the token.

    Error codes:

      already_authenticated: This session has already authenticated, follow
                             the reauthentication procedure above.
      invalid_session_token: The provided session token information is invalid,
                             the error message may contain more information.

Information retrieval

  Sessions (Request uses Id, Token and Type)

    {
        "Type": "Sessions",
        "Sessions": {
          "Type": "Token type",
          "Token": "Token data"
        }
    }

    Valid known token types are:
      contact:
        Token data retrieved when a contact request is accepted.
      session:
        Token data retrieved on incoming messages as A field (attestation
        token).

  If session information retrieval fails, an Error document with one of the
  listed codes will be returned.

  Sessions (Response with Id, Token and Type from request and
  populated Session list).

    {
        "Type": "Sessions",
        "Sessions": {
          "Type": "Type as in request",
          "Token": "Token as in request"
        },
        "Users": [
          {
            "Type": "Online",
            "Id": "1",
            "Ua": "Firefox 27",
            "Status": {...}
          },
          {
              "Type": "Online",
              "Id": "3",
              "Userid": "u3",
              "Ua": "Chrome 28",
              "Status": {...}
          }, ...
        ]
    }

  Error codes:

    contacts_not_enabled: Requests with subtype `contact` are not enabled.
    bad_attestation: The requested session attestation is invalid.
    no_such_session: The requested session could not be found.

Chat messages and status information

  The chat is used to transfer simple messages ore more complex structures
  using the Status sub key.

  Chat (Send without time)

    {
        "Type": "Chat",
        "Chat": {
            "Message": "Some chat message"
        }
    }

  Chat (Send without time and tell server not to loop send us our own mesasge)

    {
        "Type":"Chat",
        "Chat":{
          "Message":"hello",
          "NoEcho":true
        }
    }

    The NoEcho boolean key indicates that the client can display its own
    messages directly without the need to receive it from the server. This
    is the preferred client mode.

  Chat (Received with time)

    {
        "Type": "Chat",
        "Chat": {
            "Message": "Some chat message",
            "Time": "2006-01-02T15:04:05Z",
            "Status": null
        }
    }

  Chat typing state

    {
        "Message": "",
        "Time": "2013-11-20T16:31:34+01:00",
        "Status": {
            "Typing": "start"
        }
    }

    The typing state can either be "start" or "stop".

  Chat with file sharing information

    {
        "Message": "File",
        "Time": "2013-11-20T16:28:42+01:00",
        "Status": {
            "FileInfo": {
                "chunks": 450,
                "id": "file_null_MTM4NDk2MTA1M3xFd3dBRUxGZ0NYZUxqdWtBS2xPUUpYYURVblE9fDpVXfnE3KNz-Eq_I0zmi8mCX_OzP1mPSas6lC2BjhCI_1",
                "name": "audio.wav",
                "size": 26959472,
                "type": "audio/wav"
            }
        }
    }

    The id of the FileInfo struct is the token which can be used to create
    a token peer connection for file transfer. It is up to the UI if the
    message is shown or not. For file transfer information the message is
    always "File".

  Chat with geo location sharing

    {
        "Message": "Geolocation",
        "Time": "2014-07-10T10:30:03+02:00",
        "Status": {
            "Geolocation": {
                "accuracy": 25000
                "latitude": 48.743342
                "longitude": 9.320112,
                "altitude": 278.691223
                "altitudeAccuracy" 13.969156
            }
        }
    }

    The latitude and longitude attributes are geographic coordinates
    specified in decimal degrees. Altitude and altitudeAccuracy are
    specified in meters. All values are of type float64.


  Chat with contact request/confirm information

    Request to create a contact token with Id.

    {
        "Message": "Some message",
        "Time": "2013-11-20T16:28:42+01:00",
        "Status": {
            "ContactRequest": {
                "Id": "client-generated-id"
            }
        }
    }

    Reply with success (Sever generates and inserts token).

    {
        "Message": "Some response message",
        "Time": "2013-11-20T16:28:59+01:00",
        "Status": {
            "ContactRequest": {
                "Id": "request-id",
                "Success": true,
                "Token": "server-generated-token-on-success"
            }
        }
    }

    Or reject (no reply is also possible).

    {
        "Message": "Some response message",
        "Time": "2013-11-20T16:28:59+01:00",
        "Status": {
            "ContactRequest": {
                "Id": "request-id",
                "Success": false
            }
        }
    }


  Chat message deliver status extensions

    Send chat messages as normal, but add the "Mid" field which is a
    client generated unique id to identify this single message. All status
    messages for this message are sent back with this Mid. Whenever a Mid
    is present in the Chat document, the server will trigger Status messages
    automatically. Mid is completely optional. Only add it when the client
    can handle it. Whenever a Status message is sent which should not trigger
    another Status message, make sure to add the Mid below Status document
    and not directly below Chat.

    Generate the Mid from a secure random number generator to make it unique
    and sufficiently unguessable.

    Also make sure you have implemented the NoEcho client chat feature as
    specified above.

    Send message:

    {
      "Type":"Chat",
      "Chat":{
        "To":"MTM5MDEzMTEyMXxFd3dBRU1qeFJ1OW9jTllTdndjUjRnbzZ4dk09fFtAr3XSgyr9U9qo-xU-dOvcs5t-h2ANll7sqKKy-ov6",
        "Type":"Chat",
        "Chat":{
          "Mid":"346c7d6e2989dca262be2c0a6a29eba2",
          "Message":"test",
          "NoEcho":true
        }
      }
    }

    Receive sent status back (generated by channeling server). In peer to peer
    chat the client needs to trigger this itself.

    {
      "Type":"Chat",
      "Chat":{
        "Mid":"346c7d6e2989dca262be2c0a6a29eba2",
        "Status":{
          "State":"sent"
        }
      }
    }

    Receive delivered status from receiving client. The Mid in receiving client
    generated Status messages is below the Status key, to avoid another round
    of Status messages triggered by the Server. This message needs to be
    triggered by the client whenever a message whith an Mid was received.

    {
      "Type":"Chat",
      "Chat":{
        "Time":"2014-01-19T22:31:00+01:00",
        "Status":{
          "Mid":"346c7d6e2989dca262be2c0a6a29eba2",
          "State":"delivered"
        }
      }
    }

    Receive read status of messages by batch mode Mid list. This needs to be
    triggered by the client whenever a user has seen a particular message. As
    this usually becomes true for multiple Mid messages this is implemented as
    Mid list. Touch, mouse or text input qualify as indication of read status.

    {
      "Type":"Chat",
      "Chat":{
        "Time":"2014-01-19T22:29:05+01:00",
        "Status":{
          "SeenMids":[
            "346c7d6e2989dca262be2c0a6a29eba2"
          ]
        }
      }
    }


  Request an automatic callback, by sending a chat message with the AutoCall
  document in Status.

    {
        "Type": "Chat",
        "Chat": {
            "Message": "Call me back",
            "Status": {
              "AutoCall": {
                "Type": "conference",
                "Id": "my-conference-room"
            }
        }
    }

    For example this can be sent to sessions which have "autoCalls" set in session
    status. The peer will then try to establish a peer connection  to the caller which
    the client eeds to pick up automatically.


Data channel only messages

  Each of the peer connections also create a data channel with the label
  "default". The party sending the offer also creates this data channel.
  The default data channel can be used to send all of the above messages
  directly to the peer, bypassing the channeling server. Additionally some
  message documents are only sent/received via a such data channel and are
  never sent through the channeling server.

  Talking (data channel only)

    {
        "Type": "Talking",
        "Talking": true
    }

    The talking state sent by a given session as boolean value in "Talking"
    key (true, false).

  Screenshare (data channel only)

    {
        "Type": "Screenshare",
        "Id": "",
        "Screenshare": {
            "id": "screenshare_token"
        }
    }

    The Id field is the peer where this screen sharing token is valid. Essentially
    it defines the session which started screensharing. It will be empty string when
    received in peer to peer data channel mode.

    The id is the token to be used to establish a token peer connection
    to the session which sent the Screenshare document.


Conferences and how to use them

  There is a new data document "Conference" to share information about
  conference participants. It is to be sent to the server, containing an Id
  for this conference, and the session ids for the conference participants.

  Once a client recieves such a Conference document, it has to check state
  for all session ids in the Conference document Conference list like this:

    - If not in a call already -> ignore.
    - If in a call, and own Id is not in the Conference list -> ignore.
    - Loop through all Ids, string compare the Id with own Id, and if result
      is -1 (not 0 or 1), send Offer to this Id if not got a call with this
      Id already.

  Conference offers are the same as normal Offers, with one additional field
  "_conference" inside the Offer.Offer mapping for the Conference Id.

  Offer for a conference

    {
        "Type": "Offer",
        "Offer": {
            "To": "5",
            "Type": "Offer",
            "Offer": {
                "sdp": "v=0\r\no=- 8411189997130069027 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox\r\nm=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:4gu7jur9CAGKfnEb\r\na=ice-pwd:0OrfIpPc9DIv8RXnY+c63AEE\r\na=ice-options:google-ice\r\na=fingerprint:sha-256 39:DB:AA:8E:0F:09:23:93:C3:D0:4A:4D:31:E3:4E:42:B6:6D:B3:19:8D:08:4B:3C:6E:D9:A4:CE:4D:12:E9:4A\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=mid:audio\r\na=rtcp-mux\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:Zq8e3w5J2hcobT3tDQa4FeypkNI3D5P8dBlbkX3k\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:107 CN/48000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\na=ssrc:1804041269 cname:VOdXM2lXvKaANDCI\r\na=ssrc:1804041269 msid:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Ooxa0\r\na=ssrc:1804041269 mslabel:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox\r\na=ssrc:1804041269 label:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Ooxa0\r\nm=video 1 RTP/SAVPF 100 116 117\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:4gu7jur9CAGKfnEb\r\na=ice-pwd:0OrfIpPc9DIv8RXnY+c63AEE\r\na=ice-options:google-ice\r\na=fingerprint:sha-256 39:DB:AA:8E:0F:09:23:93:C3:D0:4A:4D:31:E3:4E:42:B6:6D:B3:19:8D:08:4B:3C:6E:D9:A4:CE:4D:12:E9:4A\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=sendrecv\r\na=mid:video\r\na=rtcp-mux\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:Zq8e3w5J2hcobT3tDQa4FeypkNI3D5P8dBlbkX3k\r\na=rtpmap:100 VP8/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack \r\na=rtcp-fb:100 goog-remb \r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\na=ssrc:2344329267 cname:VOdXM2lXvKaANDCI\r\na=ssrc:2344329267 msid:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Ooxv0\r\na=ssrc:2344329267 mslabel:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Oox\r\na=ssrc:2344329267 label:DbFDWhC7hZwBCS9z3npJJMoEXtzrMLcb5Ooxv0\r\n",
                "type": "offer",
                "_conference": "the-conference-id"
            }
        }
    }

    This sends an Offer to Id "5" for conference "the-conference-id".

    Whenever an offer is received for a Conference id, and the client
    already is in a call with matching conference id, all subsequent Offers
    for this Conference Id should be accepted automatically.

  Conference information

    {
        "Type": "Conference",
        "Id": "the-conference-id",
        "Conference": [
            "session-a-id",
            "session-b-id"
        ]
    }

    Use Conference documents, to create a conference / add new session to a
    conference.

    The Id is to be generated by the client and needs to be unique. It
    should ne the Id of the client creating the conference (as received from
    Self document) plus some random string, and both hashed together. Create
    it as secure and unpredictable as possible.

    The Conference list inside the Conference document, does contain ids
    (string) to be added to the conference. You should always send all Ids
    including those already in the conference and the ones to be added to
    the conference.


Additional token based peer connections

  In addition to the normal audio/video peer connections multiple other
  token trust peer connections can be estabished to any number of peers. A
  existing peer connection is not required. Offers for a token based peer
  connection can be always recevied.

  In general a token is shared through the channeling server or another
  peer connection first. Whoever has that exact token is trusted and can
  establish (== send an offer) to establish a peer connection for exactly
  this token to a peer which is expected also to know this token. The peer
  is then expected to answer the offer automatically and pass all the
  control of this token peer connection to the token registrant ui
  component (eg. for file sharing or screen sharing).

  In addition to each token which is present as key _token in the payload
  mapping there also needs to be an id as key _id, which identifies exactly
  this connection. The _id is required to match multiple connections
  between the same two peers.

  The additional keys _token and _id need to be added to all payload data
  keys for Offer, Answer and Candidate.

  Example token Offer

    {
        "Type": "Offer",
        "To": "MTM4NDk1OTg4MnxFd3dBRUc0MDlfejFQMmVuSEN5WTB6M2hYRXM9fPz4UWUMxtikvfg7jJLxzAyJMXdLRFj3f6EswNhIDsvz",
        "Offer": {
            "_id": 3,
            "_token": "file_null_MTM4NDk1OTg4MnxFd3dBRUc0MDlfejFQMmVuSEN5WTB6M2hYRXM9fPz4UWUMxtikvfg7jJLxzAyJMXdLRFj3f6EswNhIDsvz_0",
            "sdp": "v=0\r\no=- 8028668300862525469 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio data\r\na=msid-semantic: WMS\r\nm=audio 1 RTP/SAVPF 111 103 104 0 8 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:6/L663BhUnNLzCFQ\r\na=ice-pwd:339CPlTYmUJQqvlDsmubbhcE\r\na=ice-options:google-ice\r\na=fingerprint:sha-1 C4:5A:E3:B1:48:A9:EE:E1:1A:47:E8:E6:98:DC:0F:37:5C:C7:A4:12\r\na=setup:actpass\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=recvonly\r\na=rtcp-mux\r\na=crypto:0 AES_CM_128_HMAC_SHA1_32 inline:X+jVMuCkjfn2CeVTUUDBjlNhYa6p1kkNnbn0nQL/\r\na=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:a0kTFRRu0QtXlSzTc1zcMZzxMLNXTTouW0R/+URx\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\nm=application 1 DTLS/SCTP 5000\r\nc=IN IP4 0.0.0.0\r\na=ice-ufrag:6/L663BhUnNLzCFQ\r\na=ice-pwd:339CPlTYmUJQqvlDsmubbhcE\r\na=ice-options:google-ice\r\na=fingerprint:sha-1 C4:5A:E3:B1:48:A9:EE:E1:1A:47:E8:E6:98:DC:0F:37:5C:C7:A4:12\r\na=setup:actpass\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n",
            "type": "offer"
        }
    }

  Token peer connections als have a default data channel with label
  "default" which is used for feature wise communication like flow control
  in file sharing.


File sharing data channel protocol

  File sharing uses a token peer connection for transferring the data
  through the default data channel with label default.

  There are the following two supported message types which are received
  for file sharing on such a data channel:

    ArrayBuffer

      Payload data in the following format (version 0):
        1 byte UInt8  : Version.
        3 byte        : Reserved for future use.
        4 byte UInt32 : Chunk sequence number.
        4 byte UInt32 : Chunk Crc32 checksum.
        ... bytes     : Payload data.

    String

      JSON chunk request

        {
            "m": "r",
            "i": 0
        }

        m is the mode. Currently only "r" is known to request chunks.
        i is the chunk sequence number to request (integer).

        Whenever you want the peer to send a chunk, request it by sending a
        JSON chunk request over the data channel with the sequence which
        should be transmitted. The current web implementation requests chunks
        sequentially, and waiting for each chunk to be complete before
        sending the request for the next one.

      JSON bye request

        {
            "m": "bye"
        }

        This is used to clean up connections when the downloader is finished
        or has manually aborted downloading. The downloader sends this message
        to the connected peer which then may close the connection where this
        message was received.


End of Channeling API.

For latest version of Spreed WebRTC check
https://github.com/strukturag/spreed-webrtc

For questions, contact mailto:opensource@struktur.de.


(c)2014 struktur AG
