Skip to content

Instantly share code, notes, and snippets.

@Iftimie
Last active January 30, 2022 12:02
Show Gist options
  • Save Iftimie/8981086790636460947633bc1055774e to your computer and use it in GitHub Desktop.
Save Iftimie/8981086790636460947633bc1055774e to your computer and use it in GitHub Desktop.
WebRTC 2
export const CHAT_CHANNEL = "chat"
export function waitForAllICE(peerConnection) {
return waitForEvent((fulfill) => {
peerConnection.onicecandidate = (iceEvent) => {
if (iceEvent.candidate === null)
fulfill()
}
})
}
export function waitForEvent(user_function) {
return new Promise((fulfill, reject) => {
user_function(fulfill)
setTimeout(() => reject("Waited too long"), 60000)
})
}
export function addConnectionStateHandler(peerConnection) {
peerConnection.onconnectionstatechange = function () {
console.log(peerConnection.connectionState)
};
}
from django.urls import path
from . import views
from django.conf.urls import include
import django_eventstream
urlpatterns = [
path('offer', views.offer, name='offer'),
path('answer', views.answer, name='answer'),
path('clear', views.clear, name='clear'),
path('events/', include(django_eventstream.urls), {
'channels': ['testchannel']
}),
path('home/<user>', views.home, name='home'),
]
from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django_eventstream import send_event
from django.http.response import HttpResponse
import json
storage = {
"user1_chat_offer": '""',
"user2_chat_offer": '""'
}
@csrf_exempt
def offer(request):
if request.method == "POST":
request_body = json.loads(request.body)
received_offer = json.dumps(request_body['offer'])
user = request_body['user']
if "user1" == user:
storage["user1_chat_offer"] = received_offer
returned_offer = storage["user2_chat_offer"]
else:
storage["user2_chat_offer"] = received_offer
returned_offer = storage["user1_chat_offer"]
peer_offer_sdp = json.loads(returned_offer)
return JsonResponse({'offer': peer_offer_sdp})
@csrf_exempt
def answer(request):
if request.method == "POST":
request_body = json.loads(request.body)
send_event('testchannel', 'message', request_body['answer'])
return HttpResponse("ok")
@csrf_exempt
def clear(request):
if request.method == "POST":
storage["user1_chat_offer"] = '""'
storage["user2_chat_offer"] = '""'
return HttpResponse("ok")
def home(request, user):
return render(request, 'mainapp/index.html', {"user": user})
<html>
<head>
<title>WebRTC</title>
<script type="module" src="index.js"></script>
</head>
<body>
<h1>Check the console</h1>
</body>
</html>
import * as common from './common.js';
console.log("\n".repeat(10))
async function start() {
const [peerConnection, dataChannel] = initializeBeforeCreatingOffer()
await prepareOfferSDP(peerConnection)
const remoteOfferString = prompt("Peer offer (skip if caller peer)");
if (remoteOfferString) {
await beCallee(remoteOfferString, peerConnection)
} else {
await beCaller(peerConnection, dataChannel)
}
}
function initializeBeforeCreatingOffer() {
const peerConnection = new RTCPeerConnection()
common.addConnectionStateHandler(peerConnection)
const dataChannel = peerConnection.createDataChannel(common.CHAT_CHANNEL)
dataChannel.onmessage = function (e) {
console.log("Received message: ", e.data)
};
return [peerConnection, dataChannel]
}
async function prepareOfferSDP(peerConnection) {
const localOffer = await peerConnection.createOffer()
await peerConnection.setLocalDescription(localOffer)
await common.waitForAllICE(peerConnection)
const localOfferWithICECandidates = peerConnection.localDescription
console.log("localOfferWithICECandidates:")
console.log(JSON.stringify(localOfferWithICECandidates))
}
async function beCallee(remoteOfferString, peerConnection) {
await receiveOfferSDP(peerConnection, remoteOfferString)
await sendAnswerSDP(peerConnection)
const dataChannel = await waitForDataChannel(peerConnection)
console.log("Sending message, check the other tab")
dataChannel.send("World")
}
async function receiveOfferSDP(peerConnection, remoteOfferString) {
const remoteOffer = new RTCSessionDescription(JSON.parse(remoteOfferString))
await peerConnection.setRemoteDescription(remoteOffer)
}
async function sendAnswerSDP(peerConnection) {
const localAnswer = await peerConnection.createAnswer()
peerConnection.setLocalDescription(localAnswer)
await common.waitForAllICE(peerConnection)
const localAnswerWithICECandidates = peerConnection.localDescription
console.log("localAnswerWithICECandidates:")
console.log(JSON.stringify(localAnswerWithICECandidates))
}
function waitForDataChannel(peerConnection) {
return common.waitForEvent((fulfill) => {
peerConnection.ondatachannel = function (e) {
const dataChannel = e.channel
dataChannel.onmessage = function (e) {
console.log("Received message: ", e.data)
};
fulfill(dataChannel)
}
})
}
async function beCaller(peerConnection, dataChannel) {
await receiveAnswerSDP(peerConnection)
await sendMessage(dataChannel)
}
async function receiveAnswerSDP(peerConnection) {
console.log("Will wait for answer")
const remoteAnswerString = prompt("Peer answer");
const remoteAnswer = JSON.parse(remoteAnswerString)
peerConnection.setRemoteDescription(remoteAnswer)
}
async function sendMessage(dataChannel) {
await waitForDataChannelOpen(dataChannel)
console.log("Sending message. Check the other tab")
dataChannel.send("Hello")
}
function waitForDataChannelOpen(dataChannel) {
return common.waitForEvent((fulfill) => {
dataChannel.onopen = function() {
if (dataChannel.readyState == "open") {
fulfill()
}
};
})
}
start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment