Spreed Speak Freely Channeling API v1.2.0 ================================================= (c)2014 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 */ } } So any document you sent, you have to specify a Type key pointing to the key where the real document is to be found. Received documents are wrapped by a special Document which provides additional information. { "From": "4", "To": "5", "Data": {} } 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. Special purpose documents for channling Self { "Type": "Self", "Id": "4", "Token": "some-very-long-string", "Version": "server-version-number", "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 : Channel id for this connection (string) 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. 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", Id: "" } } Hello document is to be send by the client after connection was established. Keys under Hello: Version : Channel protocol version (string). Ua : User agent description (string). Id : Room id. The default Room has the empty string Id ("") (string). 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 (busy, reject). (string). 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", "Ua": "", "Status": null } Joined { "Type": "Joined", "Id": "7", "Ua": "Chrome 28", "Status": null } Status { "Type": "Status", "Status": { "displayName": "Some name", "buddyPicture": "data:image/jpeg;base64,/9j/4..." }, "Rev": 1 } 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 is in a room (means sent Hello), a Users request can be sent, to receive a list of sessions in that particular room. This always returns the sessions in the same room as the calling session. Users (Request uses empty data) { "Type": "Users", "Users": { "Type": "Users", "Users": {} } } Users (Response with data) { "Type": "Users", "Users": [ { "Type": "Online", "Id": "1", "Ua": "webrtc-publisher", "Status": null }, { "Type": "Online", "Id": "3", "Ua": "Chrome 28", "Status": null }, { "Type": "Online", "Id": "4", "Ua": "Chrome 28", "Status": null } ], "Index": 0, "Batch": 0 } 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). 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 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 being called from audio mixer { "Type": "Chat", "Chat": { "Message": null, "Status": { "type": "conference", "id": "my-conference-room" } } } This can be sent to any participant that has a "Status" containing the "isMixer" flag with a "true" value. The peer will then try to establish a peer connection to the caller which it needs to pick up to join an audio conference. 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 Speak Freely check https://github.com/strukturag/spreed-speakfreely For questions, contact mailto:opensource@struktur.de. (c)2014 struktur AG