WebRTC audio/video call and conferencing server.
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

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