aboutsummaryrefslogtreecommitdiff
path: root/source/client/index.ts
blob: 3841c8a3dc2df6a5ca4587a4debb77ac3e214412 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
export const servers = {
    iceServers: [
        {
            urls: ["stun:stun1.l.google.com:19302", "stun:stun2.l.google.com:19302"]
        }
    ],
    iceCandidatePoolSize: 10,
}

let remote_stream: MediaStream, local_stream: MediaStream;
let pc: RTCPeerConnection;

window.onload = async () => {

    if (window.location.search.startsWith("?offer=")) {
        await setup_webrtc()
        await offer(window.location.search.substr("?offer=".length))
    } else if (window.location.search.startsWith("?answer=")) {
        await setup_webrtc()
        await answer(window.location.search.substr("?answer=".length))
    } else {

    }

}

async function setup_webrtc() {
    document.body.innerHTML = ""

    pc = new RTCPeerConnection(servers)

    local_stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
    remote_stream = new MediaStream()

    local_stream.getTracks().forEach(t => pc.addTrack(t, local_stream))

    pc.ontrack = ev => {
        console.log("peer got remote tracks", ev.streams);
        ev.streams[0].getTracks().forEach(t => remote_stream.addTrack(t))
    }


    const ls_el = document.createElement("video")
    const rs_el = document.createElement("video")
    ls_el.muted = true
    ls_el.autoplay = rs_el.autoplay = true
    ls_el.setAttribute("playsinline", "1")
    rs_el.setAttribute("playsinline", "1")
    ls_el.srcObject = local_stream
    rs_el.srcObject = remote_stream

    document.body.append(ls_el, rs_el)

}

interface Offer {
    sdp: any,
    type: any
}

async function offer(id: string) {
    const ws = new WebSocket(`ws://${window.location.host}/offer/${id}`)
    ws.onclose = ev => console.log("websocket closed: " + ev.reason);
    await new Promise<void>(r => ws.onopen = () => r())

    console.log("websocket opened")

    pc.onicecandidate = ev => {
        const candidate = ev.candidate?.toJSON()
        if (!candidate) return
        ws.send(JSON.stringify({ candidate }))
        console.log("sent ice candidate", ev.candidate);
    }

    const offer_description = await pc.createOffer()
    await pc.setLocalDescription(offer_description);

    const offer: Offer = { sdp: offer_description.sdp, type: offer_description.type };

    ws.send(JSON.stringify({ offer }))

    ws.onmessage = ev => {
        const s = JSON.parse(ev.data)
        if (s.answer) {
            console.log("got answer", s.answer);
            const answer_description = new RTCSessionDescription(s.answer)
            pc.setRemoteDescription(answer_description)
        }
        if (s.candidate) {
            console.log("got candidate", s.candidate);
            const candidate = new RTCIceCandidate(s.candidate)
            pc.addIceCandidate(candidate)
        }
    }

}

async function answer(id: string) {
    const ws = new WebSocket(`ws://${window.location.host}/answer/${id}`)
    ws.onclose = ev => console.log("websocket closed: " + ev.reason);
    await new Promise<void>(r => ws.onopen = () => r())
    console.log("websocket opened");


    pc.onicecandidate = ev => {
        const candidate = ev.candidate?.toJSON()
        if (!candidate) return
        ws.send(JSON.stringify({ candidate }))
        console.log("sent ice candidate", candidate);
    }

    ws.onmessage = async ev => {
        const s = JSON.parse(ev.data)
        if (s.offer) {
            console.log("got offer", s.offer);
            await pc.setRemoteDescription(new RTCSessionDescription(s.offer))

            const answer_description = await pc.createAnswer()
            await pc.setLocalDescription(answer_description)

            const answer: Offer = { type: answer_description.type, sdp: answer_description.sdp }
            ws.send(JSON.stringify({ answer }))
        }
        if (s.candidate) {
            console.log("got candidate", s.candidate);
            pc.addIceCandidate(new RTCIceCandidate(s.candidate))
        }
    }
}