-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Basic Example Web Application #16
Comments
@JacobZwang Sure! You will have to change To make the code more "clear", "actions" that come from peers (clients) are written in lower-case. And actions from/to the signaling server is in upper-case. Let me know if you run into any issues! I am happy to help :) export const WebRTCApp= (function() {
// Define "global" variables
var dataChannels = []
var peerConfig = {"iceServers":[{"urls":"stun:stun.l.google.com:19302"}]};
var sdpConstraints = { offerToReceiveAudio: false, offerToReceiveVideo: false };
var ws = null;
var client = generateUUID();
var room = "test_room"
var wsaddr = "127.0.0.1:3003"
// Functions
// Generate a random user-id
function generateUUID() {
// http://www.ietf.org/rfc/rfc4122.txt
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = "-";
return s.join("");
}
// Avoid responding to ourself, and only respond to messages in the same room
function shouldRespond(jsonMsg) {
return jsonMsg.from !== client && ((jsonMsg.endpoint === client) || (jsonMsg.room === room));
}
// Connect to the signaling server
async function connect() {
return new Promise((resolve, reject) => {
ws = new WebSocket("ws://" + wsaddr + "?user=" + client);
ws.onopen = (e) => {
console.log("Websocket opened");
sendNegotiation('HANDLE_CONNECTION', client)
}
ws.onclose = (e) => {
console.log("Websocket closed");
}
ws.onmessage = async (e) => {
var json = JSON.parse(e.data);
if (shouldRespond(json)) {
if(json.action === "HANDLE_CONNECTION"){
console.log("NEW PEER WANTS TO CONNECT")
await connectPeers(json.data)
resolve(WebRTCApp)
} else if (json.action === "offer"){
console.log("GOT OFFER FROM A NODE WE WANT TO CONNECT TO")
console.log("THE NODE IS", json.from)
await processOffer(json.from, json.data)
resolve(WebRTCApp)
}
}
}
ws.onerror = (e) => {
console.log("Websocket error");
reject(e);
}
})
}
function processMessage(e) {
console.log("----- DC MESSAGE PROCESS -----");
var message = JSON.parse(e.data);
// Here is where we process direct messages from other peers
}
// Used when establishing a connection
function processIce(localConnection, iceCandidate){
localConnection.addIceCandidate(new RTCIceCandidate(iceCandidate)).catch(e => {
console.log(e)
})
}
// Used when establishing a connection with a peer
function sendNegotiation(type, sdp){
var jsonSend = { protocol: "one-to-all", room: room, from: client, endpoint: "any", action: type, data: sdp};
ws.send(JSON.stringify(jsonSend));
}
// Send connection request to a specific endpoint-id
function sendOneToOneNegotiation(type, endpoint, sdp){
var jsonSend = { protocol: "one-to-one", room: room, from: client, endpoint: endpoint, action: type, data: sdp};
ws.send(JSON.stringify(jsonSend));
}
function connectPeers(requestee) {
return new Promise((resolve, reject) => {
console.log("CONNECTING PEERS")
// Create the local connection and its event listeners
let localConnection = new RTCPeerConnection(peerConfig);
let sendChannel = localConnection.createDataChannel("sendChannel");
localConnection.onicecandidate = event => {
if (event.candidate) {
sendOneToOneNegotiation("candidate", requestee, event.candidate)
}
}
function messageListener (e) {
var json = JSON.parse(e.data);
if(shouldRespond(json)){
if(json.action === "candidate"){
processIce(localConnection, json.data);
} else if(json.action === "answer"){
console.log("--- GOT ANSWER IN CONNECT ---")
localConnection.setRemoteDescription(new RTCSessionDescription(json.data));
}
}
}
ws.addEventListener('message', messageListener)
// Create the data channel and establish its event listeners
sendChannel.onopen = event => {
console.log("Channel opened");
resolve(WebRTCApp);
ws.removeEventListener('message', messageListener)
}
sendChannel.onmessage = message => {
processMessage(message)
}
sendChannel.onclose = event => {
console.log("Channel closed");
ws.removeEventListener('message', messageListener)
reject();
};
dataChannels.push(sendChannel)
// Now create an offer to connect; this starts the process
localConnection.createOffer(sdpConstraints)
.then(offer => {
localConnection.setLocalDescription(offer)
sendOneToOneNegotiation("offer", requestee, offer);
console.log("------ SEND OFFER ------");
})
.catch(handleCreateDescriptionError);
})
}
function processOffer(requestee, remoteOffer) {
console.log("RUNNING PROCESS OFFER")
return new Promise((resolve, reject) => {
let localConnection = new RTCPeerConnection(peerConfig);
localConnection.onicecandidate = event => {
if (event.candidate) {
sendOneToOneNegotiation("candidate", requestee, event.candidate)
}
}
localConnection.ondatachannel = event => {
event.channel.onopen = () => {
console.log('Data channel is open and ready to be used.');
dataChannels.push(event.channel)
resolve(WebRTCApp)
};
event.channel.onmessage = message => {
processMessage(message)
};
event.channel.onerror = error => {
// Handle channel errors here!
reject(WebRTCApp)
}
};
// SEND ANSWER
localConnection.setRemoteDescription(new RTCSessionDescription(remoteOffer))
localConnection.createAnswer().then(localDescription => {
localConnection.setLocalDescription(localDescription)
console.log("------ SEND ANSWER ------");
sendOneToOneNegotiation('answer', requestee, localDescription)
})
})
}
function handleCreateDescriptionError(error) {
console.log("Unable to create an offer: " + error.toString());
}
function sendDirect(message) {
let sentMessages = 0
dataChannels.forEach(function (datachannel) {
if (datachannel.readyState === 'open') {
datachannel.send(JSON.stringify({sender: client, payload: message}))
sentMessages++
}
});
console.log("Sent this many messages:", sentMessages)
}
return {
connect: (connect),
sendDirect: (sendDirect),
};
})(); |
Thanks so much! I'll try this out. |
So I half got it working. I'm not completely sure how this is supposed to bed run. I assumed it was ES6 and tried to use rollup which didn't work. So to make it partially work, I just deleted "export" from the beginning. Which allowed it to work enough to connect 2 peers to a room, however many errors were thrown. Maybe you can message me on discord? JacobZwang#5310 |
Could you provide a basic web application that demonstrates how to use this? Something minimal like sending a message or media stream would be great to learn how this works. Thanks for the help. (Beginner developer here)
The text was updated successfully, but these errors were encountered: