Обновление протокола для неавторизованных звонков

This commit is contained in:
RoyceDa
2026-04-04 18:31:05 +02:00
parent 3c6b2e0e71
commit 939a4d55f4
10 changed files with 427 additions and 128 deletions

View File

@@ -6,6 +6,8 @@ import java.util.Set;
import java.util.UUID;
import im.rosetta.Failures;
import im.rosetta.calls.CallManager;
import im.rosetta.calls.CallSession;
import im.rosetta.client.ClientManager;
import im.rosetta.client.tags.ECIAuthentificate;
import im.rosetta.packet.Packet26SignalPeer;
@@ -33,16 +35,18 @@ public class Executor26SignalPeer extends PacketExecutor<Packet26SignalPeer> {
*/
private Set<NetworkSignalType> authentificatedTypes = new HashSet<>(){{
add(NetworkSignalType.CALL);
/**
* Так как комнату создает звонящий, то комнату может создать только
* авторизованный пользователь
*/
add(NetworkSignalType.CREATE_ROOM);
}};
public Executor26SignalPeer(ClientManager clientManager, ForwardUnitService fus) {
/**
* Менеджер звонков, который реализует весь необхоимый функционал для управления звонками,
* например проверку занятости пользователя, и тд
*/
private CallManager callManager;
public Executor26SignalPeer(ClientManager clientManager, ForwardUnitService fus, CallManager callManager) {
this.clientManager = clientManager;
this.fus = fus;
this.callManager = callManager;
}
@Override
@@ -72,42 +76,123 @@ public class Executor26SignalPeer extends PacketExecutor<Packet26SignalPeer> {
/**
* Инициируется звонок от src к dst, проверяем, что dst не занят другим звонком, если занят, то отправляем сигнал END_CALL_BECAUSE_BUSY обратно src
*/
Room room = this.fus.getRoomByParticipantId(packet.getDst());
if(room != null) {
if(this.callManager.isBusy(dst) || this.callManager.isBusy(src)) {
/**
* Получатель сигнала уже находится в другой комнате, значит он занят другим звонком, отправляем сигнал END_CALL_BECAUSE_BUSY обратно src
*/
Packet26SignalPeer responsePacket = new Packet26SignalPeer();
responsePacket.setSignalType(NetworkSignalType.END_CALL_BECAUSE_BUSY);
this.clientManager.sendPacketToAuthorizedPK(packet.getSrc(), responsePacket);
client.send(responsePacket);
return;
}
/**
* Генерируем CallID и JoinToken
*/
String callId = UUID.randomUUID().toString();
String joinToken = UUID.randomUUID().toString();
packet.setJoinToken(joinToken);
packet.setCallId(callId);
/**
* Создаем сессию звонка и добавляем в нее звонящего
*/
CallSession session = this.callManager.createCall(callId, joinToken);
session.joinCall(src, client);
/**
* Добавляем dst в ringing, чтобы пометить, что ему поступает звонок
*/
session.addRinging(dst);
/**
* Получатель сигнала не занят, отправляем ему пуш уведомление о входящем звонке и сигнал CALL для инициализации звонка
*/
pushNotifyDispatcher.sendPush(dst, new HashMap<>(){{
put("type", PushType.CALL);
put("dialog", src);
put("callId", UUID.randomUUID().toString());
put("callId", callId);
put("joinToken", joinToken);
}});
}
if(type == NetworkSignalType.CREATE_ROOM){
/**
* Создается комната для звонка
* Отправляем сигнал CALL всем авторизованным устройствам вызываемого абонента
*/
Room room = this.fus.createRoom();
room.addParticipant(packet.getSrc());
room.addParticipant(packet.getDst());
packet.setRoomId(room.getRoomId());
/**
* Результат создания комнаты транслируем обоим участникам, чтобы они могли начать обмен WebRTC SDP, и тд
*/
this.clientManager.sendPacketToAuthorizedPK(packet.getSrc(), packet);
this.clientManager.sendPacketToAuthorizedPK(packet.getDst(), packet);
this.clientManager.sendPacketToAuthorizedPK(dst, packet);
return;
}
this.clientManager.sendPacketToAuthorizedPK(packet.getDst(), packet);
if(type == NetworkSignalType.ACCEPT){
String callId = packet.getCallId();
String joinToken = packet.getJoinToken();
CallSession session = this.callManager.getCallSession(callId, joinToken);
if(session == null) {
/**
* Сессии звонка нет
*/
client.disconnect(Failures.DATA_MISSMATCH);
return;
}
Room room = this.fus.createRoom();
session.setRoom(room);
session.joinCall(src, client);
for(String participant : session.clients.keySet()) {
room.addParticipant(participant);
}
session.sendPacket(packet, client);
return;
}
if(type == NetworkSignalType.KEY_EXCHANGE){
/**
* Ретранслируем ключи в рамках сессии
*/
CallSession session = this.callManager.getCallSession(client);
if(session == null) {
/**
* Сессии звонка нет
*/
client.disconnect(Failures.DATA_MISSMATCH);
return;
}
/**
* Обмениваемся ключами в рамках сессии, ретранслируя их всем участникам сессии, кроме отправителя
*/
session.sendPacket(packet, client);
return;
}
if(type == NetworkSignalType.END_CALL) {
/**
* Ретранслируем сигнал окончания звонка всем участникам сессии, кроме отправителя, и удаляем сессию
*/
/**
* Сначала получаем сессию по сокету отправителя пакета, если не находим, то пробуем найти сессию по callId и joinToken из пакета, если не находим,
* то отключаем клиента от сервера, так как он отправляет некорректные данные
*/
CallSession session = this.callManager.getCallSession(client);
if(session == null) {
String callId = packet.getCallId();
String joinToken = packet.getJoinToken();
session = this.callManager.getCallSession(callId, joinToken);
}
if(session == null) {
/**
* Сессии звонка нет
*/
client.disconnect(Failures.DATA_MISSMATCH);
return;
}
session.sendPacket(packet, client);
this.callManager.removeSession(session);
return;
}
if(type == NetworkSignalType.ACTIVE) {
/**
* Клиент сообщил, что прошел стадию обмена ключами и звонок активен
*/
CallSession session = this.callManager.getCallSession(client);
if(session == null) {
/**
* Сессии звонка нет
*/
client.disconnect(Failures.DATA_MISSMATCH);
return;
}
session.sendPacket(packet, null);
}
}
}