Update livekit service URLs if they fail
Requires https://github.com/matrix-org/matrix-js-sdk/pull/3598 Fixes https://github.com/vector-im/element-call/issues/1190 Fixes https://github.com/matrix-org/matrix-hosted/issues/8021
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
useState,
|
||||
} from "react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { GroupCall } from "matrix-js-sdk";
|
||||
|
||||
import {
|
||||
OpenIDClientParts,
|
||||
@@ -32,7 +33,7 @@ import { ErrorView, LoadingView } from "../FullScreenView";
|
||||
|
||||
interface Props {
|
||||
client: OpenIDClientParts;
|
||||
livekitServiceURL: string;
|
||||
groupCall: GroupCall;
|
||||
roomName: string;
|
||||
children: ReactNode;
|
||||
}
|
||||
@@ -41,12 +42,7 @@ const SFUConfigContext = createContext<SFUConfig>(undefined);
|
||||
|
||||
export const useSFUConfig = () => useContext(SFUConfigContext);
|
||||
|
||||
export function OpenIDLoader({
|
||||
client,
|
||||
livekitServiceURL,
|
||||
roomName,
|
||||
children,
|
||||
}: Props) {
|
||||
export function OpenIDLoader({ client, groupCall, roomName, children }: Props) {
|
||||
const [state, setState] = useState<
|
||||
SFUConfigLoading | SFUConfigLoaded | SFUConfigFailed
|
||||
>({ kind: "loading" });
|
||||
@@ -56,7 +52,7 @@ export function OpenIDLoader({
|
||||
try {
|
||||
const result = await getSFUConfigWithOpenID(
|
||||
client,
|
||||
livekitServiceURL,
|
||||
groupCall,
|
||||
roomName
|
||||
);
|
||||
setState({ kind: "loaded", sfuConfig: result });
|
||||
@@ -65,7 +61,7 @@ export function OpenIDLoader({
|
||||
setState({ kind: "failed", error: e });
|
||||
}
|
||||
})();
|
||||
}, [client, livekitServiceURL, roomName]);
|
||||
}, [client, groupCall, roomName]);
|
||||
|
||||
switch (state.kind) {
|
||||
case "loading":
|
||||
|
||||
@@ -14,9 +14,11 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { MatrixClient } from "matrix-js-sdk";
|
||||
import { GroupCall, IOpenIDToken, MatrixClient } from "matrix-js-sdk";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { Config } from "../config/Config";
|
||||
|
||||
export interface SFUConfig {
|
||||
url: string;
|
||||
jwt: string;
|
||||
@@ -30,25 +32,84 @@ export type OpenIDClientParts = Pick<
|
||||
|
||||
export async function getSFUConfigWithOpenID(
|
||||
client: OpenIDClientParts,
|
||||
livekitServiceURL: string,
|
||||
groupCall: GroupCall,
|
||||
roomName: string
|
||||
): Promise<SFUConfig> {
|
||||
const openIdToken = await client.getOpenIdToken();
|
||||
logger.debug("Got openID token", openIdToken);
|
||||
|
||||
const res = await fetch(livekitServiceURL + "/sfu/get", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
room: roomName,
|
||||
openid_token: openIdToken,
|
||||
device_id: client.getDeviceId(),
|
||||
}),
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error("SFU Config fetch failed with status code " + res.status);
|
||||
// if the call has a livekit service URL, try it.
|
||||
if (groupCall.livekitServiceURL) {
|
||||
try {
|
||||
logger.info(`Trying to get JWT from ${groupCall.livekitServiceURL}...`);
|
||||
const sfuConfig = await getLiveKitJWT(
|
||||
client,
|
||||
groupCall.livekitServiceURL,
|
||||
roomName,
|
||||
openIdToken
|
||||
);
|
||||
|
||||
return sfuConfig;
|
||||
} catch (e) {
|
||||
logger.warn(
|
||||
`Failed to get JWT from group call's configured URL of ${groupCall.livekitServiceURL}.`,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise, try our configured one and, if it works, update the call's service URL in the state event
|
||||
// NB. This wuill update it for everyone so we may end up with multiple clients updating this when they
|
||||
// join at similar times, but we don't have a huge number of options here.
|
||||
const urlFromConf = Config.get().livekit.livekit_service_url;
|
||||
logger.info(`Trying livekit service URL from our config: ${urlFromConf}...`);
|
||||
try {
|
||||
const sfuConfig = await getLiveKitJWT(
|
||||
client,
|
||||
urlFromConf,
|
||||
roomName,
|
||||
openIdToken
|
||||
);
|
||||
|
||||
logger.info(`Updating call livekit service URL with: ${urlFromConf}...`);
|
||||
try {
|
||||
await groupCall.updateLivekitServiceURL(urlFromConf);
|
||||
} catch (e) {
|
||||
logger.warn(
|
||||
`Failed to update call livekit service URL: continuing anyway.`
|
||||
);
|
||||
}
|
||||
|
||||
return sfuConfig;
|
||||
} catch (e) {
|
||||
logger.error("Failed to get JWT from URL defined in Config.", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async function getLiveKitJWT(
|
||||
client: OpenIDClientParts,
|
||||
livekitServiceURL: string,
|
||||
roomName: string,
|
||||
openIDToken: IOpenIDToken
|
||||
): Promise<SFUConfig> {
|
||||
try {
|
||||
const res = await fetch(livekitServiceURL + "/sfu/get", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
room: roomName,
|
||||
openid_token: openIDToken,
|
||||
device_id: client.getDeviceId(),
|
||||
}),
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error("SFU Config fetch failed with status code " + res.status);
|
||||
}
|
||||
return await res.json();
|
||||
} catch (e) {
|
||||
throw new Error("SFU Config fetch failed with exception " + e);
|
||||
}
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import { UserChoices } from "../livekit/useLiveKit";
|
||||
import { findDeviceByName } from "../media-utils";
|
||||
import { OpenIDLoader } from "../livekit/OpenIDLoader";
|
||||
import { ActiveCall } from "./InCallView";
|
||||
import { Config } from "../config/Config";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -220,20 +219,13 @@ export function GroupCallView({
|
||||
undefined
|
||||
);
|
||||
|
||||
const livekitServiceURL =
|
||||
groupCall.foci[0]?.livekitServiceUrl ??
|
||||
Config.get().livekit.livekit_service_url;
|
||||
if (!livekitServiceURL) {
|
||||
return <ErrorView error={new Error("No livekit_service_url defined")} />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <ErrorView error={error} />;
|
||||
} else if (state === GroupCallState.Entered && userChoices) {
|
||||
return (
|
||||
<OpenIDLoader
|
||||
client={client}
|
||||
livekitServiceURL={livekitServiceURL}
|
||||
groupCall={groupCall}
|
||||
roomName={`${groupCall.room.roomId}-${groupCall.groupCallId}`}
|
||||
>
|
||||
<ActiveCall
|
||||
|
||||
Reference in New Issue
Block a user