You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1032 lines
39 KiB
1032 lines
39 KiB
|
|
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. |
|
|
|
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
|
|
|