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