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

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

@@ -0,0 +1,109 @@
package im.rosetta.calls;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import im.rosetta.client.ClientManager;
import im.rosetta.packet.Packet26SignalPeer;
import im.rosetta.packet.runtime.NetworkSignalType;
import io.orprotocol.ProtocolException;
import io.orprotocol.client.Client;
import io.orprotocol.packet.Packet;
public class CallManager {
private List<CallSession> callSessions = new ArrayList<>();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private static final long RINGING_TIMEOUT = 10 * 1000; // 1 минута
private ClientManager clientManager;
public CallManager(ClientManager clientManager) {
this.clientManager = clientManager;
scheduler.scheduleAtFixedRate(this::cleanupCallSessions, 0, 30, TimeUnit.SECONDS);
}
public void cleanupCallSessions() {
/**
* Такая конструкция нужна для избежания ConcurrentModificationException,
* так как мы не можем удалять элементы из списка, по которому проходим в цикле,
* поэтому мы сначала собираем сессии звонков, которые нужно удалить, а потом
* удаляем их из основного списка
*/
List<CallSession> sessionsToRemove = new ArrayList<>();
for (CallSession session : this.callSessions) {
if (session.shouldRemove()) {
/**
* Отправляем всем в сессии что звонок завершился, так как он устарел, и удаляем сессию из списка активных сессий
*/
Packet26SignalPeer rtout = new Packet26SignalPeer();
rtout.setSignalType(NetworkSignalType.RINGING_TIMEOUT);
Packet26SignalPeer endCallPacket = new Packet26SignalPeer();
endCallPacket.setSignalType(NetworkSignalType.END_CALL);
endCallPacket.setJoinToken(session.getJoinToken());
endCallPacket.setCallId(session.getCallId());
try {
session.sendPacket(rtout, null);
this.sendPacketToRinging(session, endCallPacket);
} catch (ProtocolException e) {
e.printStackTrace();
}
sessionsToRemove.add(session);
}
}
for (CallSession session : sessionsToRemove) {
this.callSessions.remove(session);
}
}
public CallSession createCall(String callId, String joinToken) {
CallSession session = new CallSession(callId, joinToken, RINGING_TIMEOUT);
this.callSessions.add(session);
return session;
}
public CallSession getCallSession(String callId, String joinToken) {
for (CallSession session : this.callSessions) {
if (session.getCallId().equals(callId) && session.getJoinToken().equals(joinToken)) {
return session;
}
}
return null;
}
public boolean isBusy(String publicKey) {
for (CallSession session : this.callSessions) {
if (session.clients.containsKey(publicKey)) {
return true;
}
if(session.ringing.containsKey(publicKey)) {
return true;
}
}
return false;
}
public void sendPacketToRinging(CallSession session, Packet packet) throws ProtocolException {
for (String publicKey : session.ringing.keySet()) {
this.clientManager.sendPacketToAuthorizedPK(publicKey, packet);
}
}
public CallSession getCallSession(Client client) {
for (CallSession session : this.callSessions) {
if (session.clients.containsValue(client)) {
return session;
}
}
return null;
}
public void removeSession(CallSession session) {
this.callSessions.remove(session);
}
}