From c052fdae41f95af35db538934104642e43171cda Mon Sep 17 00:00:00 2001 From: RoyceDa Date: Sat, 4 Apr 2026 16:48:26 +0200 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BD=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=82=D0=BE=D0=BA=D0=BE=D0=BB=D0=B0=20=D0=B7?= =?UTF-8?q?=D0=B2=D0=BE=D0=BD=D0=BA=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/providers/CallProvider/CallProvider.tsx | 114 +++++++++--------- .../protocol/packets/packet.signal.peer.ts | 44 ++++--- .../protocol/packets/packet.webrtc.ts | 22 ---- 3 files changed, 87 insertions(+), 93 deletions(-) diff --git a/app/providers/CallProvider/CallProvider.tsx b/app/providers/CallProvider/CallProvider.tsx index 6f65b6b..3ef314e 100644 --- a/app/providers/CallProvider/CallProvider.tsx +++ b/app/providers/CallProvider/CallProvider.tsx @@ -16,7 +16,6 @@ import { attachReceiverE2EE, attachSenderE2EE } from "./audioE2EE"; import { useDeattachedSender } from "../DialogProvider/useDeattachedSender"; import { AttachmentType } from "../ProtocolProvider/protocol/packets/packet.message"; import { generateRandomKey } from "@/app/utils/utils"; -import { useSystemInformation } from "../SystemProvider/useSystemInformation"; export interface CallContextValue { call: (callable: string) => void; @@ -86,7 +85,12 @@ export function CallProvider(props : CallProviderProps) { const soundRef = useRef(true); const {sendMessage} = useDeattachedSender(); const hasRemoteTrackRef = useRef(false); - const systemInformation = useSystemInformation(); + + /** + * Используются для входа в звонок + */ + const callSessionIdRef = useRef(""); + const callTokenRef = useRef(""); const {playSound, stopSound, stopLoopSound} = useSound(); const {setWindowPriority} = useWindow(); @@ -196,8 +200,6 @@ export function CallProvider(props : CallProviderProps) { let answerSignal = new PacketWebRTC(); answerSignal.setSignalType(WebRTCSignalType.ANSWER); answerSignal.setSdpOrCandidate(JSON.stringify(answer)); - answerSignal.setPublicKey(publicKey); - answerSignal.setDeviceId(systemInformation.id); send(answerSignal); info("Received WebRTC offer, set remote description and sent answer"); return; @@ -247,47 +249,49 @@ export function CallProvider(props : CallProviderProps) { info("Received incoming call from " + packet.getSrc() + " but we are already on a call, sent busy signal"); return; } + callSessionIdRef.current = packet.getCallId(); + callTokenRef.current = packet.getJoinToken(); setWindowPriority(true); playSound("ringtone.mp3", true); setActiveCall(packet.getSrc()); setCallState(CallState.INCOMING); setShowCallView(true); } - if(signalType == SignalType.KEY_EXCHANGE && roleRef.current == CallRole.CALLER){ - console.info("EXCHANGE SIGNAL RECEIVED, CALLER ROLE"); - /** - * Другая сторона сгенерировала ключи для сессии и отправила нам публичную часть, - * теперь мы можем создать общую секретную сессию для шифрования звонка - */ - const sharedPublic = packet.getSharedPublic(); - if(!sharedPublic){ - info("Received key exchange signal without shared public key"); - return; - } - const sessionKeys = generateSessionKeys(); - const computedSharedSecret = nacl.box.before(Buffer.from(sharedPublic, 'hex'), sessionKeys.secretKey); - sharedSecretRef.current = Buffer.from(computedSharedSecret).toString('hex'); - info("Generated shared secret for call session: " + sharedSecretRef.current); - /** - * Нам нужно отправить свой публичный ключ другой стороне, чтобы она тоже могла создать общую секретную сессию - */ - const signalPacket = new PacketSignalPeer(); - signalPacket.setSrc(publicKey); - signalPacket.setDst(packet.getSrc()); - signalPacket.setSignalType(SignalType.KEY_EXCHANGE); - signalPacket.setSharedPublic(Buffer.from(sessionKeys.publicKey).toString('hex')); - send(signalPacket); - setCallState(CallState.WEB_RTC_EXCHANGE); - /** - * Создаем комнату на сервере SFU, комнату создает звонящий - */ - let webRtcSignal = new PacketSignalPeer(); - webRtcSignal.setSignalType(SignalType.CREATE_ROOM); - webRtcSignal.setSrc(publicKey); - webRtcSignal.setDst(packet.getSrc()); - send(webRtcSignal); - } - if(signalType == SignalType.KEY_EXCHANGE && roleRef.current == CallRole.CALLEE){ + // if(signalType == SignalType.KEY_EXCHANGE && roleRef.current == CallRole.CALLER){ + // console.info("EXCHANGE SIGNAL RECEIVED, CALLER ROLE"); + // /** + // * Другая сторона сгенерировала ключи для сессии и отправила нам публичную часть, + // * теперь мы можем создать общую секретную сессию для шифрования звонка + // */ + // const sharedPublic = packet.getSharedPublic(); + // if(!sharedPublic){ + // info("Received key exchange signal without shared public key"); + // return; + // } + // const sessionKeys = generateSessionKeys(); + // const computedSharedSecret = nacl.box.before(Buffer.from(sharedPublic, 'hex'), sessionKeys.secretKey); + // sharedSecretRef.current = Buffer.from(computedSharedSecret).toString('hex'); + // info("Generated shared secret for call session: " + sharedSecretRef.current); + // /** + // * Нам нужно отправить свой публичный ключ другой стороне, чтобы она тоже могла создать общую секретную сессию + // */ + // const signalPacket = new PacketSignalPeer(); + // signalPacket.setSrc(publicKey); + // signalPacket.setDst(packet.getSrc()); + // signalPacket.setSignalType(SignalType.KEY_EXCHANGE); + // signalPacket.setSharedPublic(Buffer.from(sessionKeys.publicKey).toString('hex')); + // send(signalPacket); + // setCallState(CallState.WEB_RTC_EXCHANGE); + // /** + // * Создаем комнату на сервере SFU, комнату создает звонящий + // */ + // // let webRtcSignal = new PacketSignalPeer(); + // // webRtcSignal.setSignalType(SignalType.CREATE_ROOM); + // // webRtcSignal.setSrc(publicKey); + // // webRtcSignal.setDst(packet.getSrc()); + // // send(webRtcSignal); + // } + if(signalType == SignalType.KEY_EXCHANGE){ console.info("EXCHANGE SIGNAL RECEIVED, CALLEE ROLE"); /** * Мы отправили свою публичную часть ключа другой стороне, @@ -308,7 +312,19 @@ export function CallProvider(props : CallProviderProps) { info("Generated shared secret for call session: " + sharedSecretRef.current); setCallState(CallState.WEB_RTC_EXCHANGE); } - if(signalType == SignalType.CREATE_ROOM) { + if(signalType == SignalType.ACCEPT){ + /** + * Другая сторона приняла наш звонок, комната на SFU создалась, нужно сгенерировать ключи + */ + const keys = generateSessionKeys(); + const signalPacket = new PacketSignalPeer(); + signalPacket.setSrc(publicKey); + signalPacket.setDst(activeCall); + signalPacket.setSignalType(SignalType.KEY_EXCHANGE); + signalPacket.setSharedPublic(Buffer.from(keys.publicKey).toString('hex')); + send(signalPacket); + } + if(signalType == SignalType.ACTIVE) { if(!sessionKeys){ /** * Сервер может отправить CREATE_ROOM сигнал, даже если мы приняли звонок на другом устройстве, по этому проверяем, @@ -319,12 +335,6 @@ export function CallProvider(props : CallProviderProps) { end(); return; } - /** - * Создана комната для обмена WebRTC потоками, но такое событие сервер может отправить даже если звонок - * был принят с другого устройства, по этому проверяем, наш ли звонок - */ - roomIdRef.current = packet.getRoomId(); - info("WebRTC room created with id: " + packet.getRoomId()); /** * Нужно отправить свой SDP оффер другой стороне, чтобы установить WebRTC соединение */ @@ -341,8 +351,6 @@ export function CallProvider(props : CallProviderProps) { let candidateSignal = new PacketWebRTC(); candidateSignal.setSignalType(WebRTCSignalType.ICE_CANDIDATE); candidateSignal.setSdpOrCandidate(JSON.stringify(event.candidate)); - candidateSignal.setPublicKey(publicKey); - candidateSignal.setDeviceId(systemInformation.id); send(candidateSignal); } } @@ -404,8 +412,6 @@ export function CallProvider(props : CallProviderProps) { let offerSignal = new PacketWebRTC(); offerSignal.setSignalType(WebRTCSignalType.OFFER); offerSignal.setSdpOrCandidate(JSON.stringify(offer)); - offerSignal.setPublicKey(publicKey); - offerSignal.setDeviceId(systemInformation.id); send(offerSignal); return; } @@ -541,14 +547,14 @@ export function CallProvider(props : CallProviderProps) { stopLoopSound(); stopSound(); /** - * Звонок принят, генерируем ключи для сессии и отправляем их другой стороне для установления защищенного канала связи + * Звонок принят, можно обмениваться ключами */ - const keys = generateSessionKeys(); const signalPacket = new PacketSignalPeer(); signalPacket.setSrc(publicKey); signalPacket.setDst(activeCall); - signalPacket.setSignalType(SignalType.KEY_EXCHANGE); - signalPacket.setSharedPublic(Buffer.from(keys.publicKey).toString('hex')); + signalPacket.setCallId(callSessionIdRef.current); + signalPacket.setJoinToken(callTokenRef.current); + signalPacket.setSignalType(SignalType.ACCEPT); send(signalPacket); setCallState(CallState.KEY_EXCHANGE); roleRef.current = CallRole.CALLEE; diff --git a/app/providers/ProtocolProvider/protocol/packets/packet.signal.peer.ts b/app/providers/ProtocolProvider/protocol/packets/packet.signal.peer.ts index 1ad3d38..fcba154 100644 --- a/app/providers/ProtocolProvider/protocol/packets/packet.signal.peer.ts +++ b/app/providers/ProtocolProvider/protocol/packets/packet.signal.peer.ts @@ -6,9 +6,13 @@ export enum SignalType { KEY_EXCHANGE = 1, ACTIVE_CALL = 2, END_CALL = 3, - CREATE_ROOM = 4, + /** + * Переведен в стадию активного, значит комната на SFU уже создана и можно начинать обмен сигналами WebRTC + */ + ACTIVE = 4, END_CALL_BECAUSE_PEER_DISCONNECTED = 5, - END_CALL_BECAUSE_BUSY = 6 + END_CALL_BECAUSE_BUSY = 6, + ACCEPT = 7 } /** @@ -28,12 +32,8 @@ export class PacketSignalPeer extends Packet { private signalType: SignalType = SignalType.CALL; - /** - * Используется если SignalType == CREATE_ROOM, - * для идентификации комнаты на SFU сервере, в которой будет происходить обмен сигналами - * WebRTC для установления P2P соединения между участниками звонка - */ - private roomId: string = ""; + private callId: string = ""; + private joinToken: string = ""; public getPacketId(): number { @@ -50,8 +50,9 @@ export class PacketSignalPeer extends Packet { if(this.signalType == SignalType.KEY_EXCHANGE){ this.sharedPublic = stream.readString(); } - if(this.signalType == SignalType.CREATE_ROOM){ - this.roomId = stream.readString(); + if(this.signalType == SignalType.CALL || this.signalType == SignalType.ACCEPT){ + this.callId = stream.readString(); + this.joinToken = stream.readString(); } } @@ -67,8 +68,9 @@ export class PacketSignalPeer extends Packet { if(this.signalType == SignalType.KEY_EXCHANGE){ stream.writeString(this.sharedPublic); } - if(this.signalType == SignalType.CREATE_ROOM){ - stream.writeString(this.roomId); + if(this.signalType == SignalType.CALL || this.signalType == SignalType.ACCEPT){ + stream.writeString(this.callId); + stream.writeString(this.joinToken); } return stream; } @@ -105,12 +107,20 @@ export class PacketSignalPeer extends Packet { this.src = src; } - public getRoomId(): string { - return this.roomId; + public getCallId(): string { + return this.callId; } - - public setRoomId(roomId: string) { - this.roomId = roomId; + + public setCallId(callId: string) { + this.callId = callId; + } + + public getJoinToken(): string { + return this.joinToken; + } + + public setJoinToken(joinToken: string) { + this.joinToken = joinToken; } } \ No newline at end of file diff --git a/app/providers/ProtocolProvider/protocol/packets/packet.webrtc.ts b/app/providers/ProtocolProvider/protocol/packets/packet.webrtc.ts index 8641b4b..9a5ca74 100644 --- a/app/providers/ProtocolProvider/protocol/packets/packet.webrtc.ts +++ b/app/providers/ProtocolProvider/protocol/packets/packet.webrtc.ts @@ -15,8 +15,6 @@ export class PacketWebRTC extends Packet { private signalType: WebRTCSignalType = WebRTCSignalType.OFFER; private sdpOrCandidate: string = ""; - private publicKey: string = ""; - private deviceId: string = ""; public getPacketId(): number { return 27; @@ -25,8 +23,6 @@ export class PacketWebRTC extends Packet { public _receive(stream: Stream): void { this.signalType = stream.readInt8(); this.sdpOrCandidate = stream.readString(); - this.publicKey = stream.readString(); - this.deviceId = stream.readString(); } public _send(): Promise | Stream { @@ -34,8 +30,6 @@ export class PacketWebRTC extends Packet { stream.writeInt16(this.getPacketId()); stream.writeInt8(this.signalType); stream.writeString(this.sdpOrCandidate); - stream.writeString(this.publicKey); - stream.writeString(this.deviceId); return stream; } @@ -55,20 +49,4 @@ export class PacketWebRTC extends Packet { return this.sdpOrCandidate; } - public setPublicKey(key: string) { - this.publicKey = key; - } - - public getPublicKey(): string { - return this.publicKey; - } - - public setDeviceId(id: string) { - this.deviceId = id; - } - - public getDeviceId(): string { - return this.deviceId; - } - } \ No newline at end of file