Files
gobot/gobot-gui/webrtc_test/api/webrtc_fake.ts
2024-11-03 23:52:06 +01:00

146 lines
3.7 KiB
TypeScript

import { Router } from "jsr:@oak/oak@14";
// @deno-types="npm:@types/sdp-transform"
import sdpTransform from "npm:sdp-transform@2.14.2";
import { encodeHex,} from "https://deno.land/std@0.224.0/encoding/hex.ts";
import { parseIceCandidate, IceCandidate } from "./src/iceCandiate.ts";
const router = new Router({
prefix: "/api",
});
export {router as router_webrtc};
let rxAddress: Deno.Addr | undefined = undefined;
const ffmpegSocket = Deno.listenDatagram({
hostname: "localhost",
port: 1234,
transport: "udp"
});
let ffmpegRxRun = true;
// deno-lint-ignore no-async-promise-executor
const _ffmpegRxPromose = new Promise(async (resolve, _reject) => {
while(ffmpegRxRun) {
const data = new Uint8Array(65536);
await ffmpegSocket.receive(data);
if(rxAddress !== undefined) {
await ffmpegSocket.send(data, rxAddress);
}
}
resolve(null);
});
interface RTCIceCandidate {
candidate: string;
sdpMid: string;
sdpMLineIndex: number;
usernameFragment: string;
};
interface RTCSessionDescription {
sdp: string;
type: "offer" | "answer";
}
async function getSDP(): Promise<string> {
return await Deno.readTextFile("./output.sdp");
}
async function getFingerprint(): Promise<string> {
const cert = new Uint8Array(32);
crypto.getRandomValues(cert);
const hash = encodeHex(await crypto.subtle.digest("SHA-256", cert)).toUpperCase();
return hash.split(/(..)/g).filter((s: string) => s !== "").join(":");
}
async function modifySDP(sdp: string): Promise<string> {
//let sdpObj = sdpTransform.parse(sdp);
const localAddress = "127.0.0.1";
let sdpObj: sdpTransform.SessionDescription = {
fingerprint: {
"type": "SHA-256",
"hash": await getFingerprint()
},
icePwd : "AAAABBBB",
iceUfrag: "AAAABBBB",
origin: {
username: "-",
sessionId: (Math.random()*10000000).toFixed(0),
sessionVersion: 0,
netType: "IN",
ipVer: 4,
address: localAddress,
},
timing: {
start: 0,
stop: 0
},
media: [
{
type: "video",
port: 1235,
protocol: "RTP/AVP",
direction: "sendrecv",
connection: {
ip: localAddress,
version: 4,
},
payloads: "126",
fmtp: [
],
rtp: [
{
payload: 126,
codec: "H264",
rate: 90000
}
]
}
]
};
console.log(sdpObj);
return sdpTransform.write(sdpObj);
}
router.post("/webrtc", async (ctx) => {
const body: {
ice: RTCIceCandidate[];
offer: RTCSessionDescription
} = await ctx.request.body.json();
const ice: RTCIceCandidate[] = [];
const answer: RTCSessionDescription = {
sdp: await modifySDP(await getSDP()),
type: "answer"
};
console.log(body.offer);
const remoteIce = body.ice.map((candidate: RTCIceCandidate) => parseIceCandidate(candidate.candidate))
.filter((c: IceCandidate | null) => c !== null)
.filter((c: IceCandidate | null) => c?.transport === "UDP" && c?.candidateType === "host")
//console.log(remoteIce);
if (body) {
ctx.response.status = 200;
ctx.response.body = {
ice: ice,
answer: answer
};
} else {
ctx.response.status = 400;
ctx.response.body = { error: "Invalid JSON" };
}
});