diff --git a/app/providers/CallProvider/CallProvider.tsx b/app/providers/CallProvider/CallProvider.tsx index f5781fb..c62f082 100644 --- a/app/providers/CallProvider/CallProvider.tsx +++ b/app/providers/CallProvider/CallProvider.tsx @@ -1,12 +1,13 @@ import { Call } from "@/app/components/Call/Call"; import { useConsoleLogger } from "@/app/hooks/useConsoleLogger"; -import { createContext, useRef, useState } from "react"; +import { createContext, useEffect, useRef, useState } from "react"; import nacl from 'tweetnacl'; import { useSender } from "../ProtocolProvider/useSender"; import { PacketSignalPeer, SignalType } from "../ProtocolProvider/protocol/packets/packet.signal.peer"; import { usePacket } from "../ProtocolProvider/usePacket"; import { usePublicKey } from "../AccountProvider/usePublicKey"; import { PacketWebRTC, WebRTCSignalType } from "../ProtocolProvider/protocol/packets/packet.webrtc"; +import { PacketIceServers } from "../ProtocolProvider/protocol/packets/packet.ice.servers"; export interface CallContextValue { @@ -69,6 +70,40 @@ export function CallProvider(props : CallProviderProps) { const roleRef = useRef(null); const [sharedSecret, setSharedSecret] = useState(""); + const iceServersRef = useRef([]); + + useEffect(() => { + /** + * Нам нужно получить ICE серверы для установки соединения из разных сетей + * Получаем их от сервера + */ + let packet = new PacketIceServers(); + send(packet); + }, []); + + usePacket(28, async (packet: PacketIceServers) => { + let iceServers = packet.getIceServers(); + /** + * ICE серверы получены, теперь нужно привести их к форматку клиента и добавить udp и tcp варианты + */ + let formattedIceServers: RTCIceServer[] = []; + for(let i = 0; i < iceServers.length; i++){ + let server = iceServers[i]; + formattedIceServers.push({ + urls: "trun:" + server.urls + "?transport=udp", + username: server.username, + credential: server.credential + }); + formattedIceServers.push({ + urls: "trun:" + server.urls + "?transport=tcp", + username: server.username, + credential: server.credential + }); + } + console.info("ICE SERVERS RECEIVED: ", formattedIceServers); + iceServersRef.current = formattedIceServers; + info("Received ICE servers from server, count: " + formattedIceServers.length); + }, []); usePacket(27, async (packet: PacketWebRTC) => { if(!activeCall || callState != CallState.WEB_RTC_EXCHANGE){ @@ -213,10 +248,7 @@ export function CallProvider(props : CallProviderProps) { * Нужно отправить свой SDP оффер другой стороне, чтобы установить WebRTC соединение */ peerConnectionRef.current = new RTCPeerConnection({ - //Experemental - iceServers: [ - { urls: 'stun:stun.l.google.com:19302' } - ] + iceServers: iceServersRef.current }); /** * Подписываемся на ICE кандидат diff --git a/app/providers/ProtocolProvider/protocol/packets/packet.ice.servers.ts b/app/providers/ProtocolProvider/protocol/packets/packet.ice.servers.ts new file mode 100644 index 0000000..69a598b --- /dev/null +++ b/app/providers/ProtocolProvider/protocol/packets/packet.ice.servers.ts @@ -0,0 +1,50 @@ +import Packet from "../packet"; +import Stream from "../stream"; + +export class PacketIceServers extends Packet { + private iceServers: RTCIceServer[] = []; + + public getPacketId(): number { + return 28; + } + + public _receive(stream: Stream): void { + const serversCount = stream.readInt16(); + this.iceServers = []; + for(let i = 0; i < serversCount; i++){ + const urls = stream.readString(); + const username = stream.readString(); + const credential = stream.readString(); + this.iceServers.push({ + urls, + username, + credential + }); + } + } + + public _send(): Promise | Stream { + const stream = new Stream(); + stream.writeInt16(this.getPacketId()); + stream.writeInt16(this.iceServers.length); + for(let i = 0; i < this.iceServers.length; i++){ + const server = this.iceServers[i]; + /** + * Не поддерживает массив urls!!! + */ + stream.writeString((server.urls as string)); + stream.writeString(server.username || ""); + stream.writeString(server.credential || ""); + } + return stream; + } + + public getIceServers(): RTCIceServer[] { + return this.iceServers; + } + + public setIceServers(servers: RTCIceServer[]) { + this.iceServers = servers; + } + +} \ No newline at end of file diff --git a/app/providers/ProtocolProvider/protocol/protocol.ts b/app/providers/ProtocolProvider/protocol/protocol.ts index 28c4172..c9e6822 100644 --- a/app/providers/ProtocolProvider/protocol/protocol.ts +++ b/app/providers/ProtocolProvider/protocol/protocol.ts @@ -27,6 +27,7 @@ import { PacketDeviceResolve } from "./packets/packet.device.resolve"; import { PacketSync } from "./packets/packet.sync"; import { PacketSignalPeer } from "./packets/packet.signal.peer"; import { PacketWebRTC } from "./packets/packet.webrtc"; +import { PacketIceServers } from "./packets/packet.ice.servers"; export default class Protocol extends EventEmitter { private serverAddress: string; @@ -129,6 +130,7 @@ export default class Protocol extends EventEmitter { this._supportedPackets.set(25, new PacketSync()); this._supportedPackets.set(26, new PacketSignalPeer()); this._supportedPackets.set(27, new PacketWebRTC()); + this._supportedPackets.set(28, new PacketIceServers()); } private _findWaiters(packetId: number): ((packet: Packet) => void)[] {