From 5b8b40faebf6996f1d2f5aef4c733dfe13d73b1b Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 16 Mar 2024 19:46:44 -0700 Subject: Add local address to connection key --- .../traccar/handler/StandardLoggingHandler.java | 13 ++---- src/main/java/org/traccar/model/LogRecord.java | 21 ++++++--- .../java/org/traccar/session/ConnectionKey.java | 54 ++++++++++++++++++++++ .../org/traccar/session/ConnectionManager.java | 28 +++++------ .../java/org/traccar/session/DeviceSession.java | 6 +-- 5 files changed, 92 insertions(+), 30 deletions(-) create mode 100644 src/main/java/org/traccar/session/ConnectionKey.java diff --git a/src/main/java/org/traccar/handler/StandardLoggingHandler.java b/src/main/java/org/traccar/handler/StandardLoggingHandler.java index 5978d632e..513602dd8 100644 --- a/src/main/java/org/traccar/handler/StandardLoggingHandler.java +++ b/src/main/java/org/traccar/handler/StandardLoggingHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 - 2023 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2024 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,8 +28,6 @@ import org.traccar.helper.NetworkUtil; import org.traccar.model.LogRecord; import org.traccar.session.ConnectionManager; -import java.net.InetSocketAddress; - public class StandardLoggingHandler extends ChannelDuplexHandler { private static final Logger LOGGER = LoggerFactory.getLogger(StandardLoggingHandler.class); @@ -48,7 +46,7 @@ public class StandardLoggingHandler extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - LogRecord record = createLogRecord(msg); + LogRecord record = createLogRecord(ctx, msg); log(ctx, false, record); super.channelRead(ctx, msg); if (record != null) { @@ -58,16 +56,15 @@ public class StandardLoggingHandler extends ChannelDuplexHandler { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - log(ctx, true, createLogRecord(msg)); + log(ctx, true, createLogRecord(ctx, msg)); super.write(ctx, msg, promise); } - private LogRecord createLogRecord(Object msg) { + private LogRecord createLogRecord(ChannelHandlerContext ctx, Object msg) { if (msg instanceof NetworkMessage) { NetworkMessage networkMessage = (NetworkMessage) msg; if (networkMessage.getMessage() instanceof ByteBuf) { - LogRecord record = new LogRecord(); - record.setAddress((InetSocketAddress) networkMessage.getRemoteAddress()); + LogRecord record = new LogRecord(ctx.channel().localAddress(), networkMessage.getRemoteAddress()); record.setProtocol(protocol); record.setData(ByteBufUtil.hexDump((ByteBuf) networkMessage.getMessage())); return record; diff --git a/src/main/java/org/traccar/model/LogRecord.java b/src/main/java/org/traccar/model/LogRecord.java index c19163af3..b04f51b32 100644 --- a/src/main/java/org/traccar/model/LogRecord.java +++ b/src/main/java/org/traccar/model/LogRecord.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Anton Tananaev (anton@traccar.org) + * Copyright 2023 - 2024 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,24 +16,33 @@ package org.traccar.model; import com.fasterxml.jackson.annotation.JsonIgnore; +import org.traccar.session.ConnectionKey; import java.net.InetSocketAddress; +import java.net.SocketAddress; public class LogRecord { - private InetSocketAddress address; + private final InetSocketAddress localAddress; + private final InetSocketAddress remoteAddress; - public void setAddress(InetSocketAddress address) { - this.address = address; + public LogRecord(SocketAddress localAddress, SocketAddress remoteAddress) { + this.localAddress = (InetSocketAddress) localAddress; + this.remoteAddress = (InetSocketAddress) remoteAddress; } @JsonIgnore public InetSocketAddress getAddress() { - return address; + return remoteAddress; + } + + @JsonIgnore + public ConnectionKey getConnectionKey() { + return new ConnectionKey(localAddress, remoteAddress); } public String getHost() { - return address.getHostString(); + return remoteAddress.getHostString(); } private String protocol; diff --git a/src/main/java/org/traccar/session/ConnectionKey.java b/src/main/java/org/traccar/session/ConnectionKey.java new file mode 100644 index 000000000..3b7e2ebf8 --- /dev/null +++ b/src/main/java/org/traccar/session/ConnectionKey.java @@ -0,0 +1,54 @@ +/* + * Copyright 2024 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.session; + +import io.netty.channel.Channel; + +import java.net.SocketAddress; +import java.util.Objects; + +public class ConnectionKey { + + private final SocketAddress localAddress; + private final SocketAddress remoteAddress; + + public ConnectionKey(Channel channel, SocketAddress remoteAddress) { + this(channel.localAddress(), remoteAddress); + } + + public ConnectionKey(SocketAddress localAddress, SocketAddress remoteAddress) { + this.localAddress = localAddress; + this.remoteAddress = remoteAddress; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ConnectionKey that = (ConnectionKey) o; + return Objects.equals(localAddress, that.localAddress) && Objects.equals(remoteAddress, that.remoteAddress); + } + + @Override + public int hashCode() { + return Objects.hash(localAddress, remoteAddress); + } + +} diff --git a/src/main/java/org/traccar/session/ConnectionManager.java b/src/main/java/org/traccar/session/ConnectionManager.java index 42dcf5ce9..8431a0327 100644 --- a/src/main/java/org/traccar/session/ConnectionManager.java +++ b/src/main/java/org/traccar/session/ConnectionManager.java @@ -66,8 +66,8 @@ public class ConnectionManager implements BroadcastInterface { private final boolean showUnknownDevices; private final Map sessionsByDeviceId = new ConcurrentHashMap<>(); - private final Map> sessionsByEndpoint = new ConcurrentHashMap<>(); - private final Map unknownByEndpoint = new ConcurrentHashMap<>(); + private final Map> sessionsByEndpoint = new ConcurrentHashMap<>(); + private final Map unknownByEndpoint = new ConcurrentHashMap<>(); private final Config config; private final CacheManager cacheManager; @@ -108,8 +108,9 @@ public class ConnectionManager implements BroadcastInterface { Protocol protocol, Channel channel, SocketAddress remoteAddress, String... uniqueIds) throws Exception { + ConnectionKey connectionKey = new ConnectionKey(channel, remoteAddress); Map endpointSessions = sessionsByEndpoint.getOrDefault( - remoteAddress, new ConcurrentHashMap<>()); + connectionKey, new ConcurrentHashMap<>()); uniqueIds = Arrays.stream(uniqueIds).filter(Objects::nonNull).toArray(String[]::new); if (uniqueIds.length > 0) { @@ -133,23 +134,23 @@ public class ConnectionManager implements BroadcastInterface { } if (device != null) { - unknownByEndpoint.remove(remoteAddress); + unknownByEndpoint.remove(connectionKey); device.checkDisabled(); DeviceSession oldSession = sessionsByDeviceId.remove(device.getId()); if (oldSession != null) { - Map oldEndpointSessions = sessionsByEndpoint.get(oldSession.getRemoteAddress()); + Map oldEndpointSessions = sessionsByEndpoint.get(oldSession.getConnectionKey()); if (oldEndpointSessions != null && oldEndpointSessions.size() > 1) { oldEndpointSessions.remove(device.getUniqueId()); } else { - sessionsByEndpoint.remove(oldSession.getRemoteAddress()); + sessionsByEndpoint.remove(oldSession.getConnectionKey()); } } DeviceSession deviceSession = new DeviceSession( device.getId(), device.getUniqueId(), device.getModel(), protocol, channel, remoteAddress); endpointSessions.put(device.getUniqueId(), deviceSession); - sessionsByEndpoint.put(remoteAddress, endpointSessions); + sessionsByEndpoint.put(connectionKey, endpointSessions); sessionsByDeviceId.put(device.getId(), deviceSession); if (oldSession == null) { @@ -158,7 +159,7 @@ public class ConnectionManager implements BroadcastInterface { return deviceSession; } else { - unknownByEndpoint.put(remoteAddress, firstUniqueId); + unknownByEndpoint.put(connectionKey, firstUniqueId); LOGGER.warn("Unknown device - " + String.join(" ", uniqueIds) + " (" + ((InetSocketAddress) remoteAddress).getHostString() + ")"); return null; @@ -189,7 +190,8 @@ public class ConnectionManager implements BroadcastInterface { public void deviceDisconnected(Channel channel, boolean supportsOffline) { SocketAddress remoteAddress = channel.remoteAddress(); if (remoteAddress != null) { - Map endpointSessions = sessionsByEndpoint.remove(remoteAddress); + ConnectionKey connectionKey = new ConnectionKey(channel, remoteAddress); + Map endpointSessions = sessionsByEndpoint.remove(connectionKey); if (endpointSessions != null) { for (DeviceSession deviceSession : endpointSessions.values()) { if (supportsOffline) { @@ -199,7 +201,7 @@ public class ConnectionManager implements BroadcastInterface { cacheManager.removeDevice(deviceSession.getDeviceId()); } } - unknownByEndpoint.remove(remoteAddress); + unknownByEndpoint.remove(connectionKey); } } @@ -212,7 +214,7 @@ public class ConnectionManager implements BroadcastInterface { DeviceSession deviceSession = sessionsByDeviceId.remove(deviceId); if (deviceSession != null) { cacheManager.removeDevice(deviceId); - sessionsByEndpoint.computeIfPresent(deviceSession.getRemoteAddress(), (e, sessions) -> { + sessionsByEndpoint.computeIfPresent(deviceSession.getConnectionKey(), (e, sessions) -> { sessions.remove(deviceSession.getUniqueId()); return sessions.isEmpty() ? null : sessions; }); @@ -345,9 +347,9 @@ public class ConnectionManager implements BroadcastInterface { } public synchronized void updateLog(LogRecord record) { - var sessions = sessionsByEndpoint.getOrDefault(record.getAddress(), Map.of()); + var sessions = sessionsByEndpoint.getOrDefault(record.getConnectionKey(), Map.of()); if (sessions.isEmpty()) { - String unknownUniqueId = unknownByEndpoint.get(record.getAddress()); + String unknownUniqueId = unknownByEndpoint.get(record.getConnectionKey()); if (unknownUniqueId != null && showUnknownDevices) { record.setUniqueId(unknownUniqueId); listeners.values().stream() diff --git a/src/main/java/org/traccar/session/DeviceSession.java b/src/main/java/org/traccar/session/DeviceSession.java index f124ca7f9..31d5e6a13 100644 --- a/src/main/java/org/traccar/session/DeviceSession.java +++ b/src/main/java/org/traccar/session/DeviceSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2024 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,8 +61,8 @@ public class DeviceSession { return channel; } - public SocketAddress getRemoteAddress() { - return remoteAddress; + public ConnectionKey getConnectionKey() { + return new ConnectionKey(channel, remoteAddress); } public boolean supportsLiveCommands() { -- cgit v1.2.3