SHA256
Звонки: WebPush incoming/stop, actions и TTL; обновлена логика
This commit is contained in:
+52
-13
@@ -9,14 +9,14 @@ 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_CallInviteBroadcast_Request;
|
||||
import server.logic.ws_protocol.JSON.messages.entyties.Net_CallInviteBroadcast_Response;
|
||||
import server.logic.ws_protocol.JSON.push.FcmPushSender;
|
||||
import server.logic.ws_protocol.JSON.push.WebPushSender;
|
||||
import server.logic.ws_protocol.JSON.push.WsEventSender;
|
||||
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
|
||||
import server.logic.ws_protocol.JSON.utils.NetIdGenerator;
|
||||
import server.logic.ws_protocol.WireCodes;
|
||||
import shine.db.dao.PushTokensDAO;
|
||||
import shine.db.dao.ActiveSessionsDAO;
|
||||
import shine.db.dao.SolanaUsersDAO;
|
||||
import shine.db.entities.PushTokenEntry;
|
||||
import shine.db.entities.ActiveSessionEntry;
|
||||
import shine.db.entities.SolanaUserEntry;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -26,6 +26,7 @@ import java.util.Set;
|
||||
public class Net_CallInviteBroadcast_Handler implements JsonMessageHandler {
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
private static final int TYPE_INVITE = 100;
|
||||
private static final long PUSH_CALL_TTL_MS = 10_000L;
|
||||
|
||||
@Override
|
||||
public Net_Response handle(Net_Request baseRequest, ConnectionContext ctx) throws Exception {
|
||||
@@ -49,12 +50,13 @@ public class Net_CallInviteBroadcast_Handler implements JsonMessageHandler {
|
||||
String from = ctx.getLogin();
|
||||
String to = targetUser.getLogin();
|
||||
long timeMs = System.currentTimeMillis();
|
||||
long expiresAtMs = timeMs + PUSH_CALL_TTL_MS;
|
||||
|
||||
Set<ConnectionContext> activeSessions = ActiveConnectionsRegistry.getInstance().getByLogin(to);
|
||||
List<PushTokenEntry> tokens = PushTokensDAO.getInstance().listByLogin(to);
|
||||
List<ActiveSessionEntry> allTargetSessions = ActiveSessionsDAO.getInstance().getByLogin(to);
|
||||
|
||||
int wsDelivered = 0;
|
||||
int fcmDelivered = 0;
|
||||
int webPushDelivered = 0;
|
||||
Set<String> activeSessionIds = new HashSet<>();
|
||||
|
||||
for (ConnectionContext targetCtx : activeSessions) {
|
||||
@@ -74,14 +76,31 @@ public class Net_CallInviteBroadcast_Handler implements JsonMessageHandler {
|
||||
if (sent) wsDelivered++;
|
||||
}
|
||||
|
||||
for (PushTokenEntry token : tokens) {
|
||||
boolean pushed = FcmPushSender.sendNotification(
|
||||
token.getToken(),
|
||||
"Входящий звонок",
|
||||
from + " пытается дозвониться",
|
||||
callId
|
||||
for (ActiveSessionEntry session : allTargetSessions) {
|
||||
String sessionId = String.valueOf(session.getSessionId() == null ? "" : session.getSessionId()).trim();
|
||||
if (!sessionId.isBlank() && activeSessionIds.contains(sessionId)) {
|
||||
continue;
|
||||
}
|
||||
if (isBlank(session.getPushEndpoint()) || isBlank(session.getPushP256dhKey()) || isBlank(session.getPushAuthKey())) {
|
||||
continue;
|
||||
}
|
||||
String payload = "{\"kind\":\"incoming_call\""
|
||||
+ ",\"title\":\"SHiNE: входящий звонок\""
|
||||
+ ",\"text\":\"Вам звонит " + jsonEscape(from) + "\""
|
||||
+ ",\"fromLogin\":\"" + jsonEscape(from) + "\""
|
||||
+ ",\"fromSessionId\":\"" + jsonEscape(ctx.getSessionId()) + "\""
|
||||
+ ",\"toLogin\":\"" + jsonEscape(to) + "\""
|
||||
+ ",\"callId\":\"" + jsonEscape(callId) + "\""
|
||||
+ ",\"sentAtMs\":" + timeMs
|
||||
+ ",\"expiresAtMs\":" + expiresAtMs
|
||||
+ "}";
|
||||
boolean pushed = WebPushSender.sendBase64Payload(
|
||||
session.getPushEndpoint(),
|
||||
session.getPushP256dhKey(),
|
||||
session.getPushAuthKey(),
|
||||
payload
|
||||
);
|
||||
if (pushed) fcmDelivered++;
|
||||
if (pushed) webPushDelivered++;
|
||||
}
|
||||
|
||||
Net_CallInviteBroadcast_Response resp = new Net_CallInviteBroadcast_Response();
|
||||
@@ -90,7 +109,27 @@ public class Net_CallInviteBroadcast_Handler implements JsonMessageHandler {
|
||||
resp.setStatus(WireCodes.Status.OK);
|
||||
resp.setCallId(callId);
|
||||
resp.setDeliveredWsSessions(wsDelivered);
|
||||
resp.setDeliveredFcmSessions(fcmDelivered);
|
||||
resp.setDeliveredFcmSessions(webPushDelivered);
|
||||
resp.setDeliveredWebPushSessions(webPushDelivered);
|
||||
return resp;
|
||||
}
|
||||
|
||||
private boolean isBlank(String s) {
|
||||
return s == null || s.isBlank();
|
||||
}
|
||||
|
||||
private static String jsonEscape(String s) {
|
||||
if (s == null) return "";
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c == '\\') out.append("\\\\");
|
||||
else if (c == '"') out.append("\\\"");
|
||||
else if (c == '\n') out.append("\\n");
|
||||
else if (c == '\r') out.append("\\r");
|
||||
else if (c == '\t') out.append("\\t");
|
||||
else out.append(c);
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
|
||||
+96
-12
@@ -9,18 +9,25 @@ 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_CallSignalToSession_Request;
|
||||
import server.logic.ws_protocol.JSON.messages.entyties.Net_CallSignalToSession_Response;
|
||||
import server.logic.ws_protocol.JSON.push.WebPushSender;
|
||||
import server.logic.ws_protocol.JSON.push.WsEventSender;
|
||||
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
|
||||
import server.logic.ws_protocol.JSON.utils.NetIdGenerator;
|
||||
import server.logic.ws_protocol.WireCodes;
|
||||
import shine.db.dao.ActiveSessionsDAO;
|
||||
import shine.db.dao.SolanaUsersDAO;
|
||||
import shine.db.entities.ActiveSessionEntry;
|
||||
import shine.db.entities.SolanaUserEntry;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class Net_CallSignalToSession_Handler implements JsonMessageHandler {
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
private static final int TYPE_ACCEPT = 120;
|
||||
private static final int TYPE_DECLINE_BUSY = 130;
|
||||
private static final int TYPE_TIMEOUT = 140;
|
||||
private static final int TYPE_HANGUP = 150;
|
||||
|
||||
@Override
|
||||
@@ -72,7 +79,34 @@ public class Net_CallSignalToSession_Handler implements JsonMessageHandler {
|
||||
boolean delivered = WsEventSender.sendEvent(targetCtx, "IncomingCallSignal", eventId, payload);
|
||||
|
||||
if (type == TYPE_ACCEPT) {
|
||||
notifyAcceptedOnOtherSessions(ctx, callId);
|
||||
notifyStopOnOtherSessions(
|
||||
ctx.getLogin(),
|
||||
ctx.getSessionId(),
|
||||
ctx.getLogin(),
|
||||
ctx.getSessionId(),
|
||||
callId,
|
||||
"accepted_on_other_device"
|
||||
);
|
||||
}
|
||||
|
||||
if (type == TYPE_DECLINE_BUSY || type == TYPE_TIMEOUT || type == TYPE_HANGUP) {
|
||||
String reason = "terminal_call_signal_" + type;
|
||||
notifyStopOnOtherSessions(
|
||||
ctx.getLogin(),
|
||||
ctx.getSessionId(),
|
||||
ctx.getLogin(),
|
||||
ctx.getSessionId(),
|
||||
callId,
|
||||
reason
|
||||
);
|
||||
notifyStopOnOtherSessions(
|
||||
to,
|
||||
targetCtx.getSessionId(),
|
||||
ctx.getLogin(),
|
||||
ctx.getSessionId(),
|
||||
callId,
|
||||
reason
|
||||
);
|
||||
}
|
||||
|
||||
Net_CallSignalToSession_Response resp = new Net_CallSignalToSession_Response();
|
||||
@@ -83,31 +117,81 @@ public class Net_CallSignalToSession_Handler implements JsonMessageHandler {
|
||||
return resp;
|
||||
}
|
||||
|
||||
private void notifyAcceptedOnOtherSessions(ConnectionContext accepterCtx, String callId) {
|
||||
if (accepterCtx == null) return;
|
||||
String login = accepterCtx.getLogin();
|
||||
String acceptedSessionId = accepterCtx.getSessionId();
|
||||
if (login == null || login.isBlank() || acceptedSessionId == null || acceptedSessionId.isBlank() || callId == null || callId.isBlank()) {
|
||||
private void notifyStopOnOtherSessions(
|
||||
String targetLogin,
|
||||
String excludeSessionId,
|
||||
String fromLogin,
|
||||
String fromSessionId,
|
||||
String callId,
|
||||
String reason
|
||||
) throws Exception {
|
||||
if (isBlank(targetLogin) || isBlank(callId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<ConnectionContext> sameUserSessions = ActiveConnectionsRegistry.getInstance().getByLogin(login);
|
||||
Set<String> onlineSessionIds = new HashSet<>();
|
||||
Set<ConnectionContext> sameUserSessions = ActiveConnectionsRegistry.getInstance().getByLogin(targetLogin);
|
||||
for (ConnectionContext siblingCtx : sameUserSessions) {
|
||||
if (siblingCtx == null || siblingCtx.getWsSession() == null || !siblingCtx.getWsSession().isOpen()) continue;
|
||||
if (acceptedSessionId.equals(siblingCtx.getSessionId())) continue;
|
||||
onlineSessionIds.add(String.valueOf(siblingCtx.getSessionId() == null ? "" : siblingCtx.getSessionId()).trim());
|
||||
if (!isBlank(excludeSessionId) && excludeSessionId.equals(siblingCtx.getSessionId())) continue;
|
||||
|
||||
String siblingEventId = NetIdGenerator.eventId("evt");
|
||||
ObjectNode siblingPayload = MAPPER.createObjectNode();
|
||||
siblingPayload.put("eventId", siblingEventId);
|
||||
siblingPayload.put("fromLogin", login);
|
||||
siblingPayload.put("fromSessionId", acceptedSessionId);
|
||||
siblingPayload.put("toLogin", login);
|
||||
siblingPayload.put("fromLogin", fromLogin);
|
||||
siblingPayload.put("fromSessionId", fromSessionId);
|
||||
siblingPayload.put("toLogin", targetLogin);
|
||||
siblingPayload.put("callId", callId);
|
||||
siblingPayload.put("type", TYPE_HANGUP);
|
||||
siblingPayload.put("data", "accepted_on_other_device");
|
||||
siblingPayload.put("data", reason);
|
||||
siblingPayload.put("timeMs", System.currentTimeMillis());
|
||||
|
||||
WsEventSender.sendEvent(siblingCtx, "IncomingCallSignal", siblingEventId, siblingPayload);
|
||||
}
|
||||
|
||||
List<ActiveSessionEntry> persistedSessions = ActiveSessionsDAO.getInstance().getByLogin(targetLogin);
|
||||
long sentAtMs = System.currentTimeMillis();
|
||||
for (ActiveSessionEntry session : persistedSessions) {
|
||||
String sessionId = String.valueOf(session.getSessionId() == null ? "" : session.getSessionId()).trim();
|
||||
if (!isBlank(excludeSessionId) && excludeSessionId.equals(sessionId)) continue;
|
||||
if (!sessionId.isBlank() && onlineSessionIds.contains(sessionId)) continue;
|
||||
if (isBlank(session.getPushEndpoint()) || isBlank(session.getPushP256dhKey()) || isBlank(session.getPushAuthKey())) {
|
||||
continue;
|
||||
}
|
||||
String pushPayload = "{\"kind\":\"stop_call\""
|
||||
+ ",\"callId\":\"" + jsonEscape(callId) + "\""
|
||||
+ ",\"reason\":\"" + jsonEscape(reason) + "\""
|
||||
+ ",\"fromLogin\":\"" + jsonEscape(fromLogin) + "\""
|
||||
+ ",\"fromSessionId\":\"" + jsonEscape(fromSessionId) + "\""
|
||||
+ ",\"toLogin\":\"" + jsonEscape(targetLogin) + "\""
|
||||
+ ",\"sentAtMs\":" + sentAtMs
|
||||
+ "}";
|
||||
WebPushSender.sendBase64Payload(
|
||||
session.getPushEndpoint(),
|
||||
session.getPushP256dhKey(),
|
||||
session.getPushAuthKey(),
|
||||
pushPayload
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBlank(String s) {
|
||||
return s == null || s.isBlank();
|
||||
}
|
||||
|
||||
private static String jsonEscape(String s) {
|
||||
if (s == null) return "";
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c == '\\') out.append("\\\\");
|
||||
else if (c == '"') out.append("\\\"");
|
||||
else if (c == '\n') out.append("\\n");
|
||||
else if (c == '\r') out.append("\\r");
|
||||
else if (c == '\t') out.append("\\t");
|
||||
else out.append(c);
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -6,6 +6,7 @@ public class Net_CallInviteBroadcast_Response extends Net_Response {
|
||||
private String callId;
|
||||
private int deliveredWsSessions;
|
||||
private int deliveredFcmSessions;
|
||||
private int deliveredWebPushSessions;
|
||||
|
||||
public String getCallId() { return callId; }
|
||||
public void setCallId(String callId) { this.callId = callId; }
|
||||
@@ -15,4 +16,7 @@ public class Net_CallInviteBroadcast_Response extends Net_Response {
|
||||
|
||||
public int getDeliveredFcmSessions() { return deliveredFcmSessions; }
|
||||
public void setDeliveredFcmSessions(int deliveredFcmSessions) { this.deliveredFcmSessions = deliveredFcmSessions; }
|
||||
|
||||
public int getDeliveredWebPushSessions() { return deliveredWebPushSessions; }
|
||||
public void setDeliveredWebPushSessions(int deliveredWebPushSessions) { this.deliveredWebPushSessions = deliveredWebPushSessions; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user