diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonInboundProcessor.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonInboundProcessor.java index 6048325..c27a07c 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonInboundProcessor.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonInboundProcessor.java @@ -17,12 +17,13 @@ import java.util.Map; /** * JsonInboundProcessor — обработка JSON-сообщений. - *. - * 1) Парсит общий пакет (op, requestId,...). + * + * 1) Парсит общий пакет (op, requestId, payload). * 2) По op выбирает класс запроса и хэндлер. - * 3) Маппит JSON → NetRequest через ObjectMapper. - * 4) Вызывает хэндлер, получает NetResponse. - * 5) Собирает JSON-ответ: + * 3) Собирает "плоский" объект: op + requestId + поля из payload. + * 4) Маппит его в NetRequest через ObjectMapper. + * 5) Вызывает хэндлер, получает NetResponse. + * 6) Собирает JSON-ответ: * { * "op": ..., * "requestId": ..., @@ -42,7 +43,9 @@ public final class JsonInboundProcessor { private static final Map> JSON_REQUEST_TYPES = JsonHandlerRegistry.getRequestTypes(); - private JsonInboundProcessor() {} + private JsonInboundProcessor() { + // utility + } public static String processJson(String json, ConnectionContext ctx) { String op = null; @@ -63,7 +66,7 @@ public final class JsonInboundProcessor { // 1. Парсим общий пакет JsonNode root = JSON_MAPPER.readTree(json); - // 2. op и requestId + // 2. op и requestId из корня op = getTextOrNull(root, "op"); requestId = getTextOrNull(root, "requestId"); @@ -92,12 +95,50 @@ public final class JsonInboundProcessor { return writeResponse(err); } - // 3. Маппим JSON → нужный NetRequest - NetRequest request = JSON_MAPPER.treeToValue(root, reqClass); + // 3. Берём payload + JsonNode payloadNode = root.get("payload"); + if (payloadNode == null || payloadNode.isNull()) { + NetExceptionResponse err = NetExceptionResponseFactory.error( + op, + requestId, + WireCodes.Status.BAD_REQUEST, + "NO_PAYLOAD", + "Поле 'payload' отсутствует" + ); + return writeResponse(err); + } + if (!payloadNode.isObject()) { + NetExceptionResponse err = NetExceptionResponseFactory.error( + op, + requestId, + WireCodes.Status.BAD_REQUEST, + "BAD_PAYLOAD", + "Поле 'payload' должно быть объектом" + ); + return writeResponse(err); + } + + // 3.1 Собираем "плоский" объект для маппинга в NetRequest: + // op + requestId + поля из payload + ObjectNode merged = JSON_MAPPER.createObjectNode(); + + // Добавляем op и requestId, чтобы они попали в NetRequest + if (op != null) { + merged.put("op", op); + } + if (requestId != null) { + merged.put("requestId", requestId); + } + + // Добавляем все поля из payload внутрь + merged.setAll((ObjectNode) payloadNode); + + // 4. Маппим в конкретный класс NetRequest + NetRequest request = JSON_MAPPER.treeToValue(merged, reqClass); NetResponse response; - // 4. Трай-кэтч вокруг хэндлера + // 5. Вызываем хэндлер try { response = handler.handle(request, ctx); } catch (Exception handlerError) { @@ -116,7 +157,7 @@ public final class JsonInboundProcessor { if (response.getOp() == null) response.setOp(op); if (response.getRequestId() == null) response.setRequestId(requestId); - // 5. Универсальная сборка ответа + // 6. Универсальная сборка ответа return writeResponse(response); } catch (Exception e) { diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/NetAuthSessionNewStep2Handler.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/NetAuthSessionNewStep2Handler.java index 46917f1..07ab1c4 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/NetAuthSessionNewStep2Handler.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/NetAuthSessionNewStep2Handler.java @@ -166,6 +166,7 @@ public class NetAuthSessionNewStep2Handler implements JsonMessageHandler { ctx.setSessionId(sessionId); ctx.setAuthenticationStatus(ConnectionContext.AUTH_STATUS_USER); + ActiveConnectionsRegistry.getInstance().removeBySessionId(sessionId); // га всякий случай предварительно удаляем что бы точно небыло дублирования активной сессии // Регистрируем это подключение в глобальном реестре активных соединений ActiveConnectionsRegistry.getInstance().register(ctx); diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/NetSessionRefreshHandler.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/NetSessionRefreshHandler.java index 57a34fd..8c63a2a 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/NetSessionRefreshHandler.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/NetSessionRefreshHandler.java @@ -110,6 +110,7 @@ public class NetSessionRefreshHandler implements JsonMessageHandler { ctx.setSessionPwd(sessionPwd); ctx.setAuthenticationStatus(ConnectionContext.AUTH_STATUS_USER); + ActiveConnectionsRegistry.getInstance().removeBySessionId(sessionId); // на всякий случай удаляем что бы точно небыло повторов // Регистрируем это подключение в глобальном реестре активных соединений ActiveConnectionsRegistry.getInstance().register(ctx); } diff --git a/src/TODO.txt b/src/TODO.txt new file mode 100644 index 0000000..8108d57 --- /dev/null +++ b/src/TODO.txt @@ -0,0 +1 @@ +Сделать потом что бы на каждую сессию стояло время последнего подключения и откуда оно было - но видимо это уже в свойства запихивать надо. \ No newline at end of file diff --git a/src/main/java/Test/TestJsonWsClient2.java b/src/main/java/Test/TestJsonWsClient2.java index 1fcd3a5..8e93723 100644 --- a/src/main/java/Test/TestJsonWsClient2.java +++ b/src/main/java/Test/TestJsonWsClient2.java @@ -16,8 +16,10 @@ public class TestJsonWsClient2 { { "op": "SessionRefresh", "requestId": "test-1", - "sessionId": 123, - "sessionPwd": "test-password" + "payload": { + "sessionId": 123, + "sessionPwd": "test-password" + } } """; @@ -25,12 +27,14 @@ public class TestJsonWsClient2 { { "op": "AddUser", "requestId": "test-add-1", - "login": "anya1111", - "loginId": 100211, - "bchId": 4222, - "pubkey0": "PUB0", - "pubkey1": "PUB1", - "bchLimit": 1000000 + "payload": { + "login": "anya1111", + "loginId": 100211, + "bchId": 4222, + "pubkey0": "PUB0", + "pubkey1": "PUB1", + "bchLimit": 1000000 + } } """; @@ -38,7 +42,9 @@ public class TestJsonWsClient2 { { "op": "AuthSessionNewStep1", "requestId": "test-auth-1", - "login": "anya1111" + "payload": { + "login": "anya1111" + } } """; diff --git a/src/main/java/Test/Test_AddUser_FirstAuth.java b/src/main/java/Test/Test_AddUser_FirstAuth.java index d45403a..6658291 100644 --- a/src/main/java/Test/Test_AddUser_FirstAuth.java +++ b/src/main/java/Test/Test_AddUser_FirstAuth.java @@ -64,12 +64,14 @@ public class Test_AddUser_FirstAuth { { "op": "AddUser", "requestId": "test-add-1", - "login": "%s", - "loginId": %d, - "bchId": %d, - "pubkey0": "%s", - "pubkey1": "%s", - "bchLimit": %d + "payload": { + "login": "%s", + "loginId": %d, + "bchId": %d, + "pubkey0": "%s", + "pubkey1": "%s", + "bchLimit": %d + } } """.formatted( TEST_LOGIN, @@ -87,7 +89,9 @@ public class Test_AddUser_FirstAuth { { "op": "AuthSessionNewStep1", "requestId": "test-auth-1", - "login": "%s" + "payload": { + "login": "%s" + } } """.formatted(TEST_LOGIN); } @@ -112,10 +116,12 @@ public class Test_AddUser_FirstAuth { { "op": "AuthSessionNewStep2", "requestId": "test-auth-2", - "loginId": %d, - "sigNum": 0, - "timeMs": %d, - "signatureB64": "%s" + "payload": { + "loginId": %d, + "sigNum": 0, + "timeMs": %d, + "signatureB64": "%s" + } } """.formatted( TEST_LOGIN_ID, diff --git a/src/main/java/Test/Test_SessionRefreshClient.java b/src/main/java/Test/Test_SessionRefreshClient.java index 9c63238..6b286aa 100644 --- a/src/main/java/Test/Test_SessionRefreshClient.java +++ b/src/main/java/Test/Test_SessionRefreshClient.java @@ -40,8 +40,10 @@ public class Test_SessionRefreshClient { { "op": "SessionRefresh", "requestId": "test-session-refresh-1", - "sessionId": %d, - "sessionPwd": "%s" + "payload": { + "sessionId": %d, + "sessionPwd": "%s" + } } """.formatted(SESSION_ID, SESSION_PWD); } @@ -49,7 +51,6 @@ public class Test_SessionRefreshClient { private static class ClientListener implements Listener { private final CountDownLatch latch; - private boolean sent = false; ClientListener(CountDownLatch latch) { this.latch = latch; @@ -67,7 +68,6 @@ public class Test_SessionRefreshClient { System.out.println("📤 Отправляем SessionRefresh:"); System.out.println(json); webSocket.sendText(json, true); - sent = true; Listener.super.onOpen(webSocket); } diff --git a/src/main/java/server/ws/WsServer.java b/src/main/java/server/ws/WsServer.java index db22130..3d03b9b 100644 --- a/src/main/java/server/ws/WsServer.java +++ b/src/main/java/server/ws/WsServer.java @@ -21,11 +21,15 @@ public final class WsServer { AppConfig config = AppConfig.getInstance(); int port = 7070; try { - port = Integer.parseInt(config.getParam("server.port"),7070); + String portStr = config.getParam("server.port"); + if (portStr != null && !portStr.isBlank()) { + port = Integer.parseInt(portStr.trim()); + } } catch (Exception e) { - log.info("Установите параметр server.port в файле настроек"); + log.info("Не удалось прочитать параметр server.port, используем порт по умолчанию {}", port); } + Server server = new Server(port); ServletContextHandler context = new ServletContextHandler();