This commit is contained in:
Manav Rathi
2024-11-26 09:12:27 +05:30
parent 72fb7e7307
commit 8cd0e6186f
3 changed files with 45 additions and 30 deletions

View File

@@ -9,8 +9,8 @@ import { getCastData, register } from "services/pair";
import { advertiseOnChromecast } from "../services/chromecast-receiver";
export default function Index() {
const [publicKeyB64, setPublicKeyB64] = useState<string | undefined>();
const [privateKeyB64, setPrivateKeyB64] = useState<string | undefined>();
const [publicKey, setPublicKey] = useState<string | undefined>();
const [privateKey, setPrivateKey] = useState<string | undefined>();
const [pairingCode, setPairingCode] = useState<string | undefined>();
const router = useRouter();
@@ -18,8 +18,8 @@ export default function Index() {
useEffect(() => {
if (!pairingCode) {
void register().then((r) => {
setPublicKeyB64(r.publicKeyB64);
setPrivateKeyB64(r.privateKeyB64);
setPublicKey(r.publicKey);
setPrivateKey(r.privateKey);
setPairingCode(r.pairingCode);
});
} else {
@@ -31,14 +31,17 @@ export default function Index() {
}, [pairingCode]);
useEffect(() => {
if (!publicKeyB64 || !privateKeyB64 || !pairingCode) return;
if (!publicKey || !privateKey || !pairingCode) return;
const pollTick = async () => {
const registration = { publicKeyB64, privateKeyB64, pairingCode };
try {
// TODO:
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const data = await getCastData(registration);
const data = await getCastData({
publicKey,
privateKey,
pairingCode,
});
if (!data) {
// No one has connected yet.
return;
@@ -58,7 +61,7 @@ export default function Index() {
const interval = setInterval(pollTick, 2000);
return () => clearInterval(interval);
}, [publicKeyB64, privateKeyB64, pairingCode, router]);
}, [publicKey, privateKey, pairingCode, router]);
return (
<Container>

View File

@@ -4,16 +4,21 @@ import log from "@/base/log";
import { apiURL } from "@/base/origins";
import { wait } from "@/utils/promise";
import { nullToUndefined } from "@/utils/transform";
import castGateway from "@ente/shared/network/cast";
import { z } from "zod";
export interface Registration {
/** A pairing code shown on the screen. A client can use this to connect. */
pairingCode: string;
/** The public part of the keypair we registered with the server. */
publicKeyB64: string;
/** The private part of the keypair we registered with the server. */
privateKeyB64: string;
/**
* A base64 string representation of the public part of the keypair we
* registered with the server.
*/
publicKey: string;
/**
* A base64 string representation of the private part of the keypair we
* registered with the server.
*/
privateKey: string;
}
/**
@@ -78,14 +83,13 @@ export interface Registration {
*/
export const register = async (): Promise<Registration> => {
// Generate keypair.
const { publicKey: publicKeyB64, privateKey: privateKeyB64 } =
await generateKeyPair();
const { publicKey, privateKey } = await generateKeyPair();
// Register keypair with museum to get a pairing code.
let pairingCode: string | undefined;
while (true) {
try {
pairingCode = await castGateway.registerDevice(publicKeyB64);
pairingCode = await registerDevice(publicKey);
} catch (e) {
log.error("Failed to register public key with server", e);
}
@@ -94,7 +98,25 @@ export const register = async (): Promise<Registration> => {
await wait(10000);
}
return { pairingCode, publicKeyB64, privateKeyB64 };
return { pairingCode, publicKey, privateKey };
};
/**
* Register the given {@link publicKey} with remote.
*
* @returns A device code that can be used to pair with us.
*/
const registerDevice = async (publicKey: string) => {
const res = await fetch(await apiURL("/cast/device-info/"), {
method: "POST",
headers: clientPackageHeader(),
body: JSON.stringify({
publicKey,
}),
});
ensureOk(res);
return z.object({ deviceCode: z.string() }).parse(await res.json())
.deviceCode;
};
/**
@@ -107,7 +129,7 @@ export const register = async (): Promise<Registration> => {
* See: [Note: Pairing protocol].
*/
export const getCastData = async (registration: Registration) => {
const { pairingCode, publicKeyB64, privateKeyB64 } = registration;
const { pairingCode, publicKey, privateKey } = registration;
// The client will send us the encrypted payload using our public key that
// we registered with museum.
@@ -119,8 +141,8 @@ export const getCastData = async (registration: Registration) => {
// slideshow for some collection.
const decryptedCastData = await boxSealOpen(
encryptedCastData,
publicKeyB64,
privateKeyB64,
publicKey,
privateKey,
);
// TODO:

View File

@@ -56,16 +56,6 @@ class CastGateway {
return resp.data.publicKey;
}
public async registerDevice(publicKey: string): Promise<string> {
const resp = await HTTPService.post(
await apiURL("/cast/device-info/"),
{
publicKey: publicKey,
},
);
return resp.data.deviceCode;
}
public async publishCastPayload(
code: string,
castPayload: string,