Compare commits
10 Commits
faaffd86d0
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 9432969cb4 | |||
|
|
f87198c054 | ||
|
|
58fe3c409d | ||
|
|
bdc44f36f0 | ||
|
|
145aaf8288 | ||
|
|
ddcd08aeae | ||
|
|
435d6fefa8 | ||
|
|
986cd765d8 | ||
|
|
a9c4612a72 | ||
|
|
bc0a64f450 |
@@ -116,7 +116,7 @@ public class Boot {
|
|||||||
int cleanupEveryDays = System.getenv("BUFFER_CLEANUP_DAYS") != null ?
|
int cleanupEveryDays = System.getenv("BUFFER_CLEANUP_DAYS") != null ?
|
||||||
Integer.parseInt(System.getenv("BUFFER_CLEANUP_DAYS")) : 7;
|
Integer.parseInt(System.getenv("BUFFER_CLEANUP_DAYS")) : 7;
|
||||||
this.bufferCleanupService = new BufferCleanupService(cleanupEveryDays, this.logger);
|
this.bufferCleanupService = new BufferCleanupService(cleanupEveryDays, this.logger);
|
||||||
this.forwardUnitService = new ForwardUnitService(this.logger, this.clientManager);
|
this.forwardUnitService = new ForwardUnitService(this.logger, this.clientManager, this.callManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import im.rosetta.client.ClientManager;
|
import im.rosetta.client.ClientManager;
|
||||||
import im.rosetta.packet.Packet26SignalPeer;
|
import im.rosetta.packet.Packet26SignalPeer;
|
||||||
import im.rosetta.packet.runtime.NetworkSignalType;
|
import im.rosetta.packet.runtime.NetworkSignalType;
|
||||||
|
import io.g365sfu.Room;
|
||||||
import io.orprotocol.ProtocolException;
|
import io.orprotocol.ProtocolException;
|
||||||
import io.orprotocol.client.Client;
|
import io.orprotocol.client.Client;
|
||||||
import io.orprotocol.packet.Packet;
|
import io.orprotocol.packet.Packet;
|
||||||
@@ -17,13 +18,13 @@ public class CallManager {
|
|||||||
|
|
||||||
private List<CallSession> callSessions = new ArrayList<>();
|
private List<CallSession> callSessions = new ArrayList<>();
|
||||||
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||||
private static final long RINGING_TIMEOUT = 10 * 1000; // 1 минута
|
private static final long RINGING_TIMEOUT = 30 * 1000;
|
||||||
private ClientManager clientManager;
|
private ClientManager clientManager;
|
||||||
|
|
||||||
|
|
||||||
public CallManager(ClientManager clientManager) {
|
public CallManager(ClientManager clientManager) {
|
||||||
this.clientManager = clientManager;
|
this.clientManager = clientManager;
|
||||||
scheduler.scheduleAtFixedRate(this::cleanupCallSessions, 0, 30, TimeUnit.SECONDS);
|
scheduler.scheduleAtFixedRate(this::cleanupCallSessions, 0, 1, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanupCallSessions() {
|
public void cleanupCallSessions() {
|
||||||
@@ -75,6 +76,15 @@ public class CallManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CallSession getCallSession(Room room) {
|
||||||
|
for (CallSession session : this.callSessions) {
|
||||||
|
if (session.getRoom() != null && session.getRoom().equals(room)) {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isBusy(String publicKey) {
|
public boolean isBusy(String publicKey) {
|
||||||
for (CallSession session : this.callSessions) {
|
for (CallSession session : this.callSessions) {
|
||||||
if (session.clients.containsKey(publicKey)) {
|
if (session.clients.containsKey(publicKey)) {
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ public class CallSession {
|
|||||||
* Клиенты в этом списке не могут принимать другие звонки, так как они уже заняты дозвоном,
|
* Клиенты в этом списке не могут принимать другие звонки, так как они уже заняты дозвоном,
|
||||||
* но они еще не в звонке, так как не приняли звонок
|
* но они еще не в звонке, так как не приняли звонок
|
||||||
*
|
*
|
||||||
* Клиенты удаляются из этого списка, когда они принимают звонок или отклоняют его, тогда они либо переходят в звонок, либо становятся свободными для других звонков
|
* Клиенты удаляются из этого списка, когда они принимают звонок или отклоняют его,
|
||||||
|
* тогда они либо переходят в звонок, либо становятся свободными для других звонков
|
||||||
|
* pk -> время начала дозвона (timestamp в миллисекундах)
|
||||||
*/
|
*/
|
||||||
public HashMap<String, Long> ringing;
|
public HashMap<String, Long> ringing;
|
||||||
/**
|
/**
|
||||||
@@ -48,6 +50,16 @@ public class CallSession {
|
|||||||
this.clients.put(publicKey, client);
|
this.clients.put(publicKey, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверяет, может ли этот публичный ключ выполнять какие-либо действия в рамках этой сессии звонка,
|
||||||
|
* чтобы не допустить выполнение действий от посторонних публичных ключей, которые не участвуют в звонке
|
||||||
|
* @param publicKey Публичный ключ для проверки
|
||||||
|
* @return true, если этот публичный ключ может выполнять действия в рамках этой сессии звонка, false иначе
|
||||||
|
*/
|
||||||
|
public boolean isValidSource(String publicKey) {
|
||||||
|
return this.ringing.containsKey(publicKey) || this.clients.containsKey(publicKey);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Получаем публичный ключ клиента по его сокету, чтобы понимать, кто отправляет сигналы в рамках звонка
|
* Получаем публичный ключ клиента по его сокету, чтобы понимать, кто отправляет сигналы в рамках звонка
|
||||||
* @param client Сокет клиента, для которого нужно получить публичный ключ
|
* @param client Сокет клиента, для которого нужно получить публичный ключ
|
||||||
@@ -70,6 +82,15 @@ public class CallSession {
|
|||||||
return this.joinToken;
|
return this.joinToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void leaveCall(String publicKey) {
|
||||||
|
if(this.clients.containsKey(publicKey)) {
|
||||||
|
this.clients.remove(publicKey);
|
||||||
|
}
|
||||||
|
if(this.ringing.containsKey(publicKey)) {
|
||||||
|
this.ringing.remove(publicKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void addRinging(String publicKey) {
|
public void addRinging(String publicKey) {
|
||||||
this.ringing.put(publicKey, System.currentTimeMillis());
|
this.ringing.put(publicKey, System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,9 +56,10 @@ public class ClientManager {
|
|||||||
* Отправить пакет ВСЕМ АВТОРИЗОВАННЫМ клиентам с публичным ключом publicKey
|
* Отправить пакет ВСЕМ АВТОРИЗОВАННЫМ клиентам с публичным ключом publicKey
|
||||||
* @param publicKey публичный ключ получателя
|
* @param publicKey публичный ключ получателя
|
||||||
* @param packet пакет для отправки
|
* @param packet пакет для отправки
|
||||||
|
* @param exclude клиент, который не должен получать этот пакет, может быть null
|
||||||
* @throws ProtocolException если произошла ошибка при отправке пакета клиенту
|
* @throws ProtocolException если произошла ошибка при отправке пакета клиенту
|
||||||
*/
|
*/
|
||||||
public void sendPacketToAuthorizedPK(String publicKey, Packet packet) throws ProtocolException {
|
public void sendPacketToAuthorizedPK(String publicKey, Packet packet, Client exclude) throws ProtocolException {
|
||||||
Set<Client> clients = this.clientIndexer.getClients(ECIAuthentificate.class, "publicKey", publicKey);
|
Set<Client> clients = this.clientIndexer.getClients(ECIAuthentificate.class, "publicKey", publicKey);
|
||||||
if(clients == null){
|
if(clients == null){
|
||||||
/**
|
/**
|
||||||
@@ -77,12 +78,55 @@ public class ClientManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Отправляем пакет каждому клиенту с таким публичным ключом (то есть всем его авторизованным сессиям/устройствам)
|
* Отправляем пакет каждому клиенту с таким публичным ключом (то есть всем его авторизованным сессиям/устройствам),
|
||||||
|
* исключая клиента exclude
|
||||||
*/
|
*/
|
||||||
|
if(exclude != null && client.equals(exclude)){
|
||||||
|
/**
|
||||||
|
* Этот клиент является исключением, он не должен получать этот пакет
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
client.send(packet);
|
client.send(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Отправить пакет ВСЕМ АВТОРИЗОВАННЫМ клиентам с публичным ключом publicKey
|
||||||
|
* @param publicKey публичный ключ получателя
|
||||||
|
* @param packet пакет для отправки
|
||||||
|
* @throws ProtocolException если произошла ошибка при отправке пакета клиенту
|
||||||
|
*/
|
||||||
|
public void sendPacketToAuthorizedPK(String publicKey, Packet packet) throws ProtocolException {
|
||||||
|
this.sendPacketToAuthorizedPK(publicKey, packet, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Отправить пакет всем клиентам с публичными ключами из списка publicKeys
|
||||||
|
* @param publicKeys список публичных ключей получателей
|
||||||
|
* @param packet пакет для отправки
|
||||||
|
* @param exclude клиент, который не должен получать этот пакет, может быть null
|
||||||
|
* @throws ProtocolException если произошла ошибка при отправке пакета клиенту
|
||||||
|
*/
|
||||||
|
public void sendPacketToAuthorizedPK(List<String> publicKeys, Packet packet, Client exclude) throws ProtocolException {
|
||||||
|
for(String publicKey : publicKeys){
|
||||||
|
this.sendPacketToAuthorizedPK(publicKey, packet, exclude);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Отправить пакет всем клиентам с публичными ключами из списка publicKeys
|
||||||
|
* @param publicKeys список публичных ключей получателей
|
||||||
|
* @param packet пакет для отправки
|
||||||
|
* @throws ProtocolException если произошла ошибка при отправке пакета клиенту
|
||||||
|
*/
|
||||||
|
public void sendPacketToAuthorizedPK(List<String> publicKeys, Packet packet) throws ProtocolException {
|
||||||
|
for(String publicKey : publicKeys){
|
||||||
|
this.sendPacketToAuthorizedPK(publicKey, packet, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Отправить пакет всем клиентам с публичными ключом как у client, кроме клиента client, который является отправителем и не должен получать этот пакет
|
* Отправить пакет всем клиентам с публичными ключом как у client, кроме клиента client, который является отправителем и не должен получать этот пакет
|
||||||
* @param client клиент
|
* @param client клиент
|
||||||
@@ -111,18 +155,6 @@ public class ClientManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Отправить пакет всем клиентам с публичными ключами из списка publicKeys
|
|
||||||
* @param publicKeys список публичных ключей получателей
|
|
||||||
* @param packet пакет для отправки
|
|
||||||
* @throws ProtocolException если произошла ошибка при отправке пакета клиенту
|
|
||||||
*/
|
|
||||||
public void sendPacketToAuthorizedPK(List<String> publicKeys, Packet packet) throws ProtocolException {
|
|
||||||
for(String publicKey : publicKeys){
|
|
||||||
this.sendPacketToAuthorizedPK(publicKey, packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Получить список клиентов по публичному ключу (get PublicKey clients), могут быть неавторизованные клиенты
|
* Получить список клиентов по публичному ключу (get PublicKey clients), могут быть неавторизованные клиенты
|
||||||
* @param publicKey публичный ключ клиента
|
* @param publicKey публичный ключ клиента
|
||||||
|
|||||||
@@ -127,6 +127,13 @@ public class Executor26SignalPeer extends PacketExecutor<Packet26SignalPeer> {
|
|||||||
client.disconnect(Failures.NO_CALL_SESSION);
|
client.disconnect(Failures.NO_CALL_SESSION);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!session.isValidSource(src)) {
|
||||||
|
/**
|
||||||
|
* Клиент не состоит в сессии звонка, отключаем его от сервера, так как он отправляет некорректные данные
|
||||||
|
*/
|
||||||
|
client.disconnect(Failures.DATA_MISSMATCH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Room room = this.fus.createRoom();
|
Room room = this.fus.createRoom();
|
||||||
session.setRoom(room);
|
session.setRoom(room);
|
||||||
session.joinCall(src, client);
|
session.joinCall(src, client);
|
||||||
@@ -134,6 +141,13 @@ public class Executor26SignalPeer extends PacketExecutor<Packet26SignalPeer> {
|
|||||||
room.addParticipant(participant);
|
room.addParticipant(participant);
|
||||||
}
|
}
|
||||||
session.sendPacket(packet, client);
|
session.sendPacket(packet, client);
|
||||||
|
/**
|
||||||
|
* Сбрасываем вызов на всех остальных устройствах пользователя, который принимает звонок,
|
||||||
|
* чтобы он не смог принять или отклонить звонок с другого устройства
|
||||||
|
*/
|
||||||
|
Packet26SignalPeer endCallOtherDevices = new Packet26SignalPeer();
|
||||||
|
endCallOtherDevices.setSignalType(NetworkSignalType.END_CALL);
|
||||||
|
this.clientManager.sendPacketToAuthorizedPK(src, endCallOtherDevices, client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(type == NetworkSignalType.KEY_EXCHANGE){
|
if(type == NetworkSignalType.KEY_EXCHANGE){
|
||||||
@@ -170,12 +184,22 @@ public class Executor26SignalPeer extends PacketExecutor<Packet26SignalPeer> {
|
|||||||
}
|
}
|
||||||
if(session == null) {
|
if(session == null) {
|
||||||
/**
|
/**
|
||||||
* Сессии звонка нет
|
* Сессии звонка нет, скорее всего она была удалена при обрыве RTC Peer Connection,
|
||||||
|
* при срабатывании RTCPeerConnection::close на клиенте раньше, чем клиент отправил сигнал END_CALL
|
||||||
*/
|
*/
|
||||||
client.disconnect(Failures.NO_CALL_SESSION);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Отправляем сигнал окончания звонка всем участникам сессии, кроме отправителя
|
||||||
|
*/
|
||||||
session.sendPacket(packet, client);
|
session.sendPacket(packet, client);
|
||||||
|
/**
|
||||||
|
* Отправляем пакет вызываемым (ringing) пользователям (которые еще не в сессии)
|
||||||
|
*/
|
||||||
|
this.callManager.sendPacketToRinging(session, packet);
|
||||||
|
/**
|
||||||
|
* Удаляем сессию из активных сессий звонков
|
||||||
|
*/
|
||||||
this.callManager.removeSession(session);
|
this.callManager.removeSession(session);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ public enum AttachmentType {
|
|||||||
MESSAGES(1),
|
MESSAGES(1),
|
||||||
FILE(2),
|
FILE(2),
|
||||||
AVATAR(3),
|
AVATAR(3),
|
||||||
CALL(4);
|
CALL(4),
|
||||||
|
VOICE(5),
|
||||||
|
VIDEO_CIRCLE(6);
|
||||||
|
|
||||||
|
|
||||||
private final int code;
|
private final int code;
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import im.rosetta.service.dispatch.runtime.PushType;
|
|||||||
|
|
||||||
public class FCM extends Pusher {
|
public class FCM extends Pusher {
|
||||||
|
|
||||||
|
private boolean isInitialized = false;
|
||||||
|
|
||||||
public FCM() {
|
public FCM() {
|
||||||
initializeFirebase();
|
initializeFirebase();
|
||||||
}
|
}
|
||||||
@@ -39,8 +41,10 @@ public class FCM extends Pusher {
|
|||||||
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
|
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
|
||||||
.build();
|
.build();
|
||||||
FirebaseApp.initializeApp(options);
|
FirebaseApp.initializeApp(options);
|
||||||
|
this.isInitialized = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Failed to initialize Firebase", e);
|
this.isInitialized = false;
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,9 +65,10 @@ public class FCM extends Pusher {
|
|||||||
* Тихий тип уведомления для очистки отправленных уведомлений на устройстве,
|
* Тихий тип уведомления для очистки отправленных уведомлений на устройстве,
|
||||||
* не должен отображаться пользователю, поэтому не задаем звук и ставим contentAvailable для iOS и high priority для Android
|
* не должен отображаться пользователю, поэтому не задаем звук и ставим contentAvailable для iOS и high priority для Android
|
||||||
*/
|
*/
|
||||||
apnsConfig.setAps(Aps.builder().setContentAvailable(true).setSound("default").build());
|
apnsConfig.setAps(Aps.builder().setContentAvailable(true).setMutableContent(true).build());
|
||||||
androidConfig.setPriority(AndroidConfig.Priority.HIGH);
|
androidConfig.setPriority(AndroidConfig.Priority.HIGH);
|
||||||
messageBuilder.setApnsConfig(apnsConfig.build());
|
messageBuilder.setApnsConfig(apnsConfig.build());
|
||||||
|
messageBuilder.setNotification(Notification.builder().setTitle("").setBody("").build());
|
||||||
messageBuilder.setAndroidConfig(androidConfig.build());
|
messageBuilder.setAndroidConfig(androidConfig.build());
|
||||||
break;
|
break;
|
||||||
case PushType.PERSONAL_MESSAGE:
|
case PushType.PERSONAL_MESSAGE:
|
||||||
@@ -93,6 +98,12 @@ public class FCM extends Pusher {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendPush(String token, HashMap<String, String> data) {
|
public void sendPush(String token, HashMap<String, String> data) {
|
||||||
|
if(!this.isInitialized){
|
||||||
|
/**
|
||||||
|
* Firebase не инициализирован, пропускаем отправку уведомлений
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
try{
|
try{
|
||||||
Message message = this.buildMessage(token, data);
|
Message message = this.buildMessage(token, data);
|
||||||
FirebaseMessaging.getInstance().send(message);
|
FirebaseMessaging.getInstance().send(message);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class VoIPApns extends Pusher {
|
|||||||
|
|
||||||
private ApnsClient client;
|
private ApnsClient client;
|
||||||
private String topic;
|
private String topic;
|
||||||
|
private boolean isInitialized = false;
|
||||||
|
|
||||||
public VoIPApns(){
|
public VoIPApns(){
|
||||||
this.initializeApns();
|
this.initializeApns();
|
||||||
@@ -38,13 +39,21 @@ public class VoIPApns extends Pusher {
|
|||||||
.setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST)
|
.setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST)
|
||||||
.setClientCredentials(new File(p12Path), p12Password)
|
.setClientCredentials(new File(p12Path), p12Password)
|
||||||
.build();
|
.build();
|
||||||
|
this.isInitialized = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Failed to init VoIP APNs client", e);
|
this.isInitialized = false;
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendPush(String token, HashMap<String, String> data) {
|
public void sendPush(String token, HashMap<String, String> data) {
|
||||||
|
if(!this.isInitialized) {
|
||||||
|
/**
|
||||||
|
* Нет файла для инициализации APNs клиента, пропускаем отправку VoIP уведомлений
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(data.get("type") != PushType.CALL) {
|
if(data.get("type") != PushType.CALL) {
|
||||||
/**
|
/**
|
||||||
* Для VoIP APNs отправляем уведомления только о входящих звонках
|
* Для VoIP APNs отправляем уведомления только о входящих звонках
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import java.util.concurrent.Executors;
|
|||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import im.rosetta.calls.CallManager;
|
||||||
|
import im.rosetta.calls.CallSession;
|
||||||
import im.rosetta.client.ClientManager;
|
import im.rosetta.client.ClientManager;
|
||||||
import im.rosetta.logger.Logger;
|
import im.rosetta.logger.Logger;
|
||||||
import im.rosetta.logger.enums.Color;
|
import im.rosetta.logger.enums.Color;
|
||||||
@@ -33,10 +35,12 @@ public class ForwardUnitService {
|
|||||||
private Set<SFU> sfuConnections = ConcurrentHashMap.newKeySet();
|
private Set<SFU> sfuConnections = ConcurrentHashMap.newKeySet();
|
||||||
private ClientManager clientManager;
|
private ClientManager clientManager;
|
||||||
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||||
|
private CallManager callManager;
|
||||||
|
|
||||||
public ForwardUnitService(Logger logger, ClientManager clientManager) {
|
public ForwardUnitService(Logger logger, ClientManager clientManager, CallManager callManager) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.clientManager = clientManager;
|
this.clientManager = clientManager;
|
||||||
|
this.callManager = callManager;
|
||||||
this.sfuConnectionsSheduler();
|
this.sfuConnectionsSheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,25 +139,33 @@ public class ForwardUnitService {
|
|||||||
|
|
||||||
public void onPeerDisconnected(DisconnectedPeer disconnectedPeer) throws ProtocolException {
|
public void onPeerDisconnected(DisconnectedPeer disconnectedPeer) throws ProtocolException {
|
||||||
Room room = disconnectedPeer.getRoom();
|
Room room = disconnectedPeer.getRoom();
|
||||||
if(disconnectedPeer.getReason() != DisconnectReason.FAILED){
|
CallSession callSession = this.callManager.getCallSession(room);
|
||||||
|
callSession.leaveCall(disconnectedPeer.getPeerId());
|
||||||
|
|
||||||
|
if(disconnectedPeer.getReason() == DisconnectReason.FAILED){
|
||||||
/**
|
/**
|
||||||
* Если у нас произошло штатное отключение, а не в результате обрыва связи - то не нужно отправлять
|
* Произошло нештатное отключение клиента от сервера SFU, например, из-за сбоя сети
|
||||||
* оппонентам пакеты о том, что участник отключился в результате обрыва связи.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for(String peerId : room.getParticipants()) {
|
|
||||||
/**
|
|
||||||
* Уведомляем все пиры, что соединение с пиром было потеряно
|
|
||||||
*/
|
|
||||||
if(room.getParticipants().size() == 1) {
|
|
||||||
/**
|
|
||||||
* Звонок был завершен, так как в комнате остался только один участник, который не может продолжать звонок в одиночку.
|
|
||||||
*/
|
*/
|
||||||
|
if(callSession.shouldRemove()){
|
||||||
Packet26SignalPeer packet = new Packet26SignalPeer();
|
Packet26SignalPeer packet = new Packet26SignalPeer();
|
||||||
packet.setSignalType(NetworkSignalType.END_CALL_BECAUSE_PEER_DISCONNECTED);
|
packet.setSignalType(NetworkSignalType.END_CALL_BECAUSE_PEER_DISCONNECTED);
|
||||||
this.clientManager.sendPacketToAuthorizedPK(peerId, packet);
|
callSession.sendPacket(packet, null);
|
||||||
|
this.callManager.removeSession(callSession);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(disconnectedPeer.getReason() == DisconnectReason.CLOSED){
|
||||||
|
/**
|
||||||
|
* Клиент намеренно покинул звонок, например, отключился от SFU сервера, так как завершил звонок или вышел из комнаты
|
||||||
|
* (например если клиент отрабатывает выход из звонка по кнопке END не правильно)
|
||||||
|
*/
|
||||||
|
if(callSession.shouldRemove()){
|
||||||
|
Packet26SignalPeer packet = new Packet26SignalPeer();
|
||||||
|
packet.setSignalType(NetworkSignalType.END_CALL);
|
||||||
|
callSession.sendPacket(packet, null);
|
||||||
|
this.callManager.removeSession(callSession);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,4 +157,12 @@ public class Room {
|
|||||||
buffer.flip();
|
buffer.flip();
|
||||||
this.sfu.getConnection().send(buffer);
|
this.sfu.getConnection().send(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
Room room = (Room) obj;
|
||||||
|
return roomId.equals(room.roomId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user