Files
rosetta-wss/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java

148 lines
7.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package im.rosetta.service.dispatch;
import java.util.HashSet;
import java.util.List;
import im.rosetta.client.ClientManager;
import im.rosetta.client.tags.ECIAuthentificate;
import im.rosetta.database.repository.BufferRepository;
import im.rosetta.database.repository.GroupRepository;
import im.rosetta.packet.base.PacketBaseDialog;
import im.rosetta.service.services.BufferService;
import io.orprotocol.ProtocolException;
import io.orprotocol.client.Client;
import io.orprotocol.packet.PacketManager;
/**
* Диспетчер сообщений, который отвечает за отправку сообщений получателям, а так же за сохранение сообщений в буфер для офлайн получателей и для синхронизации
* Такой диспетчер нужен для того, чтобы не загромождать логику обработчиков сообщений, а так же для того, чтобы
* централизовать логику отправки сообщений и сохранения их в буфер
* Например, при отправке группового сообщения, диспетчер сам достает участников группы и
* отправляет сообщение каждому участнику, а так же сохраняет сообщение в буфер для каждого участника, который офлайн
*/
public class MessageDispatcher {
private final GroupRepository groupRepository = new GroupRepository();
private final ClientManager clientManager;
private final BufferRepository bufferRepository = new BufferRepository();
private final BufferService bufferService;
public MessageDispatcher(ClientManager clientManager, PacketManager packetManager) {
this.clientManager = clientManager;
this.bufferService = new BufferService(bufferRepository, packetManager);
}
/**
* Отправляет групповое сообщение всем участникам группы, кроме отправителя
* @param packet пакет с групповым сообщением
*/
public void sendGroup(PacketBaseDialog packet, Client client, ECIAuthentificate eciAuthentificate) throws ProtocolException {
String toPublicKey = packet.getToPublicKey();
List<String> groupMembersPublicKeys = this.groupRepository.findGroupMembers(toPublicKey.replace("#group:", ""));
if(groupMembersPublicKeys.isEmpty()){
/**
* Если группа не найдена или в группе нет участников, то в такую отправить
* сообщение нельзя, ничего не делаем
*/
return;
}
if(!groupMembersPublicKeys.contains(eciAuthentificate.getPublicKey())){
/**
* Если отправитель не является участником группы, то он не может отправлять
* сообщения в эту группу
*/
return;
}
/**
* Отправляем всем участникам группы, кроме отправителя этот пакет, попутно не забывая проверить, а не один ли он в группе
*/
groupMembersPublicKeys.remove(eciAuthentificate.getPublicKey());
if(groupMembersPublicKeys.isEmpty()){
/**
* Если отправитель был единственным участником группы, то отправлять сообщение некуда,
* не кикаем пользователя
*/
return;
}
this.clientManager.sendPacketToAuthorizedPK(groupMembersPublicKeys, packet);
//TODO: Сохранить сообщение в буфер для группы, чтобы группы тоже синхронизировались
}
/**
* Отправляет личное сообщение получателю
* @param packet пакет с личным сообщением
* @param client клиент отправляющий пакет
* @param bufferizationNeed флаг указывающий на то, что сообщение нужно буфферизировать,
* чтобы доставить пользователям если они не онлайн, если указать false то этот пакет получит
* только пользователь который были в сети
*/
public void sendPeer(PacketBaseDialog packet, Client client, boolean bufferizationNeed) throws ProtocolException {
String fromPublicKey = packet.getFromPublicKey();
String toPublicKey = packet.getToPublicKey();
this.clientManager.sendPacketToAuthorizedPK(toPublicKey, packet);
if(!bufferizationNeed){
/**
* Указан флаг, что буферизация не нужна, сообщения с этим флагом не будут доставлены если
* оппонент оффлайн
*/
return;
}
/**
* Сохраняем сообщение в буфер на случай если получатель офлайн, или нам нужна будет синхронизация сообщений для получателя
*/
this.bufferService.pushPacketToBuffer(fromPublicKey, toPublicKey, packet);
/**
* Ретранслируем сообщение всем авторизованным сессиям отправителя, чтобы синхронизировать отправленные сообщения
*/
this.retranslate(packet, client);
}
/**
* Отправляет личное сообщение получателю с буферизацией
* @param packet пакет сообщения
* @param client клиент отправляющий пакет
* @throws ProtocolException
*/
public void sendPeer(PacketBaseDialog packet, Client client) throws ProtocolException {
/**
* По умолчанию буферизация включена, чтобы не терять сообщения
*/
this.sendPeer(packet, client, true);
}
/**
* Сообщает всем авторизованным сессиям отправителя о том, что он отправил сообщения,
* для того чтобы синхронизировать отправленные сообщения на всех устройствах отправителя
* @param packet пакет сообщения
* @param client клиент отправляющий пакет
* @throws ProtocolException
*/
public void retranslate(PacketBaseDialog packet, Client client) throws ProtocolException {
ECIAuthentificate eciAuthentificate = client.getTag(ECIAuthentificate.class);
HashSet<Client> clients = this.clientManager.getClientIndexer()
.getClients(ECIAuthentificate.class, "publicKey", eciAuthentificate.getPublicKey());
if(clients == null){
/**
* Нет авторизованных сессий с таким публичным ключом
*/
return;
}
for(Client c : clients){
/**
* Проходим по всем устройствам с таким публичным ключом и ретранслируем им пакет, кроме того устройства что
* отправило пакет
*/
if(c.equals(client)){
continue;
}
c.send(packet);
}
}
}