diff --git a/VERSION.properties b/VERSION.properties index d9abe65..4687b44 100644 --- a/VERSION.properties +++ b/VERSION.properties @@ -1,2 +1,2 @@ -client.version=1.2.35 -server.version=1.2.29 +client.version=1.2.36 +server.version=1.2.30 diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java index da8225a..58233ee 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java @@ -60,7 +60,6 @@ import server.logic.ws_protocol.JSON.handlers.connections.Net_ListContacts_Handl import server.logic.ws_protocol.JSON.handlers.connections.entyties.Net_GetUserConnectionsGraph_Request; import server.logic.ws_protocol.JSON.handlers.connections.entyties.Net_AddCloseFriend_Request; import server.logic.ws_protocol.JSON.handlers.connections.entyties.Net_ListContacts_Request; -import server.logic.ws_protocol.JSON.messages.Net_AckIncomingMessage_Handler; import server.logic.ws_protocol.JSON.messages.Net_AckSessionDelivery_Handler; import server.logic.ws_protocol.JSON.messages.Net_CallInviteBroadcast_Handler; import server.logic.ws_protocol.JSON.messages.Net_CallSignalToSession_Handler; @@ -70,7 +69,6 @@ import server.logic.ws_protocol.JSON.messages.Net_SendMessagePair_Handler; import server.logic.ws_protocol.JSON.messages.Net_SendTestWebPush_Handler; import server.logic.ws_protocol.JSON.messages.Net_UpsertPushToken_Handler; import server.logic.ws_protocol.JSON.messages.entyties.Net_AckSessionDelivery_Request; -import server.logic.ws_protocol.JSON.messages.entyties.Net_AckIncomingMessage_Request; import server.logic.ws_protocol.JSON.messages.entyties.Net_CallInviteBroadcast_Request; import server.logic.ws_protocol.JSON.messages.entyties.Net_CallSignalToSession_Request; import server.logic.ws_protocol.JSON.messages.entyties.Net_ReceiveIncomingMessage_Request; @@ -145,7 +143,6 @@ public final class JsonHandlerRegistry { Map.entry("SendMessagePair", new Net_SendMessagePair_Handler()), Map.entry("ReceiveOutcomingMessage", new Net_SendMessagePair_Handler()), Map.entry("ReceiveIncomingMessage", new Net_ReceiveIncomingMessage_Handler()), - Map.entry("AckIncomingMessage", new Net_AckIncomingMessage_Handler()), Map.entry("AckSessionDelivery", new Net_AckSessionDelivery_Handler()), Map.entry("CallInviteBroadcast", new Net_CallInviteBroadcast_Handler()), Map.entry("CallSignalToSession", new Net_CallSignalToSession_Handler()), @@ -202,7 +199,6 @@ public final class JsonHandlerRegistry { Map.entry("SendMessagePair", Net_SendMessagePair_Request.class), Map.entry("ReceiveOutcomingMessage", Net_SendMessagePair_Request.class), Map.entry("ReceiveIncomingMessage", Net_ReceiveIncomingMessage_Request.class), - Map.entry("AckIncomingMessage", Net_AckIncomingMessage_Request.class), Map.entry("AckSessionDelivery", Net_AckSessionDelivery_Request.class), Map.entry("CallInviteBroadcast", Net_CallInviteBroadcast_Request.class), Map.entry("CallSignalToSession", Net_CallSignalToSession_Request.class), diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/Net_AckIncomingMessage_Handler.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/Net_AckIncomingMessage_Handler.java deleted file mode 100644 index 90b9abc..0000000 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/Net_AckIncomingMessage_Handler.java +++ /dev/null @@ -1,29 +0,0 @@ -package server.logic.ws_protocol.JSON.messages; - -import server.logic.ws_protocol.JSON.ConnectionContext; -import server.logic.ws_protocol.JSON.entyties.Net_Request; -import server.logic.ws_protocol.JSON.entyties.Net_Response; -import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; -import server.logic.ws_protocol.JSON.messages.entyties.Net_AckIncomingMessage_Request; -import server.logic.ws_protocol.JSON.messages.entyties.Net_AckIncomingMessage_Response; -import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory; -import server.logic.ws_protocol.WireCodes; - -public class Net_AckIncomingMessage_Handler implements JsonMessageHandler { - @Override - public Net_Response handle(Net_Request baseRequest, ConnectionContext ctx) { - Net_AckIncomingMessage_Request req = (Net_AckIncomingMessage_Request) baseRequest; - if (ctx == null || !ctx.isAuthenticatedUser()) { - return NetExceptionResponseFactory.error(req, WireCodes.Status.UNVERIFIED, "NOT_AUTHENTICATED", "Требуется авторизация"); - } - if (req.getEventId() != null && !req.getEventId().isBlank()) { - DeliveryTracker.getInstance().ack(req.getEventId()); - } - - Net_AckIncomingMessage_Response resp = new Net_AckIncomingMessage_Response(); - resp.setOp(req.getOp()); - resp.setRequestId(req.getRequestId()); - resp.setStatus(WireCodes.Status.OK); - return resp; - } -} diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/entyties/Net_AckIncomingMessage_Request.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/entyties/Net_AckIncomingMessage_Request.java deleted file mode 100644 index 4ceec01..0000000 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/entyties/Net_AckIncomingMessage_Request.java +++ /dev/null @@ -1,13 +0,0 @@ -package server.logic.ws_protocol.JSON.messages.entyties; - -import server.logic.ws_protocol.JSON.entyties.Net_Request; - -public class Net_AckIncomingMessage_Request extends Net_Request { - private String eventId; - private String messageId; - - public String getEventId() { return eventId; } - public void setEventId(String eventId) { this.eventId = eventId; } - public String getMessageId() { return messageId; } - public void setMessageId(String messageId) { this.messageId = messageId; } -} diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/entyties/Net_AckIncomingMessage_Response.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/entyties/Net_AckIncomingMessage_Response.java deleted file mode 100644 index c8b8906..0000000 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/messages/entyties/Net_AckIncomingMessage_Response.java +++ /dev/null @@ -1,6 +0,0 @@ -package server.logic.ws_protocol.JSON.messages.entyties; - -import server.logic.ws_protocol.JSON.entyties.Net_Response; - -public class Net_AckIncomingMessage_Response extends Net_Response { -} diff --git a/Логика_доставки_почты.md b/Логика_доставки_почты.md index da6192c..2573680 100644 --- a/Логика_доставки_почты.md +++ b/Логика_доставки_почты.md @@ -16,6 +16,23 @@ 5. Если пара реально добавилась в БД, сервер запускает realtime-доставку в активные сессии целевых пользователей. 6. Если это дубль, дальнейшая доставка не выполняется (повтор не разгоняется). +## Как сообщение доходит до клиента (WS + WebPush) +1. После успешной записи сервер пытается доставить сообщение во все активные сессии `targetLogin`. +2. Для каждой сессии сервер сначала создаёт/проверяет запись доставки в `signed_message_session_delivery` (pending). +3. Если сессия онлайн, сервер шлёт `SignedMessageArrived` по WebSocket. +4. Если сессия офлайн и тип сообщения входящий текст (`TYPE_INCOMING_TEXT`), сервер пробует WebPush (если у сессии сохранены `endpoint/p256dh/auth`). +5. При следующем логине/переподключении сервер дочитывает pending-сообщения и повторно отправляет их в эту сессию как backlog. + +## Подтверждение доставки (ACK) +- Используется метод `AckSessionDelivery`. +- Клиент отправляет ACK после обработки `SignedMessageArrived` с `messageKey`. +- Сервер помечает `(messageKey, sessionId)` как `delivered=1`, и это сообщение перестаёт быть pending для этой сессии. + +### Важно про безопасность ACK +- `AckSessionDelivery` требует авторизованную WS-сессию (`ctx.isAuthenticatedUser()`). +- `sessionId` берётся сервером из текущего `ConnectionContext`, а не из payload запроса. +- Поэтому подтвердить доставку «просто зная messageKey/sessionId» без авторизованной сессии нельзя. + ## Почему допускаются дубли сети - В модели с несколькими серверами возможны повторные пересылки одного и того же сообщения. - Дедупликация делается на уровне БД по ключам записи.