aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/traccar/session/ConnectionManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/traccar/session/ConnectionManager.java')
-rw-r--r--src/main/java/org/traccar/session/ConnectionManager.java65
1 files changed, 45 insertions, 20 deletions
diff --git a/src/main/java/org/traccar/session/ConnectionManager.java b/src/main/java/org/traccar/session/ConnectionManager.java
index 0b13a5a72..1461c66ea 100644
--- a/src/main/java/org/traccar/session/ConnectionManager.java
+++ b/src/main/java/org/traccar/session/ConnectionManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2022 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 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.
@@ -30,6 +30,7 @@ import org.traccar.database.NotificationManager;
import org.traccar.model.BaseModel;
import org.traccar.model.Device;
import org.traccar.model.Event;
+import org.traccar.model.LogRecord;
import org.traccar.model.Position;
import org.traccar.model.User;
import org.traccar.session.cache.CacheManager;
@@ -62,9 +63,11 @@ public class ConnectionManager implements BroadcastInterface {
private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionManager.class);
private final long deviceTimeout;
+ private final boolean showUnknownDevices;
private final Map<Long, DeviceSession> sessionsByDeviceId = new ConcurrentHashMap<>();
- private final Map<Endpoint, Map<String, DeviceSession>> sessionsByEndpoint = new ConcurrentHashMap<>();
+ private final Map<SocketAddress, Map<String, DeviceSession>> sessionsByEndpoint = new ConcurrentHashMap<>();
+ private final Map<SocketAddress, String> unknownByEndpoint = new ConcurrentHashMap<>();
private final Config config;
private final CacheManager cacheManager;
@@ -93,6 +96,7 @@ public class ConnectionManager implements BroadcastInterface {
this.broadcastService = broadcastService;
this.deviceLookupService = deviceLookupService;
deviceTimeout = config.getLong(Keys.STATUS_TIMEOUT);
+ showUnknownDevices = config.getBoolean(Keys.WEB_SHOW_UNKNOWN_DEVICES);
broadcastService.registerListener(this);
}
@@ -102,11 +106,10 @@ public class ConnectionManager implements BroadcastInterface {
public DeviceSession getDeviceSession(
Protocol protocol, Channel channel, SocketAddress remoteAddress,
- String... uniqueIds) throws StorageException {
+ String... uniqueIds) throws Exception {
- Endpoint endpoint = new Endpoint(channel, remoteAddress);
Map<String, DeviceSession> endpointSessions = sessionsByEndpoint.getOrDefault(
- endpoint, new ConcurrentHashMap<>());
+ remoteAddress, new ConcurrentHashMap<>());
uniqueIds = Arrays.stream(uniqueIds).filter(Objects::nonNull).toArray(String[]::new);
if (uniqueIds.length > 0) {
@@ -122,30 +125,31 @@ public class ConnectionManager implements BroadcastInterface {
Device device = deviceLookupService.lookup(uniqueIds);
+ String firstUniqueId = uniqueIds[0];
if (device == null && config.getBoolean(Keys.DATABASE_REGISTER_UNKNOWN)) {
- if (uniqueIds[0].matches(config.getString(Keys.DATABASE_REGISTER_UNKNOWN_REGEX))) {
- device = addUnknownDevice(uniqueIds[0]);
+ if (firstUniqueId.matches(config.getString(Keys.DATABASE_REGISTER_UNKNOWN_REGEX))) {
+ device = addUnknownDevice(firstUniqueId);
}
}
if (device != null) {
+ unknownByEndpoint.remove(remoteAddress);
device.checkDisabled();
DeviceSession oldSession = sessionsByDeviceId.remove(device.getId());
if (oldSession != null) {
- Endpoint oldEndpoint = new Endpoint(oldSession.getChannel(), oldSession.getRemoteAddress());
- Map<String, DeviceSession> oldEndpointSessions = sessionsByEndpoint.get(oldEndpoint);
+ Map<String, DeviceSession> oldEndpointSessions = sessionsByEndpoint.get(oldSession.getRemoteAddress());
if (oldEndpointSessions != null && oldEndpointSessions.size() > 1) {
oldEndpointSessions.remove(device.getUniqueId());
} else {
- sessionsByEndpoint.remove(oldEndpoint);
+ sessionsByEndpoint.remove(oldSession.getRemoteAddress());
}
}
DeviceSession deviceSession = new DeviceSession(
device.getId(), device.getUniqueId(), protocol, channel, remoteAddress);
endpointSessions.put(device.getUniqueId(), deviceSession);
- sessionsByEndpoint.put(endpoint, endpointSessions);
+ sessionsByEndpoint.put(remoteAddress, endpointSessions);
sessionsByDeviceId.put(device.getId(), deviceSession);
if (oldSession == null) {
@@ -154,6 +158,7 @@ public class ConnectionManager implements BroadcastInterface {
return deviceSession;
} else {
+ unknownByEndpoint.put(remoteAddress, firstUniqueId);
LOGGER.warn("Unknown device - " + String.join(" ", uniqueIds)
+ " (" + ((InetSocketAddress) remoteAddress).getHostString() + ")");
return null;
@@ -182,8 +187,8 @@ public class ConnectionManager implements BroadcastInterface {
}
public void deviceDisconnected(Channel channel, boolean supportsOffline) {
- Endpoint endpoint = new Endpoint(channel, channel.remoteAddress());
- Map<String, DeviceSession> endpointSessions = sessionsByEndpoint.remove(endpoint);
+ SocketAddress remoteAddress = channel.remoteAddress();
+ Map<String, DeviceSession> endpointSessions = sessionsByEndpoint.remove(remoteAddress);
if (endpointSessions != null) {
for (DeviceSession deviceSession : endpointSessions.values()) {
if (supportsOffline) {
@@ -193,6 +198,7 @@ public class ConnectionManager implements BroadcastInterface {
cacheManager.removeDevice(deviceSession.getDeviceId());
}
}
+ unknownByEndpoint.remove(remoteAddress);
}
public void deviceUnknown(long deviceId) {
@@ -204,8 +210,7 @@ public class ConnectionManager implements BroadcastInterface {
DeviceSession deviceSession = sessionsByDeviceId.remove(deviceId);
if (deviceSession != null) {
cacheManager.removeDevice(deviceId);
- Endpoint endpoint = new Endpoint(deviceSession.getChannel(), deviceSession.getRemoteAddress());
- sessionsByEndpoint.computeIfPresent(endpoint, (e, sessions) -> {
+ sessionsByEndpoint.computeIfPresent(deviceSession.getRemoteAddress(), (e, sessions) -> {
sessions.remove(deviceSession.getUniqueId());
return sessions.isEmpty() ? null : sessions;
});
@@ -327,11 +332,8 @@ public class ConnectionManager implements BroadcastInterface {
}
@Override
- public synchronized void invalidatePermission(
- boolean local,
- Class<? extends BaseModel> clazz1, long id1,
- Class<? extends BaseModel> clazz2, long id2,
- boolean link) {
+ public synchronized <T1 extends BaseModel, T2 extends BaseModel> void invalidatePermission(
+ boolean local, Class<T1> clazz1, long id1, Class<T2> clazz2, long id2, boolean link) {
if (link && clazz1.equals(User.class) && clazz2.equals(Device.class)) {
if (listeners.containsKey(id1)) {
userDevices.get(id1).add(id2);
@@ -340,11 +342,34 @@ public class ConnectionManager implements BroadcastInterface {
}
}
+ public synchronized void updateLog(LogRecord record) {
+ var sessions = sessionsByEndpoint.getOrDefault(record.getAddress(), Map.of());
+ if (sessions.isEmpty()) {
+ String unknownUniqueId = unknownByEndpoint.get(record.getAddress());
+ if (unknownUniqueId != null && showUnknownDevices) {
+ record.setUniqueId(unknownUniqueId);
+ listeners.values().stream()
+ .flatMap(Set::stream)
+ .forEach((listener) -> listener.onUpdateLog(record));
+ }
+ } else {
+ var firstEntry = sessions.entrySet().iterator().next();
+ record.setUniqueId(firstEntry.getKey());
+ record.setDeviceId(firstEntry.getValue().getDeviceId());
+ for (long userId : deviceUsers.getOrDefault(record.getDeviceId(), Set.of())) {
+ for (UpdateListener listener : listeners.getOrDefault(userId, Set.of())) {
+ listener.onUpdateLog(record);
+ }
+ }
+ }
+ }
+
public interface UpdateListener {
void onKeepalive();
void onUpdateDevice(Device device);
void onUpdatePosition(Position position);
void onUpdateEvent(Event event);
+ void onUpdateLog(LogRecord record);
}
public synchronized void addListener(long userId, UpdateListener listener) throws StorageException {