diff --git a/src/main/java/im/rosetta/Boot.java b/src/main/java/im/rosetta/Boot.java index 4cbdfcc..2e339e5 100644 --- a/src/main/java/im/rosetta/Boot.java +++ b/src/main/java/im/rosetta/Boot.java @@ -200,7 +200,7 @@ public class Boot { this.packetManager.registerExecutor(17, new Executor17GroupCreate()); this.packetManager.registerExecutor(18, new Executor18GroupInfo()); this.packetManager.registerExecutor(19, new Executor19GroupInviteInfo()); - this.packetManager.registerExecutor(20, new Executor20GroupJoin()); + this.packetManager.registerExecutor(20, new Executor20GroupJoin(this.packetManager)); this.packetManager.registerExecutor(21, new Executor21GroupLeave()); this.packetManager.registerExecutor(22, new Executor22GroupBan()); this.packetManager.registerExecutor(24, new Executor24DeviceResolve(this.clientManager, this.eventManager, this.packetManager)); diff --git a/src/main/java/im/rosetta/client/ClientManager.java b/src/main/java/im/rosetta/client/ClientManager.java index b4c8112..0ec7650 100644 --- a/src/main/java/im/rosetta/client/ClientManager.java +++ b/src/main/java/im/rosetta/client/ClientManager.java @@ -53,7 +53,7 @@ public class ClientManager { } /** - * Отправить пакет всем АВТОРИЗОВАННЫМ клиентам с публичным ключом publicKey + * Отправить пакет ВСЕМ АВТОРИЗОВАННЫМ клиентам с публичным ключом publicKey * @param publicKey публичный ключ получателя * @param packet пакет для отправки * @throws ProtocolException если произошла ошибка при отправке пакета клиенту @@ -83,6 +83,34 @@ public class ClientManager { } } + /** + * Отправить пакет всем клиентам с публичными ключом как у client, кроме клиента client, который является отправителем и не должен получать этот пакет + * @param client клиент + * @param packet пакет для отправки + * @throws ProtocolException + */ + public void retranslate(Client client, Packet packet) throws ProtocolException{ + ECIAuthentificate eciAuthentificate = client.getTag(ECIAuthentificate.class); + HashSet clients = this.clientIndexer + .getClients(ECIAuthentificate.class, "publicKey", eciAuthentificate.getPublicKey()); + if(clients == null){ + /** + * Нет авторизованных сессий с таким публичным ключом + */ + return; + } + for(Client c : clients){ + /** + * Проходим по всем устройствам с таким публичным ключом и ретранслируем им пакет, кроме того устройства что + * отправило пакет + */ + if(c.equals(client)){ + continue; + } + c.send(packet); + } + } + /** * Отправить пакет всем клиентам с публичными ключами из списка publicKeys * @param publicKeys список публичных ключей получателей diff --git a/src/main/java/im/rosetta/database/repository/GroupRepository.java b/src/main/java/im/rosetta/database/repository/GroupRepository.java index 3de8f56..2173234 100644 --- a/src/main/java/im/rosetta/database/repository/GroupRepository.java +++ b/src/main/java/im/rosetta/database/repository/GroupRepository.java @@ -39,12 +39,9 @@ public class GroupRepository extends Repository { * @param groupId ID группы * @param creatorPublicKey публичный ключ создателя группы, который будет единственным участником группы при создании */ - public void createGroup(String groupId, String creatorPublicKey) { + public void createGroup(String groupId) { Group group = new Group(); group.setGroupId(groupId); - List membersPublicKeys = new ArrayList<>(); - membersPublicKeys.add(creatorPublicKey); - group.setMembersPublicKeys(membersPublicKeys); this.save(group); } diff --git a/src/main/java/im/rosetta/executors/Executor17GroupCreate.java b/src/main/java/im/rosetta/executors/Executor17GroupCreate.java index e85dfae..23de798 100644 --- a/src/main/java/im/rosetta/executors/Executor17GroupCreate.java +++ b/src/main/java/im/rosetta/executors/Executor17GroupCreate.java @@ -25,7 +25,7 @@ public class Executor17GroupCreate extends PacketExecutor { return; } String groupId = RandomUtil.randomString(16); - this.groupRepository.createGroup(groupId, eciAuthentificate.getPublicKey()); + this.groupRepository.createGroup(groupId); /** * Отправляем клиенту ид созданной группы */ diff --git a/src/main/java/im/rosetta/executors/Executor20GroupJoin.java b/src/main/java/im/rosetta/executors/Executor20GroupJoin.java index 6f89877..b258bda 100644 --- a/src/main/java/im/rosetta/executors/Executor20GroupJoin.java +++ b/src/main/java/im/rosetta/executors/Executor20GroupJoin.java @@ -3,17 +3,25 @@ package im.rosetta.executors; import im.rosetta.Failures; import im.rosetta.client.tags.ECIAuthentificate; import im.rosetta.database.entity.Group; +import im.rosetta.database.repository.BufferRepository; import im.rosetta.database.repository.GroupRepository; import im.rosetta.packet.Packet20GroupJoin; import im.rosetta.packet.runtime.NetworkGroupStatus; - +import im.rosetta.service.services.BufferService; import io.orprotocol.ProtocolException; import io.orprotocol.client.Client; import io.orprotocol.packet.PacketExecutor; +import io.orprotocol.packet.PacketManager; public class Executor20GroupJoin extends PacketExecutor { private final GroupRepository groupRepository = new GroupRepository(); + private final BufferRepository bufferRepository = new BufferRepository(); + private final BufferService bufferService; + + public Executor20GroupJoin(PacketManager packetManager) { + this.bufferService = new BufferService(bufferRepository, packetManager); + } @Override public void onPacketReceived(Packet20GroupJoin packet, Client client) throws Exception, ProtocolException { @@ -53,12 +61,21 @@ public class Executor20GroupJoin extends PacketExecutor { client.send(packet); return; } - + /** + * Все проверки пройдены, клиент может вступить в группу + */ + packet.setStatus(NetworkGroupStatus.JOINED); + /** + * Кладем пакет в буфер для будущей синхронизации + */ + this.bufferService.pushPacketToBuffer("server", eciAuthentificate.getPublicKey(), packet); /** * Добавляем клиента в группу и возвращаем клиенту статус JOINED */ this.groupRepository.addMemberToGroup(groupId, eciAuthentificate.getPublicKey()); - packet.setStatus(NetworkGroupStatus.JOINED); + /** + * Возвращаем клиенту ответный пакет с статусом JOINED + */ client.send(packet); } diff --git a/src/main/java/im/rosetta/packet/Packet20GroupJoin.java b/src/main/java/im/rosetta/packet/Packet20GroupJoin.java index 1abbcc1..599070d 100644 --- a/src/main/java/im/rosetta/packet/Packet20GroupJoin.java +++ b/src/main/java/im/rosetta/packet/Packet20GroupJoin.java @@ -14,11 +14,20 @@ public class Packet20GroupJoin extends Packet { private String groupId; private NetworkGroupStatus status; + /** + * Строка группы, которая содержит информацию о группе, такую как ее название, описание и ключ + * Строка зашифрована обратимым шифрованием, где ключом выступает - реальный приватный ключ + * входящего в группу клиента. Нужно это для будущей синхронзации, так как клиенту на его другом + * устройстве нужно получить ключ группы и ее информацию. Сервер расшифровать эту строку не может. Эту + * строку может расшифровать только клиент, так как она зашифрована его приватным ключом + */ + private String groupString; @Override public void read(Stream stream) { this.groupId = stream.readString(); this.status = NetworkGroupStatus.fromCode(stream.readInt8()); + this.groupString = stream.readString(); } @Override @@ -27,6 +36,7 @@ public class Packet20GroupJoin extends Packet { stream.writeInt16(this.packetId); stream.writeString(this.groupId); stream.writeInt8(this.status.getCode()); + stream.writeString(this.groupString); return stream; } @@ -62,4 +72,20 @@ public class Packet20GroupJoin extends Packet { this.status = status; } + /** + * Получить строку группы, которая содержит информацию о группе, такую как ее название, описание и ключ + * @return строка группы + */ + public String getGroupString() { + return groupString; + } + + /** + * Установить строку группы, которая содержит информацию о группе, такую как ее название, описание и ключ + * @param groupString строка группы + */ + public void setGroupString(String groupString) { + this.groupString = groupString; + } + } diff --git a/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java b/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java index 0644ebd..2141f9e 100644 --- a/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java +++ b/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java @@ -1,6 +1,5 @@ package im.rosetta.service.dispatch; -import java.util.HashSet; import java.util.List; import im.rosetta.client.ClientManager; @@ -57,7 +56,21 @@ public class MessageDispatcher { return; } /** - * Отправляем всем участникам группы, кроме отправителя этот пакет, попутно не забывая проверить, а не один ли он в группе + * Ретранслируем сообщение ВСЕМ авторизованным сессиям отправителя КРОМЕ текущей, + * чтобы синхронизировать отправленные сообщения + */ + if(!(packet instanceof Packet11Typeing)){ + /** + * Если это пакет печати его не обязательно кэшировать, так как он нужен только + * для отображения статуса печати в реальном времени + * Кладем пакет в буфер для будущей синхронизации и на случай если кто-то из участников оффлайн, + * в toPublicKey при отправке в группу у нас находится #group:groupId + */ + this.bufferService.pushPacketToBuffer(fromPublicKey, toPublicKey.replace("#group:", ""), packet); + this.clientManager.retranslate(client, packet); + } + /** + * Отправляем всем участникам группы, кроме отправителя, попутно проверяем, а не один ли он в группе */ groupMembersPublicKeys.remove(eciAuthentificate.getPublicKey()); if(groupMembersPublicKeys.isEmpty()){ @@ -67,20 +80,10 @@ public class MessageDispatcher { */ return; } - this.clientManager.sendPacketToAuthorizedPK(groupMembersPublicKeys, packet); - - if(packet instanceof Packet11Typeing){ - /** - * Если это пакет печати его не обязательно кэшировать, так как он нужен только - * для отображения статуса печати в реальном времени - */ - return; - } /** - * Кладем пакет в буфер для будущей синхронизации и на случай если кто-то из участников оффлайн, - * в toPublicKey при отправке в группу у нас находится #group:groupId + * Отправляем сообщение всем, кто в беседе */ - this.bufferService.pushPacketToBuffer(fromPublicKey, toPublicKey.replace("#group:", ""), packet); + this.clientManager.sendPacketToAuthorizedPK(groupMembersPublicKeys, packet); } /** @@ -94,6 +97,12 @@ public class MessageDispatcher { public void sendPeer(PacketBaseDialog packet, Client client, boolean bufferizationNeed) throws ProtocolException { String fromPublicKey = packet.getFromPublicKey(); String toPublicKey = packet.getToPublicKey(); + + /** + * Ретранслируем сообщение ВСЕМ авторизованным сессиям отправителя КРОМЕ текущей, + * чтобы синхронизировать отправленные сообщения + */ + this.clientManager.retranslate(client, packet); this.clientManager.sendPacketToAuthorizedPK(toPublicKey, packet); if(!bufferizationNeed){ @@ -107,11 +116,6 @@ public class MessageDispatcher { * Сохраняем сообщение в буфер на случай если получатель офлайн, или нам нужна будет синхронизация сообщений для получателя */ this.bufferService.pushPacketToBuffer(fromPublicKey, toPublicKey, packet); - - /** - * Ретранслируем сообщение всем авторизованным сессиям отправителя, чтобы синхронизировать отправленные сообщения - */ - this.retranslate(packet, client); } /** @@ -127,34 +131,4 @@ public class MessageDispatcher { 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 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); - } - } - - }