about summary refs log tree commit diff
path: root/assets/src/network/transfer/share_transfer.ts
blob: f641a56dfd03d43e08f5e1e1c74158208f2a47dd (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
import { get } from "svelte/store";
import dataStore from "../../stores/data";
import { onWithToken, send } from "../channel/connection";
import type { UnregisterFn } from "../channel/messages/event_handler";
import type {
    RequestIceCandidateMessage,
    ShareAcceptedMessage,
} from "../channel/messages/messages";
import {
    createTransfer,
    onIncomingIceCandidate,
    Transfer,
    unregisterIceOnComplete,
} from "./transfer";

export async function createOfferTransfer(
    request_token: string
): Promise<Transfer> {
    const transfer = createTransfer(onChannel);

    const offer = await transfer.pc.createOffer();
    transfer.pc.setLocalDescription(offer);

    transfer.pc.onicecandidate = event => {
        const candidate = event.candidate;
        if (event.candidate !== null) {
            send("ice_candidate", { candidate, token: request_token });
        }
    };

    send("accept_request", {
        token: request_token,
        sdp: offer.sdp,
        type: offer.type,
    });

    const unregister: UnregisterFn = onWithToken(
        "share_accepted",
        request_token,
        (message: ShareAcceptedMessage) =>
            onShareAccepted(transfer, message, unregister)
    );

    return transfer;
}

function onShareAccepted(
    transfer: Transfer,
    message: ShareAcceptedMessage,
    unregister: UnregisterFn
) {
    const token = message.token;

    const answerDescription = new RTCSessionDescription(message);
    transfer.pc.setRemoteDescription(answerDescription);

    const unregisterIce = onWithToken(
        "request_ice_candidate",
        token,
        (message: RequestIceCandidateMessage) =>
            onIncomingIceCandidate(transfer, message)
    );

    unregisterIceOnComplete(transfer, unregisterIce);

    unregister();
}

function onChannel(channel: RTCDataChannel, completeTransfer: () => void) {
    const data = get(dataStore).data;
    channel.send(data);
    // TODO: Add retransmission possibility in case of transfer failure?
    completeTransfer();
}