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

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,110 @@
package im.rosetta.calls;
import java.util.HashMap;
import io.g365sfu.Room;
import io.orprotocol.ProtocolException;
import io.orprotocol.client.Client;
import io.orprotocol.packet.Packet;
public class CallSession {
public String callId;
public String joinToken;
public Long createdAt;
public Long ringingTimeout;
/**
* Клиенты которым сейчас идет дозвон (публичные ключи)
* Клиенты в этом списке не могут принимать другие звонки, так как они уже заняты дозвоном,
* но они еще не в звонке, так как не приняли звонок
*
* Клиенты удаляются из этого списка, когда они принимают звонок или отклоняют его, тогда они либо переходят в звонок, либо становятся свободными для других звонков
*/
public HashMap<String, Long> ringing;
/**
* Клиенты, которые уже приняли звонок и находятся в звонке (публичные ключи) и их сокеты
* pk -> client
*/
public HashMap<String, Client> clients;
/**
* Если звонок активен у него появляется комната, иначе комната null
*/
public Room room;
public CallSession(String callId, String joinToken, Long ringingTimeout) {
this.callId = callId;
this.joinToken = joinToken;
this.clients = new HashMap<>();
this.ringing = new HashMap<>();
this.createdAt = System.currentTimeMillis();
this.ringingTimeout = ringingTimeout;
}
public void joinCall(String publicKey, Client client) {
if(this.ringing.containsKey(publicKey)) {
this.ringing.remove(publicKey);
}
this.clients.put(publicKey, client);
}
/**
* Получаем публичный ключ клиента по его сокету, чтобы понимать, кто отправляет сигналы в рамках звонка
* @param client Сокет клиента, для которого нужно получить публичный ключ
* @return Публичный ключ клиента, или null если клиент не найден в сессии звонка
*/
public String getPublicKey(Client client) {
for (String publicKey : this.clients.keySet()) {
if (this.clients.get(publicKey).equals(client)) {
return publicKey;
}
}
return null;
}
public String getCallId() {
return this.callId;
}
public String getJoinToken() {
return this.joinToken;
}
public void addRinging(String publicKey) {
this.ringing.put(publicKey, System.currentTimeMillis());
}
public void setRoom(Room room) {
this.room = room;
}
public Room getRoom() {
return this.room;
}
/**
* Отправляем пакет всем участникам звонка, кроме исключенного клиента (обычно отправителя)
* @param packet Пакет для отправки
* @param excludeClient Клиент, которому не нужно отправлять пакет (обычно отправитель)
* @throws ProtocolException Если произошла ошибка при отправке пакета клиенту
*/
public void sendPacket(Packet packet, Client excludeClient) throws ProtocolException {
for (Client client : this.clients.values()) {
if (!client.equals(excludeClient)) {
client.send(packet);
}
}
}
/**
* Проверяем, нужно ли удалять сессию звонка.
* Сессию звонка нужно удалять, если в ней меньше 2 клиентов и при этом нет клиентов в состоянии дозвона,
* или если сессия была создана более 1 минуты назад, так как это значит, что клиенты не ответили на звонок и он устарел
* @return true, если сессию звонка нужно удалять, false иначе
*/
public boolean shouldRemove() {
return this.clients.size() <= 1 && (this.ringing.size() == 0 || System.currentTimeMillis() - this.createdAt > this.ringingTimeout);
}
}