Commit e86af4b677af78d7d1f60cb5914be70f9cffe6b9

Authored by Andrew Shvayka
Committed by GitHub
2 parents 08e517a6 4287d838

Merge pull request #4707 from thingsboard/lwm2m-refactoring

LwM2M Refactoring
Showing 38 changed files with 971 additions and 789 deletions
@@ -72,15 +72,15 @@ public class DefaultTbResourceService implements TbResourceService { @@ -72,15 +72,15 @@ public class DefaultTbResourceService implements TbResourceService {
72 if (ResourceType.LWM2M_MODEL.equals(resource.getResourceType())) { 72 if (ResourceType.LWM2M_MODEL.equals(resource.getResourceType())) {
73 try { 73 try {
74 List<ObjectModel> objectModels = 74 List<ObjectModel> objectModels =
75 - ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getData())), resource.getSearchText()); 75 + ddfFileParser.parse(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getData())), resource.getSearchText());
76 if (!objectModels.isEmpty()) { 76 if (!objectModels.isEmpty()) {
77 ObjectModel objectModel = objectModels.get(0); 77 ObjectModel objectModel = objectModels.get(0);
78 78
79 - String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion(); 79 + String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.version;
80 String name = objectModel.name; 80 String name = objectModel.name;
81 resource.setResourceKey(resourceKey); 81 resource.setResourceKey(resourceKey);
82 if (resource.getId() == null) { 82 if (resource.getId() == null) {
83 - resource.setTitle(name + " id=" + objectModel.id + " v" + objectModel.getVersion()); 83 + resource.setTitle(name + " id=" + objectModel.id + " v" + objectModel.version);
84 } 84 }
85 resource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name); 85 resource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name);
86 } else { 86 } else {
@@ -176,7 +176,7 @@ public class DefaultTbResourceService implements TbResourceService { @@ -176,7 +176,7 @@ public class DefaultTbResourceService implements TbResourceService {
176 try { 176 try {
177 DDFFileParser ddfFileParser = new DDFFileParser(new DefaultDDFFileValidator()); 177 DDFFileParser ddfFileParser = new DDFFileParser(new DefaultDDFFileValidator());
178 List<ObjectModel> objectModels = 178 List<ObjectModel> objectModels =
179 - ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getData())), resource.getSearchText()); 179 + ddfFileParser.parse(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getData())), resource.getSearchText());
180 if (objectModels.size() == 0) { 180 if (objectModels.size() == 0) {
181 return null; 181 return null;
182 } else { 182 } else {
@@ -60,6 +60,53 @@ import java.util.concurrent.ScheduledExecutorService; @@ -60,6 +60,53 @@ import java.util.concurrent.ScheduledExecutorService;
60 @DaoSqlTest 60 @DaoSqlTest
61 public class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { 61 public class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest {
62 62
  63 + protected final String TRANSPORT_CONFIGURATION = "{\n" +
  64 + " \"type\": \"LWM2M\",\n" +
  65 + " \"observeAttr\": {\n" +
  66 + " \"keyName\": {\n" +
  67 + " \"/3_1.0/0/9\": \"batteryLevel\"\n" +
  68 + " },\n" +
  69 + " \"observe\": [],\n" +
  70 + " \"attribute\": [\n" +
  71 + " ],\n" +
  72 + " \"telemetry\": [\n" +
  73 + " \"/3_1.0/0/9\"\n" +
  74 + " ],\n" +
  75 + " \"attributeLwm2m\": {}\n" +
  76 + " },\n" +
  77 + " \"bootstrap\": {\n" +
  78 + " \"servers\": {\n" +
  79 + " \"binding\": \"U\",\n" +
  80 + " \"shortId\": 123,\n" +
  81 + " \"lifetime\": 300,\n" +
  82 + " \"notifIfDisabled\": true,\n" +
  83 + " \"defaultMinPeriod\": 1\n" +
  84 + " },\n" +
  85 + " \"lwm2mServer\": {\n" +
  86 + " \"host\": \"localhost\",\n" +
  87 + " \"port\": 5686,\n" +
  88 + " \"serverId\": 123,\n" +
  89 + " \"serverPublicKey\": \"\",\n" +
  90 + " \"bootstrapServerIs\": false,\n" +
  91 + " \"clientHoldOffTime\": 1,\n" +
  92 + " \"bootstrapServerAccountTimeout\": 0\n" +
  93 + " },\n" +
  94 + " \"bootstrapServer\": {\n" +
  95 + " \"host\": \"localhost\",\n" +
  96 + " \"port\": 5687,\n" +
  97 + " \"serverId\": 111,\n" +
  98 + " \"securityMode\": \"NO_SEC\",\n" +
  99 + " \"serverPublicKey\": \"\",\n" +
  100 + " \"bootstrapServerIs\": true,\n" +
  101 + " \"clientHoldOffTime\": 1,\n" +
  102 + " \"bootstrapServerAccountTimeout\": 0\n" +
  103 + " }\n" +
  104 + " },\n" +
  105 + " \"clientLwM2mSettings\": {\n" +
  106 + " \"clientOnlyObserveAfterConnect\": 1\n" +
  107 + " }\n" +
  108 + "}";
  109 +
63 protected DeviceProfile deviceProfile; 110 protected DeviceProfile deviceProfile;
64 protected ScheduledExecutorService executor; 111 protected ScheduledExecutorService executor;
65 protected TbTestWebSocketClient wsClient; 112 protected TbTestWebSocketClient wsClient;
@@ -22,6 +22,7 @@ import org.junit.Assert; @@ -22,6 +22,7 @@ import org.junit.Assert;
22 import org.junit.Test; 22 import org.junit.Test;
23 import org.thingsboard.common.util.JacksonUtil; 23 import org.thingsboard.common.util.JacksonUtil;
24 import org.thingsboard.server.common.data.Device; 24 import org.thingsboard.server.common.data.Device;
  25 +import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredentials;
25 import org.thingsboard.server.common.data.query.EntityData; 26 import org.thingsboard.server.common.data.query.EntityData;
26 import org.thingsboard.server.common.data.query.EntityDataPageLink; 27 import org.thingsboard.server.common.data.query.EntityDataPageLink;
27 import org.thingsboard.server.common.data.query.EntityDataQuery; 28 import org.thingsboard.server.common.data.query.EntityDataQuery;
@@ -36,7 +37,6 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate; @@ -36,7 +37,6 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate;
36 import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd; 37 import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd;
37 import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; 38 import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient;
38 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; 39 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
39 -import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredentials;  
40 40
41 import java.util.Collections; 41 import java.util.Collections;
42 import java.util.List; 42 import java.util.List;
@@ -46,60 +46,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @@ -46,60 +46,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
46 46
47 public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { 47 public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
48 48
49 - protected final String TRANSPORT_CONFIGURATION = "{\n" +  
50 - " \"type\": \"LWM2M\",\n" +  
51 - " \"observeAttr\": {\n" +  
52 - " \"keyName\": {\n" +  
53 - " \"/3_1.0/0/9\": \"batteryLevel\"\n" +  
54 - " },\n" +  
55 - " \"observe\": [],\n" +  
56 - " \"attribute\": [\n" +  
57 - " ],\n" +  
58 - " \"telemetry\": [\n" +  
59 - " \"/3_1.0/0/9\"\n" +  
60 - " ],\n" +  
61 - " \"attributeLwm2m\": {}\n" +  
62 - " },\n" +  
63 - " \"bootstrap\": {\n" +  
64 - " \"servers\": {\n" +  
65 - " \"binding\": \"UQ\",\n" +  
66 - " \"shortId\": 123,\n" +  
67 - " \"lifetime\": 300,\n" +  
68 - " \"notifIfDisabled\": true,\n" +  
69 - " \"defaultMinPeriod\": 1\n" +  
70 - " },\n" +  
71 - " \"lwm2mServer\": {\n" +  
72 - " \"host\": \"localhost\",\n" +  
73 - " \"port\": 5685,\n" +  
74 - " \"serverId\": 123,\n" +  
75 - " \"securityMode\": \"NO_SEC\",\n" +  
76 - " \"serverPublicKey\": \"\",\n" +  
77 - " \"bootstrapServerIs\": false,\n" +  
78 - " \"clientHoldOffTime\": 1,\n" +  
79 - " \"bootstrapServerAccountTimeout\": 0\n" +  
80 - " },\n" +  
81 - " \"bootstrapServer\": {\n" +  
82 - " \"host\": \"localhost\",\n" +  
83 - " \"port\": 5687,\n" +  
84 - " \"serverId\": 111,\n" +  
85 - " \"securityMode\": \"NO_SEC\",\n" +  
86 - " \"serverPublicKey\": \"\",\n" +  
87 - " \"bootstrapServerIs\": true,\n" +  
88 - " \"clientHoldOffTime\": 1,\n" +  
89 - " \"bootstrapServerAccountTimeout\": 0\n" +  
90 - " }\n" +  
91 - " },\n" +  
92 - " \"clientLwM2mSettings\": {\n" +  
93 - " \"clientOnlyObserveAfterConnect\": 1\n" +  
94 - " }\n" +  
95 - "}";  
96 -  
97 - private final int port = 5685;  
98 - private final Security security = noSec("coap://localhost:" + port, 123);  
99 - private final NetworkConfig coapConfig = new NetworkConfig().setString("COAP_PORT", Integer.toString(port)); 49 + private final int PORT = 5685;
  50 + private final Security SECURITY = noSec("coap://localhost:" + PORT, 123);
  51 + private final NetworkConfig COAP_CONFIG = new NetworkConfig().setString("COAP_PORT", Integer.toString(PORT));
  52 + private final String ENDPOINT = "deviceAEndpoint";
100 53
101 @NotNull 54 @NotNull
102 - private Device createDevice(String deviceAEndpoint) throws Exception { 55 + private Device createDevice() throws Exception {
103 Device device = new Device(); 56 Device device = new Device();
104 device.setName("Device A"); 57 device.setName("Device A");
105 device.setDeviceProfileId(deviceProfile.getId()); 58 device.setDeviceProfileId(deviceProfile.getId());
@@ -114,7 +67,7 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { @@ -114,7 +67,7 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
114 67
115 LwM2MCredentials noSecCredentials = new LwM2MCredentials(); 68 LwM2MCredentials noSecCredentials = new LwM2MCredentials();
116 NoSecClientCredentials clientCredentials = new NoSecClientCredentials(); 69 NoSecClientCredentials clientCredentials = new NoSecClientCredentials();
117 - clientCredentials.setEndpoint(deviceAEndpoint); 70 + clientCredentials.setEndpoint(ENDPOINT);
118 noSecCredentials.setClient(clientCredentials); 71 noSecCredentials.setClient(clientCredentials);
119 deviceCredentials.setCredentialsValue(JacksonUtil.toString(noSecCredentials)); 72 deviceCredentials.setCredentialsValue(JacksonUtil.toString(noSecCredentials));
120 doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk()); 73 doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk());
@@ -125,9 +78,7 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { @@ -125,9 +78,7 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
125 public void testConnectAndObserveTelemetry() throws Exception { 78 public void testConnectAndObserveTelemetry() throws Exception {
126 createDeviceProfile(TRANSPORT_CONFIGURATION); 79 createDeviceProfile(TRANSPORT_CONFIGURATION);
127 80
128 - String deviceAEndpoint = "deviceAEndpoint";  
129 -  
130 - Device device = createDevice(deviceAEndpoint); 81 + Device device = createDevice();
131 82
132 SingleEntityFilter sef = new SingleEntityFilter(); 83 SingleEntityFilter sef = new SingleEntityFilter();
133 sef.setSingleEntity(device.getId()); 84 sef.setSingleEntity(device.getId());
@@ -144,8 +95,8 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { @@ -144,8 +95,8 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
144 wsClient.waitForReply(); 95 wsClient.waitForReply();
145 96
146 wsClient.registerWaitForUpdate(); 97 wsClient.registerWaitForUpdate();
147 - LwM2MTestClient client = new LwM2MTestClient(executor, deviceAEndpoint);  
148 - client.init(security, coapConfig); 98 + LwM2MTestClient client = new LwM2MTestClient(executor, ENDPOINT);
  99 + client.init(SECURITY, COAP_CONFIG);
149 String msg = wsClient.waitForUpdate(); 100 String msg = wsClient.waitForUpdate();
150 101
151 EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class); 102 EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class);
@@ -47,54 +47,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @@ -47,54 +47,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
47 47
48 public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { 48 public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
49 49
50 - protected final String TRANSPORT_CONFIGURATION = "{\n" +  
51 - " \"type\": \"LWM2M\",\n" +  
52 - " \"observeAttr\": {\n" +  
53 - " \"keyName\": {\n" +  
54 - " \"/3_1.0/0/9\": \"batteryLevel\"\n" +  
55 - " },\n" +  
56 - " \"observe\": [],\n" +  
57 - " \"attribute\": [\n" +  
58 - " ],\n" +  
59 - " \"telemetry\": [\n" +  
60 - " \"/3_1.0/0/9\"\n" +  
61 - " ],\n" +  
62 - " \"attributeLwm2m\": {}\n" +  
63 - " },\n" +  
64 - " \"bootstrap\": {\n" +  
65 - " \"servers\": {\n" +  
66 - " \"binding\": \"UQ\",\n" +  
67 - " \"shortId\": 123,\n" +  
68 - " \"lifetime\": 300,\n" +  
69 - " \"notifIfDisabled\": true,\n" +  
70 - " \"defaultMinPeriod\": 1\n" +  
71 - " },\n" +  
72 - " \"lwm2mServer\": {\n" +  
73 - " \"host\": \"localhost\",\n" +  
74 - " \"port\": 5686,\n" +  
75 - " \"serverId\": 123,\n" +  
76 - " \"serverPublicKey\": \"\",\n" +  
77 - " \"bootstrapServerIs\": false,\n" +  
78 - " \"clientHoldOffTime\": 1,\n" +  
79 - " \"bootstrapServerAccountTimeout\": 0\n" +  
80 - " },\n" +  
81 - " \"bootstrapServer\": {\n" +  
82 - " \"host\": \"localhost\",\n" +  
83 - " \"port\": 5687,\n" +  
84 - " \"serverId\": 111,\n" +  
85 - " \"securityMode\": \"NO_SEC\",\n" +  
86 - " \"serverPublicKey\": \"\",\n" +  
87 - " \"bootstrapServerIs\": true,\n" +  
88 - " \"clientHoldOffTime\": 1,\n" +  
89 - " \"bootstrapServerAccountTimeout\": 0\n" +  
90 - " }\n" +  
91 - " },\n" +  
92 - " \"clientLwM2mSettings\": {\n" +  
93 - " \"clientOnlyObserveAfterConnect\": 1\n" +  
94 - " }\n" +  
95 - "}";  
96 -  
97 -  
98 private final int port = 5686; 50 private final int port = 5686;
99 private final NetworkConfig coapConfig = new NetworkConfig().setString("COAP_SECURE_PORT", Integer.toString(port)); 51 private final NetworkConfig coapConfig = new NetworkConfig().setString("COAP_SECURE_PORT", Integer.toString(port));
100 private final String endpoint = "deviceAEndpoint"; 52 private final String endpoint = "deviceAEndpoint";
@@ -17,40 +17,37 @@ package org.thingsboard.server.transport.lwm2m.client; @@ -17,40 +17,37 @@ package org.thingsboard.server.transport.lwm2m.client;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
  20 +import org.eclipse.californium.core.network.CoapEndpoint;
20 import org.eclipse.californium.core.network.config.NetworkConfig; 21 import org.eclipse.californium.core.network.config.NetworkConfig;
21 -import org.eclipse.californium.elements.Connector; 22 +import org.eclipse.californium.core.observe.ObservationStore;
22 import org.eclipse.californium.scandium.DTLSConnector; 23 import org.eclipse.californium.scandium.DTLSConnector;
23 import org.eclipse.californium.scandium.config.DtlsConnectorConfig; 24 import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
24 -import org.eclipse.californium.scandium.dtls.ClientHandshaker;  
25 -import org.eclipse.californium.scandium.dtls.DTLSSession;  
26 -import org.eclipse.californium.scandium.dtls.HandshakeException;  
27 -import org.eclipse.californium.scandium.dtls.Handshaker;  
28 -import org.eclipse.californium.scandium.dtls.ResumingClientHandshaker;  
29 -import org.eclipse.californium.scandium.dtls.ResumingServerHandshaker;  
30 -import org.eclipse.californium.scandium.dtls.ServerHandshaker;  
31 -import org.eclipse.californium.scandium.dtls.SessionAdapter;  
32 import org.eclipse.leshan.client.californium.LeshanClient; 25 import org.eclipse.leshan.client.californium.LeshanClient;
33 import org.eclipse.leshan.client.californium.LeshanClientBuilder; 26 import org.eclipse.leshan.client.californium.LeshanClientBuilder;
34 import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory; 27 import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory;
35 import org.eclipse.leshan.client.object.Security; 28 import org.eclipse.leshan.client.object.Security;
36 import org.eclipse.leshan.client.object.Server; 29 import org.eclipse.leshan.client.object.Server;
37 import org.eclipse.leshan.client.observer.LwM2mClientObserver; 30 import org.eclipse.leshan.client.observer.LwM2mClientObserver;
  31 +import org.eclipse.leshan.client.resource.DummyInstanceEnabler;
38 import org.eclipse.leshan.client.resource.ObjectsInitializer; 32 import org.eclipse.leshan.client.resource.ObjectsInitializer;
39 import org.eclipse.leshan.client.servers.ServerIdentity; 33 import org.eclipse.leshan.client.servers.ServerIdentity;
  34 +import org.eclipse.leshan.core.LwM2mId;
40 import org.eclipse.leshan.core.ResponseCode; 35 import org.eclipse.leshan.core.ResponseCode;
41 -import org.eclipse.leshan.core.californium.DefaultEndpointFactory; 36 +import org.eclipse.leshan.core.californium.EndpointFactory;
  37 +import org.eclipse.leshan.core.model.InvalidDDFFileException;
42 import org.eclipse.leshan.core.model.LwM2mModel; 38 import org.eclipse.leshan.core.model.LwM2mModel;
43 import org.eclipse.leshan.core.model.ObjectLoader; 39 import org.eclipse.leshan.core.model.ObjectLoader;
44 import org.eclipse.leshan.core.model.ObjectModel; 40 import org.eclipse.leshan.core.model.ObjectModel;
45 import org.eclipse.leshan.core.model.StaticModel; 41 import org.eclipse.leshan.core.model.StaticModel;
46 import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder; 42 import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder;
47 import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder; 43 import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder;
48 -import org.eclipse.leshan.core.request.BindingMode;  
49 import org.eclipse.leshan.core.request.BootstrapRequest; 44 import org.eclipse.leshan.core.request.BootstrapRequest;
50 import org.eclipse.leshan.core.request.DeregisterRequest; 45 import org.eclipse.leshan.core.request.DeregisterRequest;
51 import org.eclipse.leshan.core.request.RegisterRequest; 46 import org.eclipse.leshan.core.request.RegisterRequest;
52 import org.eclipse.leshan.core.request.UpdateRequest; 47 import org.eclipse.leshan.core.request.UpdateRequest;
53 48
  49 +import java.io.IOException;
  50 +import java.net.InetSocketAddress;
54 import java.util.ArrayList; 51 import java.util.ArrayList;
55 import java.util.List; 52 import java.util.List;
56 import java.util.concurrent.ScheduledExecutorService; 53 import java.util.concurrent.ScheduledExecutorService;
@@ -67,7 +64,7 @@ public class LwM2MTestClient { @@ -67,7 +64,7 @@ public class LwM2MTestClient {
67 private final String endpoint; 64 private final String endpoint;
68 private LeshanClient client; 65 private LeshanClient client;
69 66
70 - public void init(Security security, NetworkConfig coapConfig) { 67 + public void init(Security security, NetworkConfig coapConfig) throws InvalidDDFFileException, IOException {
71 String[] resources = new String[]{"0.xml", "1.xml", "2.xml", "3.xml"}; 68 String[] resources = new String[]{"0.xml", "1.xml", "2.xml", "3.xml"};
72 List<ObjectModel> models = new ArrayList<>(); 69 List<ObjectModel> models = new ArrayList<>();
73 for (String resourceName : resources) { 70 for (String resourceName : resources) {
@@ -76,82 +73,51 @@ public class LwM2MTestClient { @@ -76,82 +73,51 @@ public class LwM2MTestClient {
76 LwM2mModel model = new StaticModel(models); 73 LwM2mModel model = new StaticModel(models);
77 ObjectsInitializer initializer = new ObjectsInitializer(model); 74 ObjectsInitializer initializer = new ObjectsInitializer(model);
78 initializer.setInstancesForObject(SECURITY, security); 75 initializer.setInstancesForObject(SECURITY, security);
79 - initializer.setInstancesForObject(SERVER, new Server(123, 300, BindingMode.U, false)); 76 + initializer.setInstancesForObject(SERVER, new Server(123, 300));
80 initializer.setInstancesForObject(DEVICE, new SimpleLwM2MDevice()); 77 initializer.setInstancesForObject(DEVICE, new SimpleLwM2MDevice());
  78 + initializer.setClassForObject(LwM2mId.ACCESS_CONTROL, DummyInstanceEnabler.class);
81 79
82 DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); 80 DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();
83 dtlsConfig.setRecommendedCipherSuitesOnly(true); 81 dtlsConfig.setRecommendedCipherSuitesOnly(true);
  82 + dtlsConfig.setClientOnly();
84 83
85 DefaultRegistrationEngineFactory engineFactory = new DefaultRegistrationEngineFactory(); 84 DefaultRegistrationEngineFactory engineFactory = new DefaultRegistrationEngineFactory();
86 engineFactory.setReconnectOnUpdate(false); 85 engineFactory.setReconnectOnUpdate(false);
87 engineFactory.setResumeOnConnect(true); 86 engineFactory.setResumeOnConnect(true);
88 87
89 - DefaultEndpointFactory endpointFactory = new DefaultEndpointFactory(endpoint) { 88 + EndpointFactory endpointFactory = new EndpointFactory() {
  89 +
90 @Override 90 @Override
91 - protected Connector createSecuredConnector(DtlsConnectorConfig dtlsConfig) {  
92 -  
93 - return new DTLSConnector(dtlsConfig) {  
94 - @Override  
95 - protected void onInitializeHandshaker(Handshaker handshaker) {  
96 - handshaker.addSessionListener(new SessionAdapter() {  
97 -  
98 - @Override  
99 - public void handshakeStarted(Handshaker handshaker) throws HandshakeException {  
100 - if (handshaker instanceof ServerHandshaker) {  
101 - log.info("DTLS Full Handshake initiated by server : STARTED ...");  
102 - } else if (handshaker instanceof ResumingServerHandshaker) {  
103 - log.info("DTLS abbreviated Handshake initiated by server : STARTED ...");  
104 - } else if (handshaker instanceof ClientHandshaker) {  
105 - log.info("DTLS Full Handshake initiated by client : STARTED ...");  
106 - } else if (handshaker instanceof ResumingClientHandshaker) {  
107 - log.info("DTLS abbreviated Handshake initiated by client : STARTED ...");  
108 - }  
109 - }  
110 -  
111 - @Override  
112 - public void sessionEstablished(Handshaker handshaker, DTLSSession establishedSession)  
113 - throws HandshakeException {  
114 - if (handshaker instanceof ServerHandshaker) {  
115 - log.info("DTLS Full Handshake initiated by server : SUCCEED, handshaker {}", handshaker);  
116 - } else if (handshaker instanceof ResumingServerHandshaker) {  
117 - log.info("DTLS abbreviated Handshake initiated by server : SUCCEED, handshaker {}", handshaker);  
118 - } else if (handshaker instanceof ClientHandshaker) {  
119 - log.info("DTLS Full Handshake initiated by client : SUCCEED, handshaker {}", handshaker);  
120 - } else if (handshaker instanceof ResumingClientHandshaker) {  
121 - log.info("DTLS abbreviated Handshake initiated by client : SUCCEED, handshaker {}", handshaker);  
122 - }  
123 - }  
124 -  
125 - @Override  
126 - public void handshakeFailed(Handshaker handshaker, Throwable error) {  
127 - /** get cause */  
128 - String cause;  
129 - if (error != null) {  
130 - if (error.getMessage() != null) {  
131 - cause = error.getMessage();  
132 - } else {  
133 - cause = error.getClass().getName();  
134 - }  
135 - } else {  
136 - cause = "unknown cause";  
137 - }  
138 -  
139 - if (handshaker instanceof ServerHandshaker) {  
140 - log.info("DTLS Full Handshake initiated by server : FAILED [{}]", cause);  
141 - } else if (handshaker instanceof ResumingServerHandshaker) {  
142 - log.info("DTLS abbreviated Handshake initiated by server : FAILED [{}]", cause);  
143 - } else if (handshaker instanceof ClientHandshaker) {  
144 - log.info("DTLS Full Handshake initiated by client : FAILED [{}]", cause);  
145 - } else if (handshaker instanceof ResumingClientHandshaker) {  
146 - log.info("DTLS abbreviated Handshake initiated by client : FAILED [{}]", cause);  
147 - }  
148 - }  
149 - });  
150 - }  
151 - }; 91 + public CoapEndpoint createUnsecuredEndpoint(InetSocketAddress address, NetworkConfig coapConfig,
  92 + ObservationStore store) {
  93 + CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
  94 + builder.setInetSocketAddress(address);
  95 + builder.setNetworkConfig(coapConfig);
  96 + return builder.build();
  97 + }
  98 +
  99 + @Override
  100 + public CoapEndpoint createSecuredEndpoint(DtlsConnectorConfig dtlsConfig, NetworkConfig coapConfig,
  101 + ObservationStore store) {
  102 + CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
  103 + DtlsConnectorConfig.Builder dtlsConfigBuilder = new DtlsConnectorConfig.Builder(dtlsConfig);
  104 +
  105 + // tricks to be able to change psk information on the fly
  106 +// AdvancedPskStore pskStore = dtlsConfig.getAdvancedPskStore();
  107 +// if (pskStore != null) {
  108 +// PskPublicInformation identity = pskStore.getIdentity(null, null);
  109 +// SecretKey key = pskStore
  110 +// .requestPskSecretResult(ConnectionId.EMPTY, null, identity, null, null, null).getSecret();
  111 +// singlePSKStore = new SinglePSKStore(identity, key);
  112 +// dtlsConfigBuilder.setAdvancedPskStore(singlePSKStore);
  113 +// }
  114 + builder.setConnector(new DTLSConnector(dtlsConfigBuilder.build()));
  115 + builder.setNetworkConfig(coapConfig);
  116 + return builder.build();
152 } 117 }
153 }; 118 };
154 119
  120 +
155 LeshanClientBuilder builder = new LeshanClientBuilder(endpoint); 121 LeshanClientBuilder builder = new LeshanClientBuilder(endpoint);
156 builder.setLocalAddress("0.0.0.0", 11000); 122 builder.setLocalAddress("0.0.0.0", 11000);
157 builder.setObjects(initializer.createAll()); 123 builder.setObjects(initializer.createAll());
@@ -246,6 +212,11 @@ public class LwM2MTestClient { @@ -246,6 +212,11 @@ public class LwM2MTestClient {
246 public void onDeregistrationTimeout(ServerIdentity server, DeregisterRequest request) { 212 public void onDeregistrationTimeout(ServerIdentity server, DeregisterRequest request) {
247 log.info("ClientObserver ->onDeregistrationTimeout... DeregisterRequest [{}] [{}]", request.getRegistrationId(), request.getRegistrationId()); 213 log.info("ClientObserver ->onDeregistrationTimeout... DeregisterRequest [{}] [{}]", request.getRegistrationId(), request.getRegistrationId());
248 } 214 }
  215 +
  216 + @Override
  217 + public void onUnexpectedError(Throwable unexpectedError) {
  218 +
  219 + }
249 }; 220 };
250 this.client.addObserver(observer); 221 this.client.addObserver(observer);
251 222
@@ -97,7 +97,7 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl @@ -97,7 +97,7 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl
97 } 97 }
98 98
99 @Override 99 @Override
100 - public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) { 100 + public WriteResponse write(ServerIdentity identity, boolean replace, int resourceid, LwM2mResource value) {
101 log.info("Write on Device resource /{}/{}/{}", getModel().id, getId(), resourceid); 101 log.info("Write on Device resource /{}/{}/{}", getModel().id, getId(), resourceid);
102 102
103 switch (resourceid) { 103 switch (resourceid) {
@@ -112,7 +112,7 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl @@ -112,7 +112,7 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl
112 fireResourcesChange(resourceid); 112 fireResourcesChange(resourceid);
113 return WriteResponse.success(); 113 return WriteResponse.success();
114 default: 114 default:
115 - return super.write(identity, resourceid, value); 115 + return super.write(identity, replace, resourceid, value);
116 } 116 }
117 } 117 }
118 118
@@ -109,8 +109,8 @@ public class LwM2MTransportBootstrapService { @@ -109,8 +109,8 @@ public class LwM2MTransportBootstrapService {
109 /** Create credentials */ 109 /** Create credentials */
110 this.setServerWithCredentials(builder); 110 this.setServerWithCredentials(builder);
111 111
112 - /** Set securityStore with new ConfigStore */  
113 - builder.setConfigStore(lwM2MInMemoryBootstrapConfigStore); 112 +// /** Set securityStore with new ConfigStore */
  113 +// builder.setConfigStore(lwM2MInMemoryBootstrapConfigStore);
114 114
115 /** SecurityStore */ 115 /** SecurityStore */
116 builder.setSecurityStore(lwM2MBootstrapSecurityStore); 116 builder.setSecurityStore(lwM2MBootstrapSecurityStore);
@@ -69,7 +69,7 @@ public class LwM2MBootstrapConfig { @@ -69,7 +69,7 @@ public class LwM2MBootstrapConfig {
69 server0.lifetime = servers.getLifetime(); 69 server0.lifetime = servers.getLifetime();
70 server0.defaultMinPeriod = servers.getDefaultMinPeriod(); 70 server0.defaultMinPeriod = servers.getDefaultMinPeriod();
71 server0.notifIfDisabled = servers.isNotifIfDisabled(); 71 server0.notifIfDisabled = servers.isNotifIfDisabled();
72 - server0.binding = BindingMode.valueOf(servers.getBinding()); 72 + server0.binding = BindingMode.parse(servers.getBinding());
73 configBs.servers.put(0, server0); 73 configBs.servers.put(0, server0);
74 /* Security Configuration (object 0) as defined in LWM2M 1.0.x TS. Bootstrap instance = 0 */ 74 /* Security Configuration (object 0) as defined in LWM2M 1.0.x TS. Bootstrap instance = 0 */
75 this.bootstrapServer.setBootstrapServerIs(true); 75 this.bootstrapServer.setBootstrapServerIs(true);
@@ -30,7 +30,7 @@ import org.eclipse.leshan.server.security.SecurityInfo; @@ -30,7 +30,7 @@ import org.eclipse.leshan.server.security.SecurityInfo;
30 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 30 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
31 import org.springframework.stereotype.Service; 31 import org.springframework.stereotype.Service;
32 import org.thingsboard.server.gen.transport.TransportProtos; 32 import org.thingsboard.server.gen.transport.TransportProtos;
33 -import org.thingsboard.server.transport.lwm2m.secure.EndpointSecurityInfo; 33 +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
34 import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; 34 import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
35 import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener; 35 import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener;
36 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; 36 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
@@ -40,7 +40,7 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; @@ -40,7 +40,7 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
40 import java.io.IOException; 40 import java.io.IOException;
41 import java.security.GeneralSecurityException; 41 import java.security.GeneralSecurityException;
42 import java.util.Collections; 42 import java.util.Collections;
43 -import java.util.List; 43 +import java.util.Iterator;
44 import java.util.UUID; 44 import java.util.UUID;
45 45
46 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.BOOTSTRAP_SERVER; 46 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.BOOTSTRAP_SERVER;
@@ -71,8 +71,8 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { @@ -71,8 +71,8 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
71 } 71 }
72 72
73 @Override 73 @Override
74 - public List<SecurityInfo> getAllByEndpoint(String endPoint) {  
75 - EndpointSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endPoint, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP); 74 + public Iterator<SecurityInfo> getAllByEndpoint(String endPoint) {
  75 + TbLwM2MSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfoByCredentialsId(endPoint, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP);
76 if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) { 76 if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) {
77 /* add value to store from BootstrapJson */ 77 /* add value to store from BootstrapJson */
78 this.setBootstrapConfigScurityInfo(store); 78 this.setBootstrapConfigScurityInfo(store);
@@ -88,7 +88,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { @@ -88,7 +88,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
88 } catch (InvalidConfigurationException e) { 88 } catch (InvalidConfigurationException e) {
89 log.error("", e); 89 log.error("", e);
90 } 90 }
91 - return store.getSecurityInfo() == null ? null : Collections.singletonList(store.getSecurityInfo()); 91 + return store.getSecurityInfo() == null ? null : Collections.singletonList(store.getSecurityInfo()).iterator();
92 } 92 }
93 } 93 }
94 return null; 94 return null;
@@ -96,7 +96,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { @@ -96,7 +96,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
96 96
97 @Override 97 @Override
98 public SecurityInfo getByIdentity(String identity) { 98 public SecurityInfo getByIdentity(String identity) {
99 - EndpointSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(identity, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP); 99 + TbLwM2MSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfoByCredentialsId(identity, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP);
100 if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) { 100 if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) {
101 /* add value to store from BootstrapJson */ 101 /* add value to store from BootstrapJson */
102 this.setBootstrapConfigScurityInfo(store); 102 this.setBootstrapConfigScurityInfo(store);
@@ -113,7 +113,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { @@ -113,7 +113,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
113 return null; 113 return null;
114 } 114 }
115 115
116 - private void setBootstrapConfigScurityInfo(EndpointSecurityInfo store) { 116 + private void setBootstrapConfigScurityInfo(TbLwM2MSecurityInfo store) {
117 /* BootstrapConfig */ 117 /* BootstrapConfig */
118 LwM2MBootstrapConfig lwM2MBootstrapConfig = this.getParametersBootstrap(store); 118 LwM2MBootstrapConfig lwM2MBootstrapConfig = this.getParametersBootstrap(store);
119 if (lwM2MBootstrapConfig != null) { 119 if (lwM2MBootstrapConfig != null) {
@@ -150,7 +150,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { @@ -150,7 +150,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
150 } 150 }
151 } 151 }
152 152
153 - private LwM2MBootstrapConfig getParametersBootstrap(EndpointSecurityInfo store) { 153 + private LwM2MBootstrapConfig getParametersBootstrap(TbLwM2MSecurityInfo store) {
154 try { 154 try {
155 LwM2MBootstrapConfig lwM2MBootstrapConfig = store.getBootstrapCredentialConfig(); 155 LwM2MBootstrapConfig lwM2MBootstrapConfig = store.getBootstrapCredentialConfig();
156 if (lwM2MBootstrapConfig != null) { 156 if (lwM2MBootstrapConfig != null) {
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.transport.lwm2m.bootstrap.secure; 16 package org.thingsboard.server.transport.lwm2m.bootstrap.secure;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
  19 +import org.eclipse.leshan.core.request.BootstrapRequest;
19 import org.eclipse.leshan.core.request.Identity; 20 import org.eclipse.leshan.core.request.Identity;
20 import org.eclipse.leshan.server.bootstrap.BootstrapSession; 21 import org.eclipse.leshan.server.bootstrap.BootstrapSession;
21 import org.eclipse.leshan.server.bootstrap.DefaultBootstrapSession; 22 import org.eclipse.leshan.server.bootstrap.DefaultBootstrapSession;
@@ -25,7 +26,7 @@ import org.eclipse.leshan.server.security.SecurityChecker; @@ -25,7 +26,7 @@ import org.eclipse.leshan.server.security.SecurityChecker;
25 import org.eclipse.leshan.server.security.SecurityInfo; 26 import org.eclipse.leshan.server.security.SecurityInfo;
26 27
27 import java.util.Collections; 28 import java.util.Collections;
28 -import java.util.List; 29 +import java.util.Iterator;
29 30
30 @Slf4j 31 @Slf4j
31 public class LwM2mDefaultBootstrapSessionManager extends DefaultBootstrapSessionManager { 32 public class LwM2mDefaultBootstrapSessionManager extends DefaultBootstrapSessionManager {
@@ -50,16 +51,17 @@ public class LwM2mDefaultBootstrapSessionManager extends DefaultBootstrapSession @@ -50,16 +51,17 @@ public class LwM2mDefaultBootstrapSessionManager extends DefaultBootstrapSession
50 } 51 }
51 52
52 @SuppressWarnings("deprecation") 53 @SuppressWarnings("deprecation")
53 - public BootstrapSession begin(String endpoint, Identity clientIdentity) { 54 + public BootstrapSession begin(BootstrapRequest request, Identity clientIdentity) {
54 boolean authorized; 55 boolean authorized;
55 if (bsSecurityStore != null) { 56 if (bsSecurityStore != null) {
56 - List<SecurityInfo> securityInfos = (clientIdentity.getPskIdentity() != null && !clientIdentity.getPskIdentity().isEmpty()) ? Collections.singletonList(bsSecurityStore.getByIdentity(clientIdentity.getPskIdentity())) : bsSecurityStore.getAllByEndpoint(endpoint); 57 + Iterator<SecurityInfo> securityInfos = (clientIdentity.getPskIdentity() != null && !clientIdentity.getPskIdentity().isEmpty()) ?
  58 + Collections.singletonList(bsSecurityStore.getByIdentity(clientIdentity.getPskIdentity())).iterator() : bsSecurityStore.getAllByEndpoint(request.getEndpointName());
57 log.info("Bootstrap session started securityInfos: [{}]", securityInfos); 59 log.info("Bootstrap session started securityInfos: [{}]", securityInfos);
58 - authorized = securityChecker.checkSecurityInfos(endpoint, clientIdentity, securityInfos); 60 + authorized = securityChecker.checkSecurityInfos(request.getEndpointName(), clientIdentity, securityInfos);
59 } else { 61 } else {
60 authorized = true; 62 authorized = true;
61 } 63 }
62 - DefaultBootstrapSession session = new DefaultBootstrapSession(endpoint, clientIdentity, authorized); 64 + DefaultBootstrapSession session = new DefaultBootstrapSession(request, clientIdentity, authorized);
63 log.info("Bootstrap session started : {}", session); 65 log.info("Bootstrap session started : {}", session);
64 return session; 66 return session;
65 } 67 }
@@ -22,16 +22,16 @@ import org.eclipse.leshan.server.security.SecurityInfo; @@ -22,16 +22,16 @@ import org.eclipse.leshan.server.security.SecurityInfo;
22 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
23 import org.thingsboard.common.util.JacksonUtil; 23 import org.thingsboard.common.util.JacksonUtil;
24 import org.thingsboard.server.common.data.StringUtils; 24 import org.thingsboard.server.common.data.StringUtils;
  25 +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials;
25 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; 26 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
  27 +import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredentials;
  28 +import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredentials;
26 import org.thingsboard.server.common.transport.TransportServiceCallback; 29 import org.thingsboard.server.common.transport.TransportServiceCallback;
27 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 30 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
28 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; 31 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
29 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 32 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
30 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 33 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
31 -import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials;  
32 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; 34 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
33 -import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredentials;  
34 -import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredentials;  
35 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; 35 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
36 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; 36 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
37 37
@@ -55,15 +55,15 @@ public class LwM2mCredentialsSecurityInfoValidator { @@ -55,15 +55,15 @@ public class LwM2mCredentialsSecurityInfoValidator {
55 private final LwM2mTransportContext context; 55 private final LwM2mTransportContext context;
56 private final LwM2MTransportServerConfig config; 56 private final LwM2MTransportServerConfig config;
57 57
58 - public EndpointSecurityInfo getEndpointSecurityInfo(String endpoint, LwM2mTransportUtil.LwM2mTypeServer keyValue) { 58 + public TbLwM2MSecurityInfo getEndpointSecurityInfoByCredentialsId(String credentialsId, LwM2mTransportUtil.LwM2mTypeServer keyValue) {
59 CountDownLatch latch = new CountDownLatch(1); 59 CountDownLatch latch = new CountDownLatch(1);
60 - final EndpointSecurityInfo[] resultSecurityStore = new EndpointSecurityInfo[1];  
61 - context.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endpoint).build(), 60 + final TbLwM2MSecurityInfo[] resultSecurityStore = new TbLwM2MSecurityInfo[1];
  61 + context.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(credentialsId).build(),
62 new TransportServiceCallback<>() { 62 new TransportServiceCallback<>() {
63 @Override 63 @Override
64 public void onSuccess(ValidateDeviceCredentialsResponse msg) { 64 public void onSuccess(ValidateDeviceCredentialsResponse msg) {
65 String credentialsBody = msg.getCredentials(); 65 String credentialsBody = msg.getCredentials();
66 - resultSecurityStore[0] = createSecurityInfo(endpoint, credentialsBody, keyValue); 66 + resultSecurityStore[0] = createSecurityInfo(credentialsId, credentialsBody, keyValue);
67 resultSecurityStore[0].setMsg(msg); 67 resultSecurityStore[0].setMsg(msg);
68 resultSecurityStore[0].setDeviceProfile(msg.getDeviceProfile()); 68 resultSecurityStore[0].setDeviceProfile(msg.getDeviceProfile());
69 latch.countDown(); 69 latch.countDown();
@@ -71,8 +71,8 @@ public class LwM2mCredentialsSecurityInfoValidator { @@ -71,8 +71,8 @@ public class LwM2mCredentialsSecurityInfoValidator {
71 71
72 @Override 72 @Override
73 public void onError(Throwable e) { 73 public void onError(Throwable e) {
74 - log.trace("[{}] [{}] Failed to process credentials ", endpoint, e);  
75 - resultSecurityStore[0] = createSecurityInfo(endpoint, null, null); 74 + log.trace("[{}] [{}] Failed to process credentials ", credentialsId, e);
  75 + resultSecurityStore[0] = createSecurityInfo(credentialsId, null, null);
76 latch.countDown(); 76 latch.countDown();
77 } 77 }
78 }); 78 });
@@ -91,8 +91,8 @@ public class LwM2mCredentialsSecurityInfoValidator { @@ -91,8 +91,8 @@ public class LwM2mCredentialsSecurityInfoValidator {
91 * @param keyValue - 91 * @param keyValue -
92 * @return SecurityInfo 92 * @return SecurityInfo
93 */ 93 */
94 - private EndpointSecurityInfo createSecurityInfo(String endpoint, String jsonStr, LwM2mTransportUtil.LwM2mTypeServer keyValue) {  
95 - EndpointSecurityInfo result = new EndpointSecurityInfo(); 94 + private TbLwM2MSecurityInfo createSecurityInfo(String endpoint, String jsonStr, LwM2mTransportUtil.LwM2mTypeServer keyValue) {
  95 + TbLwM2MSecurityInfo result = new TbLwM2MSecurityInfo();
96 LwM2MCredentials credentials = JacksonUtil.fromString(jsonStr, LwM2MCredentials.class); 96 LwM2MCredentials credentials = JacksonUtil.fromString(jsonStr, LwM2MCredentials.class);
97 if (credentials != null) { 97 if (credentials != null) {
98 if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) { 98 if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) {
@@ -104,6 +104,7 @@ public class LwM2mCredentialsSecurityInfoValidator { @@ -104,6 +104,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
104 result.setEndpoint(endpoint); 104 result.setEndpoint(endpoint);
105 result.setSecurityMode(credentials.getBootstrap().getBootstrapServer().getSecurityMode()); 105 result.setSecurityMode(credentials.getBootstrap().getBootstrapServer().getSecurityMode());
106 } else { 106 } else {
  107 + result.setEndpoint(credentials.getClient().getEndpoint());
107 switch (credentials.getClient().getSecurityConfigClientMode()) { 108 switch (credentials.getClient().getSecurityConfigClientMode()) {
108 case NO_SEC: 109 case NO_SEC:
109 createClientSecurityInfoNoSec(result); 110 createClientSecurityInfoNoSec(result);
@@ -125,12 +126,12 @@ public class LwM2mCredentialsSecurityInfoValidator { @@ -125,12 +126,12 @@ public class LwM2mCredentialsSecurityInfoValidator {
125 return result; 126 return result;
126 } 127 }
127 128
128 - private void createClientSecurityInfoNoSec(EndpointSecurityInfo result) { 129 + private void createClientSecurityInfoNoSec(TbLwM2MSecurityInfo result) {
129 result.setSecurityInfo(null); 130 result.setSecurityInfo(null);
130 result.setSecurityMode(NO_SEC); 131 result.setSecurityMode(NO_SEC);
131 } 132 }
132 133
133 - private void createClientSecurityInfoPSK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) { 134 + private void createClientSecurityInfoPSK(TbLwM2MSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
134 PSKClientCredentials pskConfig = (PSKClientCredentials) clientCredentialsConfig; 135 PSKClientCredentials pskConfig = (PSKClientCredentials) clientCredentialsConfig;
135 if (StringUtils.isNotEmpty(pskConfig.getIdentity())) { 136 if (StringUtils.isNotEmpty(pskConfig.getIdentity())) {
136 try { 137 try {
@@ -149,7 +150,7 @@ public class LwM2mCredentialsSecurityInfoValidator { @@ -149,7 +150,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
149 } 150 }
150 } 151 }
151 152
152 - private void createClientSecurityInfoRPK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) { 153 + private void createClientSecurityInfoRPK(TbLwM2MSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
153 RPKClientCredentials rpkConfig = (RPKClientCredentials) clientCredentialsConfig; 154 RPKClientCredentials rpkConfig = (RPKClientCredentials) clientCredentialsConfig;
154 try { 155 try {
155 if (rpkConfig.getKey() != null) { 156 if (rpkConfig.getKey() != null) {
@@ -164,7 +165,7 @@ public class LwM2mCredentialsSecurityInfoValidator { @@ -164,7 +165,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
164 } 165 }
165 } 166 }
166 167
167 - private void createClientSecurityInfoX509(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) { 168 + private void createClientSecurityInfoX509(TbLwM2MSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
168 result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint)); 169 result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint));
169 result.setSecurityMode(X509); 170 result.setSecurityMode(X509);
170 } 171 }
@@ -27,6 +27,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; @@ -27,6 +27,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
27 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 27 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
28 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; 28 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
29 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore; 29 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore;
  30 +import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
30 31
31 @Component 32 @Component
32 @RequiredArgsConstructor 33 @RequiredArgsConstructor
@@ -34,7 +35,7 @@ import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore; @@ -34,7 +35,7 @@ import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore;
34 public class TbLwM2MAuthorizer implements Authorizer { 35 public class TbLwM2MAuthorizer implements Authorizer {
35 36
36 private final TbLwM2MDtlsSessionStore sessionStorage; 37 private final TbLwM2MDtlsSessionStore sessionStorage;
37 - private final TbLwM2mSecurityStore securityStore; 38 + private final TbSecurityStore securityStore;
38 private final SecurityChecker securityChecker = new SecurityChecker(); 39 private final SecurityChecker securityChecker = new SecurityChecker();
39 private final LwM2mClientContext clientContext; 40 private final LwM2mClientContext clientContext;
40 41
@@ -29,22 +29,21 @@ import org.eclipse.californium.scandium.dtls.HandshakeResultHandler; @@ -29,22 +29,21 @@ import org.eclipse.californium.scandium.dtls.HandshakeResultHandler;
29 import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier; 29 import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier;
30 import org.eclipse.californium.scandium.dtls.x509.StaticCertificateVerifier; 30 import org.eclipse.californium.scandium.dtls.x509.StaticCertificateVerifier;
31 import org.eclipse.californium.scandium.util.ServerNames; 31 import org.eclipse.californium.scandium.util.ServerNames;
  32 +import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
32 import org.springframework.beans.factory.annotation.Value; 33 import org.springframework.beans.factory.annotation.Value;
33 import org.springframework.stereotype.Component; 34 import org.springframework.stereotype.Component;
34 -import org.springframework.util.StringUtils;  
35 import org.thingsboard.common.util.JacksonUtil; 35 import org.thingsboard.common.util.JacksonUtil;
36 import org.thingsboard.server.common.data.DeviceProfile; 36 import org.thingsboard.server.common.data.DeviceProfile;
37 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; 37 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
  38 +import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials;
38 import org.thingsboard.server.common.msg.EncryptionUtil; 39 import org.thingsboard.server.common.msg.EncryptionUtil;
39 -import org.thingsboard.server.common.transport.TransportService;  
40 -import org.thingsboard.server.common.transport.TransportServiceCallback;  
41 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 40 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
42 import org.thingsboard.server.common.transport.util.SslUtil; 41 import org.thingsboard.server.common.transport.util.SslUtil;
43 -import org.thingsboard.server.gen.transport.TransportProtos;  
44 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 42 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
45 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 43 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
46 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; 44 import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
47 -import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials; 45 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
  46 +import org.thingsboard.server.transport.lwm2m.server.store.TbEditableSecurityStore;
48 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; 47 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
49 48
50 import javax.annotation.PostConstruct; 49 import javax.annotation.PostConstruct;
@@ -57,8 +56,6 @@ import java.security.cert.CertificateNotYetValidException; @@ -57,8 +56,6 @@ import java.security.cert.CertificateNotYetValidException;
57 import java.security.cert.X509Certificate; 56 import java.security.cert.X509Certificate;
58 import java.util.Arrays; 57 import java.util.Arrays;
59 import java.util.List; 58 import java.util.List;
60 -import java.util.concurrent.CountDownLatch;  
61 -import java.util.concurrent.TimeUnit;  
62 59
63 @Slf4j 60 @Slf4j
64 @Component 61 @Component
@@ -66,9 +63,10 @@ import java.util.concurrent.TimeUnit; @@ -66,9 +63,10 @@ import java.util.concurrent.TimeUnit;
66 @RequiredArgsConstructor 63 @RequiredArgsConstructor
67 public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVerifier { 64 public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVerifier {
68 65
69 - private final TransportService transportService;  
70 private final TbLwM2MDtlsSessionStore sessionStorage; 66 private final TbLwM2MDtlsSessionStore sessionStorage;
71 private final LwM2MTransportServerConfig config; 67 private final LwM2MTransportServerConfig config;
  68 + private final LwM2mCredentialsSecurityInfoValidator securityInfoValidator;
  69 + private final TbEditableSecurityStore securityStore;
72 70
73 @SuppressWarnings("deprecation") 71 @SuppressWarnings("deprecation")
74 private StaticCertificateVerifier staticCertificateVerifier; 72 private StaticCertificateVerifier staticCertificateVerifier;
@@ -119,48 +117,33 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer @@ -119,48 +117,33 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer
119 117
120 String strCert = SslUtil.getCertificateString(cert); 118 String strCert = SslUtil.getCertificateString(cert);
121 String sha3Hash = EncryptionUtil.getSha3Hash(strCert); 119 String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
122 - final ValidateDeviceCredentialsResponse[] deviceCredentialsResponse = new ValidateDeviceCredentialsResponse[1];  
123 - CountDownLatch latch = new CountDownLatch(1);  
124 - transportService.process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(sha3Hash).build(),  
125 - new TransportServiceCallback<>() {  
126 - @Override  
127 - public void onSuccess(ValidateDeviceCredentialsResponse msg) {  
128 - if (!StringUtils.isEmpty(msg.getCredentials())) {  
129 - deviceCredentialsResponse[0] = msg;  
130 - }  
131 - latch.countDown();  
132 - }  
133 -  
134 - @Override  
135 - public void onError(Throwable e) {  
136 - log.error(e.getMessage(), e);  
137 - latch.countDown();  
138 - }  
139 - });  
140 - if (latch.await(10, TimeUnit.SECONDS)) {  
141 - ValidateDeviceCredentialsResponse msg = deviceCredentialsResponse[0];  
142 - if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) {  
143 - LwM2MCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MCredentials.class);  
144 - if(!credentials.getClient().getSecurityConfigClientMode().equals(LwM2MSecurityMode.X509)){  
145 - continue;  
146 - }  
147 - X509ClientCredentials config = (X509ClientCredentials) credentials.getClient();  
148 - String certBody = config.getCert();  
149 - String endpoint = config.getEndpoint();  
150 - if (strCert.equals(certBody)) {  
151 - x509CredentialsFound = true;  
152 - DeviceProfile deviceProfile = msg.getDeviceProfile();  
153 - if (msg.hasDeviceInfo() && deviceProfile != null) {  
154 - sessionStorage.put(endpoint, new TbX509DtlsSessionInfo(cert.getSubjectX500Principal().getName(), msg));  
155 - break; 120 + TbLwM2MSecurityInfo securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(sha3Hash, LwM2mTransportUtil.LwM2mTypeServer.CLIENT);
  121 + ValidateDeviceCredentialsResponse msg = securityInfo != null ? securityInfo.getMsg() : null;
  122 + if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) {
  123 + LwM2MCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MCredentials.class);
  124 + if (!credentials.getClient().getSecurityConfigClientMode().equals(LwM2MSecurityMode.X509)) {
  125 + continue;
  126 + }
  127 + X509ClientCredentials config = (X509ClientCredentials) credentials.getClient();
  128 + String certBody = config.getCert();
  129 + String endpoint = config.getEndpoint();
  130 + if (strCert.equals(certBody)) {
  131 + x509CredentialsFound = true;
  132 + DeviceProfile deviceProfile = msg.getDeviceProfile();
  133 + if (msg.hasDeviceInfo() && deviceProfile != null) {
  134 + sessionStorage.put(endpoint, new TbX509DtlsSessionInfo(cert.getSubjectX500Principal().getName(), msg));
  135 + try {
  136 + securityStore.put(securityInfo);
  137 + } catch (NonUniqueSecurityInfoException e) {
  138 + log.trace("Failed to add security info: {}", securityInfo, e);
156 } 139 }
157 - } else {  
158 - log.trace("[{}][{}] Certificate mismatch. Expected: {}, Actual: {}", endpoint, sha3Hash, strCert, certBody); 140 + break;
159 } 141 }
  142 + } else {
  143 + log.trace("[{}][{}] Certificate mismatch. Expected: {}, Actual: {}", endpoint, sha3Hash, strCert, certBody);
160 } 144 }
161 } 145 }
162 - } catch (InterruptedException |  
163 - CertificateEncodingException | 146 + } catch (CertificateEncodingException |
164 CertificateExpiredException | 147 CertificateExpiredException |
165 CertificateNotYetValidException e) { 148 CertificateNotYetValidException e) {
166 log.error(e.getMessage(), e); 149 log.error(e.getMessage(), e);
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MSecurityInfo.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/EndpointSecurityInfo.java
@@ -24,7 +24,7 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes @@ -24,7 +24,7 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes
24 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig; 24 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig;
25 25
26 @Data 26 @Data
27 -public class EndpointSecurityInfo { 27 +public class TbLwM2MSecurityInfo {
28 private ValidateDeviceCredentialsResponse msg; 28 private ValidateDeviceCredentialsResponse msg;
29 private SecurityInfo securityInfo; 29 private SecurityInfo securityInfo;
30 private SecurityMode securityMode; 30 private SecurityMode securityMode;
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at 6 * You may obtain a copy of the License at
7 * 7 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 8 + * http://www.apache.org/licenses/LICENSE-2.0
9 * 9 *
10 * Unless required by applicable law or agreed to in writing, software 10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, 11 * distributed under the License is distributed on an "AS IS" BASIS,
@@ -31,7 +31,6 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance; @@ -31,7 +31,6 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance;
31 import org.eclipse.leshan.core.node.LwM2mPath; 31 import org.eclipse.leshan.core.node.LwM2mPath;
32 import org.eclipse.leshan.core.node.LwM2mResource; 32 import org.eclipse.leshan.core.node.LwM2mResource;
33 import org.eclipse.leshan.core.observation.Observation; 33 import org.eclipse.leshan.core.observation.Observation;
34 -import org.eclipse.leshan.core.request.ContentFormat;  
35 import org.eclipse.leshan.core.request.WriteRequest; 34 import org.eclipse.leshan.core.request.WriteRequest;
36 import org.eclipse.leshan.core.response.ReadResponse; 35 import org.eclipse.leshan.core.response.ReadResponse;
37 import org.eclipse.leshan.server.registration.Registration; 36 import org.eclipse.leshan.server.registration.Registration;
@@ -58,6 +57,8 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; @@ -58,6 +57,8 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
58 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 57 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
59 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; 58 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
60 import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; 59 import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor;
  60 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientState;
  61 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientStateException;
61 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 62 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
62 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 63 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
63 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; 64 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
@@ -91,7 +92,6 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWN @@ -91,7 +92,6 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWN
91 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING; 92 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
92 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; 93 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
93 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto; 94 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto;
94 -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED;  
95 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST; 95 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST;
96 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_ID; 96 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_ID;
97 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID; 97 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID;
@@ -99,6 +99,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L @@ -99,6 +99,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
99 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; 99 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
100 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY; 100 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY;
101 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; 101 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE;
  102 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_WARN;
102 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2; 103 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2;
103 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER; 104 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
104 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; 105 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
@@ -182,32 +183,38 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -182,32 +183,38 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
182 */ 183 */
183 public void onRegistered(Registration registration, Collection<Observation> previousObservations) { 184 public void onRegistered(Registration registration, Collection<Observation> previousObservations) {
184 registrationExecutor.submit(() -> { 185 registrationExecutor.submit(() -> {
  186 + LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint());
185 try { 187 try {
186 log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId()); 188 log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId());
187 - LwM2mClient lwM2MClient = this.clientContext.registerOrUpdate(registration);  
188 if (lwM2MClient != null) { 189 if (lwM2MClient != null) {
189 - SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);  
190 - if (sessionInfo != null) {  
191 - transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));  
192 - TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()  
193 - .setSessionInfo(sessionInfo)  
194 - .setSessionEvent(DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN))  
195 - .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build())  
196 - .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().build())  
197 - .build();  
198 - transportService.process(msg, null);  
199 - this.getInfoFirmwareUpdate(lwM2MClient, null);  
200 - this.getInfoSoftwareUpdate(lwM2MClient, null);  
201 - this.initLwM2mFromClientValue(registration, lwM2MClient);  
202 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId());  
203 - } else {  
204 - log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);  
205 - } 190 + this.clientContext.register(lwM2MClient, registration);
  191 + this.sendLogsToThingsboard(lwM2MClient, LOG_LW2M_INFO + ": Client registered with registration id: " + registration.getId());
  192 + SessionInfoProto sessionInfo = lwM2MClient.getSession();
  193 + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
  194 + TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()
  195 + .setSessionInfo(sessionInfo)
  196 + .setSessionEvent(DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN))
  197 + .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build())
  198 + .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().build())
  199 + .build();
  200 + transportService.process(msg, null);
  201 + this.getInfoFirmwareUpdate(lwM2MClient, null);
  202 + this.getInfoSoftwareUpdate(lwM2MClient, null);
  203 + this.initClientTelemetry(lwM2MClient);
206 } else { 204 } else {
207 - log.error("Client: [{}] onRegistered [{}] name [{}] lwM2MClient ", registration.getId(), registration.getEndpoint(), null); 205 + log.error("Client: [{}] onRegistered [{}] name [{}] lwM2MClient ", registration.getId(), registration.getEndpoint(), null);
  206 + }
  207 + } catch (LwM2MClientStateException stateException) {
  208 + if (LwM2MClientState.UNREGISTERED.equals(stateException.getState())) {
  209 + log.info("[{}] retry registration due to race condition: [{}].", registration.getEndpoint(), stateException.getState());
  210 + // Race condition detected and the client was in progress of unregistration while new registration arrived. Let's try again.
  211 + onRegistered(registration, previousObservations);
  212 + } else {
  213 + this.sendLogsToThingsboard(lwM2MClient, LOG_LW2M_WARN + ": Client registration failed due to invalid state: " + stateException.getState());
208 } 214 }
209 } catch (Throwable t) { 215 } catch (Throwable t) {
210 log.error("[{}] endpoint [{}] error Unable registration.", registration.getEndpoint(), t); 216 log.error("[{}] endpoint [{}] error Unable registration.", registration.getEndpoint(), t);
  217 + this.sendLogsToThingsboard(lwM2MClient, LOG_LW2M_WARN + ": Client registration failed due to: " + t.getMessage());
211 } 218 }
212 }); 219 });
213 } 220 }
@@ -219,25 +226,26 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -219,25 +226,26 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
219 */ 226 */
220 public void updatedReg(Registration registration) { 227 public void updatedReg(Registration registration) {
221 updateRegistrationExecutor.submit(() -> { 228 updateRegistrationExecutor.submit(() -> {
  229 + LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
222 try { 230 try {
223 - LwM2mClient client = clientContext.getOrRegister(registration);  
224 - if (client != null && client.getSession() != null) {  
225 - SessionInfoProto sessionInfo = client.getSession();  
226 - this.reportActivityAndRegister(sessionInfo);  
227 - if (registration.getBindingMode().useQueueMode()) {  
228 - LwM2mQueuedRequest request;  
229 - while ((request = client.getQueuedRequests().poll()) != null) {  
230 - request.send();  
231 - } 231 + clientContext.updateRegistration(lwM2MClient, registration);
  232 + TransportProtos.SessionInfoProto sessionInfo = lwM2MClient.getSession();
  233 + this.reportActivityAndRegister(sessionInfo);
  234 + if (registration.usesQueueMode()) {
  235 + LwM2mQueuedRequest request;
  236 + while ((request = lwM2MClient.getQueuedRequests().poll()) != null) {
  237 + request.send();
232 } 238 }
233 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client update Registration", registration.getId()); 239 + }
  240 + } catch (LwM2MClientStateException stateException) {
  241 + if (LwM2MClientState.UNREGISTERED.equals(stateException.getState())) {
  242 + log.info("[{}] update registration failed because client was already unregistered: [{}].", registration.getEndpoint(), stateException.getState());
234 } else { 243 } else {
235 - log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);  
236 - this.sendLogsToThingsboard(LOG_LW2M_ERROR + ": Client update Registration", registration.getId()); 244 + log.info("[{}] update registration: [{}] {}.", registration.getEndpoint(), stateException.getState(), stateException.getMessage());
237 } 245 }
238 } catch (Throwable t) { 246 } catch (Throwable t) {
239 log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t); 247 log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t);
240 - this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client update Registration, %s", t.getMessage()), registration.getId()); 248 + this.sendLogsToThingsboard(lwM2MClient, LOG_LW2M_ERROR + String.format(": Client update Registration, %s", t.getMessage()));
241 } 249 }
242 }); 250 });
243 } 251 }
@@ -248,34 +256,32 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -248,34 +256,32 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
248 */ 256 */
249 public void unReg(Registration registration, Collection<Observation> observations) { 257 public void unReg(Registration registration, Collection<Observation> observations) {
250 unRegistrationExecutor.submit(() -> { 258 unRegistrationExecutor.submit(() -> {
  259 + LwM2mClient client = clientContext.getClientByEndpoint(registration.getEndpoint());
251 try { 260 try {
252 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId());  
253 - this.closeClientSession(registration); 261 + this.sendLogsToThingsboard(client, LOG_LW2M_INFO + ": Client unRegistration");
  262 + clientContext.unregister(client, registration);
  263 + SessionInfoProto sessionInfo = client.getSession();
  264 + if (sessionInfo != null) {
  265 + transportService.deregisterSession(sessionInfo);
  266 + sessionStore.remove(registration.getEndpoint());
  267 + this.doCloseSession(sessionInfo);
  268 + log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());
  269 + } else {
  270 + log.error("Client close session: [{}] unReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);
  271 + }
  272 + } catch (LwM2MClientStateException stateException) {
  273 + log.info("[{}] delete registration: [{}] {}.", registration.getEndpoint(), stateException.getState(), stateException.getMessage());
254 } catch (Throwable t) { 274 } catch (Throwable t) {
255 log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); 275 log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t);
256 - this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client Unable un Registration, %s", t.getMessage()), registration.getId()); 276 + this.sendLogsToThingsboard(client, LOG_LW2M_ERROR + String.format(": Client Unable un Registration, %s", t.getMessage()));
257 } 277 }
258 }); 278 });
259 } 279 }
260 280
261 - private void closeClientSession(Registration registration) {  
262 - SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registration);  
263 - if (sessionInfo != null) {  
264 - transportService.deregisterSession(sessionInfo);  
265 - sessionStore.remove(registration.getEndpoint());  
266 - this.doCloseSession(sessionInfo);  
267 - clientContext.removeClientByRegistrationId(registration.getId());  
268 - log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());  
269 - } else {  
270 - log.error("Client close session: [{}] unReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);  
271 - }  
272 - }  
273 -  
274 @Override 281 @Override
275 public void onSleepingDev(Registration registration) { 282 public void onSleepingDev(Registration registration) {
276 log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint()); 283 log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint());
277 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is sleeping!", registration.getId());  
278 - 284 + this.sendLogsToThingsboard(clientContext.getClientByEndpoint(registration.getEndpoint()), LOG_LW2M_INFO + ": Client is sleeping!");
279 //TODO: associate endpointId with device information. 285 //TODO: associate endpointId with device information.
280 } 286 }
281 287
@@ -285,8 +291,11 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -285,8 +291,11 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
285 @Override 291 @Override
286 public void setCancelObservationsAll(Registration registration) { 292 public void setCancelObservationsAll(Registration registration) {
287 if (registration != null) { 293 if (registration != null) {
288 - this.lwM2mTransportRequest.sendAllRequest(registration, null, OBSERVE_CANCEL_ALL,  
289 - null, null, this.config.getTimeout(), null); 294 + LwM2mClient client = clientContext.getClientByEndpoint(registration.getEndpoint());
  295 + if (client != null && client.getRegistration() != null && client.getRegistration().getId().equals(registration.getId())) {
  296 + this.lwM2mTransportRequest.sendAllRequest(client, null, OBSERVE_CANCEL_ALL,
  297 + null, null, this.config.getTimeout(), null);
  298 + }
290 } 299 }
291 } 300 }
292 301
@@ -300,7 +309,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -300,7 +309,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
300 @Override 309 @Override
301 public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) { 310 public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) {
302 if (response.getContent() != null) { 311 if (response.getContent() != null) {
303 - LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); 312 + LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
304 ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider()); 313 ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider());
305 if (objectModelVersion != null) { 314 if (objectModelVersion != null) {
306 if (response.getContent() instanceof LwM2mObject) { 315 if (response.getContent() instanceof LwM2mObject) {
@@ -332,7 +341,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -332,7 +341,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
332 } 341 }
333 String msg = String.format("%s: type operation %s path - %s value - %s", LOG_LW2M_INFO, 342 String msg = String.format("%s: type operation %s path - %s value - %s", LOG_LW2M_INFO,
334 READ, pathIdVer, value); 343 READ, pathIdVer, value);
335 - this.sendLogsToThingsboard(msg, registration.getId()); 344 + this.sendLogsToThingsboard(lwM2MClient, msg);
336 rpcRequest.setValueMsg(String.format("%s", value)); 345 rpcRequest.setValueMsg(String.format("%s", value));
337 this.sentRpcResponse(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE); 346 this.sentRpcResponse(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE);
338 } 347 }
@@ -350,9 +359,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -350,9 +359,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
350 */ 359 */
351 @Override 360 @Override
352 public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) { 361 public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
353 - LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo); 362 + LwM2mClient lwM2MClient = clientContext.getClientBySessionInfo(sessionInfo);
354 if (msg.getSharedUpdatedCount() > 0 && lwM2MClient != null) { 363 if (msg.getSharedUpdatedCount() > 0 && lwM2MClient != null) {
355 - log.warn ("2) OnAttributeUpdate, SharedUpdatedList() [{}]", msg.getSharedUpdatedList()); 364 + log.warn("2) OnAttributeUpdate, SharedUpdatedList() [{}]", msg.getSharedUpdatedList());
356 msg.getSharedUpdatedList().forEach(tsKvProto -> { 365 msg.getSharedUpdatedList().forEach(tsKvProto -> {
357 String pathName = tsKvProto.getKv().getKey(); 366 String pathName = tsKvProto.getKv().getKey();
358 String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); 367 String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName);
@@ -377,13 +386,13 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -377,13 +386,13 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
377 log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew); 386 log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew);
378 String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", 387 String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated",
379 LOG_LW2M_ERROR, pathIdVer, valueNew); 388 LOG_LW2M_ERROR, pathIdVer, valueNew);
380 - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); 389 + this.sendLogsToThingsboard(lwM2MClient, logMsg);
381 } 390 }
382 } else if (!isFwSwWords(pathName)) { 391 } else if (!isFwSwWords(pathName)) {
383 log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew); 392 log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew);
384 String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated", 393 String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated",
385 LOG_LW2M_ERROR, pathName, valueNew); 394 LOG_LW2M_ERROR, pathName, valueNew);
386 - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); 395 + this.sendLogsToThingsboard(lwM2MClient, logMsg);
387 } 396 }
388 397
389 }); 398 });
@@ -396,9 +405,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -396,9 +405,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
396 } 405 }
397 }); 406 });
398 log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo); 407 log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);
399 - }  
400 - else if (lwM2MClient == null) {  
401 - log.error ("OnAttributeUpdate, lwM2MClient is null"); 408 + } else if (lwM2MClient == null) {
  409 + log.error("OnAttributeUpdate, lwM2MClient is null");
402 } 410 }
403 } 411 }
404 412
@@ -408,12 +416,11 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -408,12 +416,11 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
408 */ 416 */
409 @Override 417 @Override
410 public void onDeviceProfileUpdate(SessionInfoProto sessionInfo, DeviceProfile deviceProfile) { 418 public void onDeviceProfileUpdate(SessionInfoProto sessionInfo, DeviceProfile deviceProfile) {
411 - Set<LwM2mClient> clients = clientContext.getLwM2mClients()  
412 - .stream().filter(e -> e.getProfileId().equals(deviceProfile.getUuidId())).collect(Collectors.toSet()); 419 + List<LwM2mClient> clients = clientContext.getLwM2mClients()
  420 + .stream().filter(e -> e.getProfileId().equals(deviceProfile.getUuidId())).collect(Collectors.toList());
413 clients.forEach(client -> client.onDeviceProfileUpdate(deviceProfile)); 421 clients.forEach(client -> client.onDeviceProfileUpdate(deviceProfile));
414 - Set<String> registrationIds = clients.stream().map(LwM2mClient::getRegistration).map(Registration::getId).collect(Collectors.toSet());  
415 - if (registrationIds.size() > 0) {  
416 - this.onDeviceProfileUpdate(registrationIds, deviceProfile); 422 + if (clients.size() > 0) {
  423 + this.onDeviceProfileUpdate(clients, deviceProfile);
417 } 424 }
418 } 425 }
419 426
@@ -446,7 +453,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -446,7 +453,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
446 public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) { 453 public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) {
447 // #1 454 // #1
448 this.checkRpcRequestTimeout(); 455 this.checkRpcRequestTimeout();
449 - log.warn ("4) toDeviceRpcRequestMsg: [{}], sessionUUID: [{}]", toDeviceRpcRequestMsg, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); 456 + log.warn("4) toDeviceRpcRequestMsg: [{}], sessionUUID: [{}]", toDeviceRpcRequestMsg, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
450 String bodyParams = StringUtils.trimToNull(toDeviceRpcRequestMsg.getParams()) != null ? toDeviceRpcRequestMsg.getParams() : "null"; 457 String bodyParams = StringUtils.trimToNull(toDeviceRpcRequestMsg.getParams()) != null ? toDeviceRpcRequestMsg.getParams() : "null";
451 LwM2mTypeOper lwM2mTypeOper = setValidTypeOper(toDeviceRpcRequestMsg.getMethodName()); 458 LwM2mTypeOper lwM2mTypeOper = setValidTypeOper(toDeviceRpcRequestMsg.getMethodName());
452 UUID requestUUID = new UUID(toDeviceRpcRequestMsg.getRequestIdMSB(), toDeviceRpcRequestMsg.getRequestIdLSB()); 459 UUID requestUUID = new UUID(toDeviceRpcRequestMsg.getRequestIdMSB(), toDeviceRpcRequestMsg.getRequestIdLSB());
@@ -454,13 +461,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -454,13 +461,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
454 this.rpcSubscriptions.put(requestUUID, toDeviceRpcRequestMsg.getExpirationTime()); 461 this.rpcSubscriptions.put(requestUUID, toDeviceRpcRequestMsg.getExpirationTime());
455 Lwm2mClientRpcRequest lwm2mClientRpcRequest = null; 462 Lwm2mClientRpcRequest lwm2mClientRpcRequest = null;
456 try { 463 try {
457 - Registration registration = clientContext.getClient(sessionInfo).getRegistration(); 464 + LwM2mClient client = clientContext.getClientBySessionInfo(sessionInfo);
  465 + Registration registration = client.getRegistration();
458 lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this); 466 lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this);
459 if (lwm2mClientRpcRequest.getErrorMsg() != null) { 467 if (lwm2mClientRpcRequest.getErrorMsg() != null) {
460 lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); 468 lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
461 this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo); 469 this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
462 } else { 470 } else {
463 - lwM2mTransportRequest.sendAllRequest(registration, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(), 471 + lwM2mTransportRequest.sendAllRequest(client, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(),
464 null, 472 null,
465 lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(), 473 lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(),
466 this.config.getTimeout(), lwm2mClientRpcRequest); 474 this.config.getTimeout(), lwm2mClientRpcRequest);
@@ -506,7 +514,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -506,7 +514,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
506 514
507 @Override 515 @Override
508 public void onToDeviceRpcResponse(TransportProtos.ToDeviceRpcResponseMsg toDeviceResponse, SessionInfoProto sessionInfo) { 516 public void onToDeviceRpcResponse(TransportProtos.ToDeviceRpcResponseMsg toDeviceResponse, SessionInfoProto sessionInfo) {
509 - log.warn ("5) onToDeviceRpcResponse: [{}], sessionUUID: [{}]", toDeviceResponse, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); 517 + log.warn("5) onToDeviceRpcResponse: [{}], sessionUUID: [{}]", toDeviceResponse, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
510 transportService.process(sessionInfo, toDeviceResponse, null); 518 transportService.process(sessionInfo, toDeviceResponse, null);
511 } 519 }
512 520
@@ -515,17 +523,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -515,17 +523,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
515 } 523 }
516 524
517 /** 525 /**
518 - * Trigger Server path = "/1/0/8"  
519 - * <p>  
520 - * Trigger bootStrap path = "/1/0/9" - have to implemented on client  
521 - */  
522 - @Override  
523 - public void doTrigger(Registration registration, String path) {  
524 - lwM2mTransportRequest.sendAllRequest(registration, path, EXECUTE,  
525 - ContentFormat.TLV.getName(), null, this.config.getTimeout(), null);  
526 - }  
527 -  
528 - /**  
529 * Deregister session in transport 526 * Deregister session in transport
530 * 527 *
531 * @param sessionInfo - lwm2m client 528 * @param sessionInfo - lwm2m client
@@ -558,7 +555,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -558,7 +555,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
558 @Override 555 @Override
559 public void onAwakeDev(Registration registration) { 556 public void onAwakeDev(Registration registration) {
560 log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); 557 log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint());
561 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration.getId()); 558 + this.sendLogsToThingsboard(clientContext.getClientByEndpoint(registration.getEndpoint()), LOG_LW2M_INFO + ": Client is awake!");
562 //TODO: associate endpointId with device information. 559 //TODO: associate endpointId with device information.
563 } 560 }
564 561
@@ -567,13 +564,17 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -567,13 +564,17 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
567 * @param registrationId - Id of Registration LwM2M Client 564 * @param registrationId - Id of Registration LwM2M Client
568 */ 565 */
569 @Override 566 @Override
570 - public void sendLogsToThingsboard(String logMsg, String registrationId) {  
571 - SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registrationId);  
572 - if (logMsg != null && sessionInfo != null) { 567 + public void sendLogsToThingsboard(String registrationId, String logMsg) {
  568 + sendLogsToThingsboard(clientContext.getClientByRegistrationId(registrationId), logMsg);
  569 + }
  570 +
  571 + @Override
  572 + public void sendLogsToThingsboard(LwM2mClient client, String logMsg) {
  573 + if (logMsg != null && client != null && client.getSession() != null) {
573 if (logMsg.length() > 1024) { 574 if (logMsg.length() > 1024) {
574 logMsg = logMsg.substring(0, 1024); 575 logMsg = logMsg.substring(0, 1024);
575 } 576 }
576 - this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo); 577 + this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), client.getSession());
577 } 578 }
578 } 579 }
579 580
@@ -586,24 +587,23 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -586,24 +587,23 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
586 * - Read Request to the client after registration to read all resource values for all objects 587 * - Read Request to the client after registration to read all resource values for all objects
587 * - then Observe Request to the client marked as observe from the profile configuration. 588 * - then Observe Request to the client marked as observe from the profile configuration.
588 * 589 *
589 - * @param registration - Registration LwM2M Client  
590 - * @param lwM2MClient - object with All parameters off client 590 + * @param lwM2MClient - object with All parameters off client
591 */ 591 */
592 - private void initLwM2mFromClientValue(Registration registration, LwM2mClient lwM2MClient) {  
593 - LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration);  
594 - Set<String> clientObjects = clientContext.getSupportedIdVerInClient(registration); 592 + private void initClientTelemetry(LwM2mClient lwM2MClient) {
  593 + LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(lwM2MClient.getProfileId());
  594 + Set<String> clientObjects = clientContext.getSupportedIdVerInClient(lwM2MClient);
595 if (clientObjects != null && clientObjects.size() > 0) { 595 if (clientObjects != null && clientObjects.size() > 0) {
596 if (LWM2M_STRATEGY_2 == LwM2mTransportUtil.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { 596 if (LWM2M_STRATEGY_2 == LwM2mTransportUtil.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
597 // #2 597 // #2
598 lwM2MClient.getPendingReadRequests().addAll(clientObjects); 598 lwM2MClient.getPendingReadRequests().addAll(clientObjects);
599 - clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, READ, ContentFormat.TLV.getName(), 599 + clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(lwM2MClient, path, READ,
600 null, this.config.getTimeout(), null)); 600 null, this.config.getTimeout(), null));
601 } 601 }
602 // #1 602 // #1
603 - this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, READ, clientObjects);  
604 - this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, OBSERVE, clientObjects);  
605 - this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, WRITE_ATTRIBUTES, clientObjects);  
606 - this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, DISCOVER, clientObjects); 603 + this.initReadAttrTelemetryObserveToClient(lwM2MClient, READ, clientObjects);
  604 + this.initReadAttrTelemetryObserveToClient(lwM2MClient, OBSERVE, clientObjects);
  605 + this.initReadAttrTelemetryObserveToClient(lwM2MClient, WRITE_ATTRIBUTES, clientObjects);
  606 + this.initReadAttrTelemetryObserveToClient(lwM2MClient, DISCOVER, clientObjects);
607 } 607 }
608 } 608 }
609 609
@@ -645,7 +645,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -645,7 +645,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
645 * @param path - resource 645 * @param path - resource
646 */ 646 */
647 private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { 647 private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) {
648 - LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); 648 + LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
649 if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config.getModelProvider())) { 649 if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config.getModelProvider())) {
650 /** version != null 650 /** version != null
651 * set setClient_fw_info... = value 651 * set setClient_fw_info... = value
@@ -740,15 +740,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -740,15 +740,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
740 } 740 }
741 } 741 }
742 742
743 - /**  
744 - * Start observe/read: Attr/Telemetry  
745 - * #1 - Analyze: path in resource profile == client resource  
746 - *  
747 - * @param registration -  
748 - */  
749 - private void initReadAttrTelemetryObserveToClient(Registration registration, LwM2mClient lwM2MClient,  
750 - LwM2mTypeOper typeOper, Set<String> clientObjects) {  
751 - LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration); 743 + private void initReadAttrTelemetryObserveToClient(LwM2mClient lwM2MClient, LwM2mTypeOper typeOper, Set<String> clientObjects) {
  744 + LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(lwM2MClient.getProfileId());
752 Set<String> result = null; 745 Set<String> result = null;
753 ConcurrentHashMap<String, Object> params = null; 746 ConcurrentHashMap<String, Object> params = null;
754 if (READ.equals(typeOper)) { 747 if (READ.equals(typeOper)) {
@@ -768,28 +761,42 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -768,28 +761,42 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
768 params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile()); 761 params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile());
769 result = params.keySet(); 762 result = params.keySet();
770 } 763 }
771 - if (result != null && !result.isEmpty()) {  
772 - // #1  
773 - Set<String> pathSend = result.stream().filter(target -> {  
774 - return target.split(LWM2M_SEPARATOR_PATH).length < 3 ?  
775 - clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]) :  
776 - clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1] + "/" + target.split(LWM2M_SEPARATOR_PATH)[2]);  
777 - } 764 + sendRequestsToClient(lwM2MClient, typeOper, clientObjects, result, params);
  765 + }
  766 +
  767 + private void sendRequestsToClient(LwM2mClient lwM2MClient, LwM2mTypeOper operationType, Set<String> supportedObjectIds, Set<String> desiredObjectIds, ConcurrentHashMap<String, Object> params) {
  768 + if (desiredObjectIds != null && !desiredObjectIds.isEmpty()) {
  769 + Set<String> targetObjectIds = desiredObjectIds.stream().filter(target -> isSupportedTargetId(supportedObjectIds, target)
778 ).collect(Collectors.toUnmodifiableSet()); 770 ).collect(Collectors.toUnmodifiableSet());
779 - if (!pathSend.isEmpty()) {  
780 - lwM2MClient.getPendingReadRequests().addAll(pathSend);  
781 - ConcurrentHashMap<String, Object> finalParams = params;  
782 - pathSend.forEach(target -> {  
783 - lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(),  
784 - finalParams != null ? finalParams.get(target) : null, this.config.getTimeout(), null); 771 + if (!targetObjectIds.isEmpty()) {
  772 + //TODO: remove this side effect?
  773 + lwM2MClient.getPendingReadRequests().addAll(targetObjectIds);
  774 + targetObjectIds.forEach(target -> {
  775 + Object additionalParams = params != null ? params.get(target) : null;
  776 + lwM2mTransportRequest.sendAllRequest(lwM2MClient, target, operationType, additionalParams, this.config.getTimeout(), null);
785 }); 777 });
786 - if (OBSERVE.equals(typeOper)) { 778 + if (OBSERVE.equals(operationType)) {
787 lwM2MClient.initReadValue(this, null); 779 lwM2MClient.initReadValue(this, null);
788 } 780 }
789 } 781 }
790 } 782 }
791 } 783 }
792 784
  785 + private boolean isSupportedTargetId(Set<String> supportedIds, String targetId) {
  786 + String[] targetIdParts = targetId.split(LWM2M_SEPARATOR_PATH);
  787 + if (targetIdParts.length <= 1) {
  788 + return false;
  789 + }
  790 + String targetIdSearch = targetIdParts[0];
  791 + for (int i = 1; i < targetIdParts.length; i++) {
  792 + targetIdSearch += "/" + targetIdParts[i];
  793 + if (supportedIds.contains(targetIdSearch)) {
  794 + return true;
  795 + }
  796 + }
  797 + return false;
  798 + }
  799 +
793 private ConcurrentHashMap<String, Object> getPathForWriteAttributes(JsonObject objectJson) { 800 private ConcurrentHashMap<String, Object> getPathForWriteAttributes(JsonObject objectJson) {
794 ConcurrentHashMap<String, Object> pathAttributes = new Gson().fromJson(objectJson.toString(), 801 ConcurrentHashMap<String, Object> pathAttributes = new Gson().fromJson(objectJson.toString(),
795 new TypeToken<ConcurrentHashMap<String, Object>>() { 802 new TypeToken<ConcurrentHashMap<String, Object>>() {
@@ -798,7 +805,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -798,7 +805,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
798 } 805 }
799 806
800 private void onDeviceUpdate(LwM2mClient lwM2MClient, Device device, Optional<DeviceProfile> deviceProfileOpt) { 807 private void onDeviceUpdate(LwM2mClient lwM2MClient, Device device, Optional<DeviceProfile> deviceProfileOpt) {
801 - deviceProfileOpt.ifPresent(deviceProfile -> this.onDeviceProfileUpdate(Collections.singleton(lwM2MClient.getRegistration().getId()), deviceProfile)); 808 + deviceProfileOpt.ifPresent(deviceProfile -> this.onDeviceProfileUpdate(Collections.singletonList(lwM2MClient), deviceProfile));
802 lwM2MClient.onDeviceUpdate(device, deviceProfileOpt); 809 lwM2MClient.onDeviceUpdate(device, deviceProfileOpt);
803 } 810 }
804 811
@@ -843,7 +850,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -843,7 +850,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
843 } 850 }
844 851
845 private TransportProtos.KeyValueProto getKvToThingsboard(String pathIdVer, Registration registration) { 852 private TransportProtos.KeyValueProto getKvToThingsboard(String pathIdVer, Registration registration) {
846 - LwM2mClient lwM2MClient = this.clientContext.getClientByRegistrationId(registration.getId()); 853 + LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint());
847 JsonObject names = clientContext.getProfiles().get(lwM2MClient.getProfileId()).getPostKeyNameProfile(); 854 JsonObject names = clientContext.getProfiles().get(lwM2MClient.getProfileId()).getPostKeyNameProfile();
848 if (names != null && names.has(pathIdVer)) { 855 if (names != null && names.has(pathIdVer)) {
849 String resourceName = names.get(pathIdVer).getAsString(); 856 String resourceName = names.get(pathIdVer).getAsString();
@@ -858,7 +865,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -858,7 +865,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
858 valueKvProto = new JsonObject(); 865 valueKvProto = new JsonObject();
859 Object finalvalueKvProto = valueKvProto; 866 Object finalvalueKvProto = valueKvProto;
860 Gson gson = new GsonBuilder().create(); 867 Gson gson = new GsonBuilder().create();
861 - resourceValue.getValues().forEach((k, v) -> { 868 + resourceValue.getInstances().forEach((k, v) -> {
862 Object val = this.converter.convertValue(v, currentType, expectedType, 869 Object val = this.converter.convertValue(v, currentType, expectedType,
863 new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); 870 new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
864 JsonElement element = gson.toJsonTree(val, val.getClass()); 871 JsonElement element = gson.toJsonTree(val, val.getClass());
@@ -892,9 +899,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -892,9 +899,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
892 ResourceModel.Type expectedType = this.helper.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer); 899 ResourceModel.Type expectedType = this.helper.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer);
893 return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, 900 return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType,
894 new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); 901 new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
895 - }  
896 -  
897 - else { 902 + } else {
898 return null; 903 return null;
899 } 904 }
900 } 905 }
@@ -955,10 +960,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -955,10 +960,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
955 * #6.1 - update WriteAttribute 960 * #6.1 - update WriteAttribute
956 * #6.2 - del WriteAttribute 961 * #6.2 - del WriteAttribute
957 * 962 *
958 - * @param registrationIds -  
959 - * @param deviceProfile - 963 + * @param clients -
  964 + * @param deviceProfile -
960 */ 965 */
961 - private void onDeviceProfileUpdate(Set<String> registrationIds, DeviceProfile deviceProfile) { 966 + private void onDeviceProfileUpdate(List<LwM2mClient> clients, DeviceProfile deviceProfile) {
962 LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone(); 967 LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone();
963 if (clientContext.profileUpdate(deviceProfile) != null) { 968 if (clientContext.profileUpdate(deviceProfile) != null) {
964 // #1 969 // #1
@@ -1009,15 +1014,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1009,15 +1014,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1009 1014
1010 // #3.4, #6 1015 // #3.4, #6
1011 if (!attributeLwm2mOld.equals(attributeLwm2mNew)) { 1016 if (!attributeLwm2mOld.equals(attributeLwm2mNew)) {
1012 - this.getAnalyzerAttributeLwm2m(registrationIds, attributeLwm2mOld, attributeLwm2mNew); 1017 + this.getAnalyzerAttributeLwm2m(clients, attributeLwm2mOld, attributeLwm2mNew);
1013 } 1018 }
1014 1019
1015 // #4.1 add 1020 // #4.1 add
1016 if (sendAttrToThingsboard.getPathPostParametersAdd().size() > 0) { 1021 if (sendAttrToThingsboard.getPathPostParametersAdd().size() > 0) {
1017 // update value in Resources 1022 // update value in Resources
1018 - registrationIds.forEach(registrationId -> {  
1019 - Registration registration = clientContext.getRegistration(registrationId);  
1020 - this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); 1023 + clients.forEach(client -> {
  1024 + this.readObserveFromProfile(client, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
1021 }); 1025 });
1022 } 1026 }
1023 // #4.2 del 1027 // #4.2 del
@@ -1041,15 +1045,15 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1041,15 +1045,15 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1041 // does not include oldObserve 1045 // does not include oldObserve
1042 ResultsAnalyzerParameters postObserveAnalyzer = this.getAnalyzerParameters(sendObserveToClientOld.getPathPostParametersAdd(), sendObserveToClientNew.getPathPostParametersAdd()); 1046 ResultsAnalyzerParameters postObserveAnalyzer = this.getAnalyzerParameters(sendObserveToClientOld.getPathPostParametersAdd(), sendObserveToClientNew.getPathPostParametersAdd());
1043 // send Request observe to Client 1047 // send Request observe to Client
1044 - registrationIds.forEach(registrationId -> {  
1045 - Registration registration = clientContext.getRegistration(registrationId); 1048 + clients.forEach(client -> {
  1049 + Registration registration = client.getRegistration();
1046 if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) { 1050 if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) {
1047 - this.readObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE); 1051 + this.readObserveFromProfile(client, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE);
1048 } 1052 }
1049 // 5.3 del 1053 // 5.3 del
1050 // send Request cancel observe to Client 1054 // send Request cancel observe to Client
1051 if (postObserveAnalyzer.getPathPostParametersDel().size() > 0) { 1055 if (postObserveAnalyzer.getPathPostParametersDel().size() > 0) {
1052 - this.cancelObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersDel()); 1056 + this.cancelObserveFromProfile(client, postObserveAnalyzer.getPathPostParametersDel());
1053 } 1057 }
1054 }); 1058 });
1055 } 1059 }
@@ -1086,19 +1090,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1086,19 +1090,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1086 * Update Resource value after change RezAttrTelemetry in config Profile 1090 * Update Resource value after change RezAttrTelemetry in config Profile
1087 * send response Read to Client and add path to pathResAttrTelemetry in LwM2MClient.getAttrTelemetryObserveValue() 1091 * send response Read to Client and add path to pathResAttrTelemetry in LwM2MClient.getAttrTelemetryObserveValue()
1088 * 1092 *
1089 - * @param registration - Registration LwM2M Client  
1090 - * @param targets - path Resources == [ "/2/0/0", "/2/0/1"] 1093 + * @param targets - path Resources == [ "/2/0/0", "/2/0/1"]
1091 */ 1094 */
1092 - private void readObserveFromProfile(Registration registration, Set<String> targets, LwM2mTypeOper typeOper) { 1095 + private void readObserveFromProfile(LwM2mClient client, Set<String> targets, LwM2mTypeOper typeOper) {
1093 targets.forEach(target -> { 1096 targets.forEach(target -> {
1094 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target)); 1097 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target));
1095 if (pathIds.isResource()) { 1098 if (pathIds.isResource()) {
1096 if (READ.equals(typeOper)) { 1099 if (READ.equals(typeOper)) {
1097 - lwM2mTransportRequest.sendAllRequest(registration, target, typeOper,  
1098 - ContentFormat.TLV.getName(), null, this.config.getTimeout(), null); 1100 + lwM2mTransportRequest.sendAllRequest(client, target, typeOper,
  1101 + null, this.config.getTimeout(), null);
1099 } else if (OBSERVE.equals(typeOper)) { 1102 } else if (OBSERVE.equals(typeOper)) {
1100 - lwM2mTransportRequest.sendAllRequest(registration, target, typeOper,  
1101 - null, null, this.config.getTimeout(), null); 1103 + lwM2mTransportRequest.sendAllRequest(client, target, typeOper,
  1104 + null, this.config.getTimeout(), null);
1102 } 1105 }
1103 } 1106 }
1104 }); 1107 });
@@ -1124,7 +1127,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1124,7 +1127,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1124 * @param attributeLwm2mNew - 1127 * @param attributeLwm2mNew -
1125 * @return 1128 * @return
1126 */ 1129 */
1127 - private void getAnalyzerAttributeLwm2m(Set<String> registrationIds, JsonObject attributeLwm2mOld, JsonObject attributeLwm2mNew) { 1130 + private void getAnalyzerAttributeLwm2m(List<LwM2mClient> clients, JsonObject attributeLwm2mOld, JsonObject attributeLwm2mNew) {
1128 ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters(); 1131 ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters();
1129 ConcurrentHashMap<String, Object> lwm2mAttributesOld = new Gson().fromJson(attributeLwm2mOld.toString(), 1132 ConcurrentHashMap<String, Object> lwm2mAttributesOld = new Gson().fromJson(attributeLwm2mOld.toString(),
1130 new TypeToken<ConcurrentHashMap<String, Object>>() { 1133 new TypeToken<ConcurrentHashMap<String, Object>>() {
@@ -1146,23 +1149,22 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1146,23 +1149,22 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1146 // #6 1149 // #6
1147 // #6.2 1150 // #6.2
1148 if (analyzerParameters.getPathPostParametersAdd().size() > 0) { 1151 if (analyzerParameters.getPathPostParametersAdd().size() > 0) {
1149 - registrationIds.forEach(registrationId -> {  
1150 - Registration registration = this.clientContext.getRegistration(registrationId);  
1151 - Set<String> clientObjects = clientContext.getSupportedIdVerInClient(registration); 1152 + clients.forEach(client -> {
  1153 + Set<String> clientObjects = clientContext.getSupportedIdVerInClient(client);
1152 Set<String> pathSend = analyzerParameters.getPathPostParametersAdd().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1])) 1154 Set<String> pathSend = analyzerParameters.getPathPostParametersAdd().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]))
1153 .collect(Collectors.toUnmodifiableSet()); 1155 .collect(Collectors.toUnmodifiableSet());
1154 if (!pathSend.isEmpty()) { 1156 if (!pathSend.isEmpty()) {
1155 ConcurrentHashMap<String, Object> finalParams = lwm2mAttributesNew; 1157 ConcurrentHashMap<String, Object> finalParams = lwm2mAttributesNew;
1156 - pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TLV.getName(), 1158 + pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(client, target, WRITE_ATTRIBUTES,
1157 finalParams.get(target), this.config.getTimeout(), null)); 1159 finalParams.get(target), this.config.getTimeout(), null));
1158 } 1160 }
1159 }); 1161 });
1160 } 1162 }
1161 // #6.2 1163 // #6.2
1162 if (analyzerParameters.getPathPostParametersDel().size() > 0) { 1164 if (analyzerParameters.getPathPostParametersDel().size() > 0) {
1163 - registrationIds.forEach(registrationId -> {  
1164 - Registration registration = this.clientContext.getRegistration(registrationId);  
1165 - Set<String> clientObjects = clientContext.getSupportedIdVerInClient(registration); 1165 + clients.forEach(client -> {
  1166 + Registration registration = client.getRegistration();
  1167 + Set<String> clientObjects = clientContext.getSupportedIdVerInClient(client);
1166 Set<String> pathSend = analyzerParameters.getPathPostParametersDel().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1])) 1168 Set<String> pathSend = analyzerParameters.getPathPostParametersDel().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]))
1167 .collect(Collectors.toUnmodifiableSet()); 1169 .collect(Collectors.toUnmodifiableSet());
1168 if (!pathSend.isEmpty()) { 1170 if (!pathSend.isEmpty()) {
@@ -1170,8 +1172,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1170,8 +1172,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1170 Map<String, Object> params = (Map<String, Object>) lwm2mAttributesOld.get(target); 1172 Map<String, Object> params = (Map<String, Object>) lwm2mAttributesOld.get(target);
1171 params.clear(); 1173 params.clear();
1172 params.put(OBJECT_VERSION, ""); 1174 params.put(OBJECT_VERSION, "");
1173 - lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TLV.getName(),  
1174 - params, this.config.getTimeout(), null); 1175 + lwM2mTransportRequest.sendAllRequest(client, target, WRITE_ATTRIBUTES, params, this.config.getTimeout(), null);
1175 }); 1176 });
1176 } 1177 }
1177 }); 1178 });
@@ -1179,12 +1180,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1179,12 +1180,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1179 1180
1180 } 1181 }
1181 1182
1182 - private void cancelObserveFromProfile(Registration registration, Set<String> paramAnallyzer) {  
1183 - LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); 1183 + private void cancelObserveFromProfile(LwM2mClient lwM2mClient, Set<String> paramAnallyzer) {
1184 paramAnallyzer.forEach(pathIdVer -> { 1184 paramAnallyzer.forEach(pathIdVer -> {
1185 - if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) {  
1186 - lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, OBSERVE_CANCEL, null,  
1187 - null, this.config.getTimeout(), null); 1185 + if (this.getResourceValueFromLwM2MClient(lwM2mClient, pathIdVer) != null) {
  1186 + lwM2mTransportRequest.sendAllRequest(lwM2mClient, pathIdVer, OBSERVE_CANCEL, null, this.config.getTimeout(), null);
1188 } 1187 }
1189 } 1188 }
1190 ); 1189 );
@@ -1192,14 +1191,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1192,14 +1191,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1192 1191
1193 private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) { 1192 private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) {
1194 if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) { 1193 if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) {
1195 - lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, WRITE_REPLACE,  
1196 - ContentFormat.TLV.getName(), valueNew,  
1197 - this.config.getTimeout(), null); 1194 + lwM2mTransportRequest.sendAllRequest(lwM2MClient, path, WRITE_REPLACE, valueNew, this.config.getTimeout(), null);
1198 } else { 1195 } else {
1199 log.error("Failed update resource [{}] [{}]", path, valueNew); 1196 log.error("Failed update resource [{}] [{}]", path, valueNew);
1200 String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad", 1197 String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad",
1201 LOG_LW2M_ERROR, path, valueNew); 1198 LOG_LW2M_ERROR, path, valueNew);
1202 - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId()); 1199 + this.sendLogsToThingsboard(lwM2MClient, logMsg);
1203 log.info("Failed update resource [{}] [{}]", path, valueNew); 1200 log.info("Failed update resource [{}] [{}]", path, valueNew);
1204 } 1201 }
1205 } 1202 }
@@ -1221,7 +1218,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1221,7 +1218,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1221 */ 1218 */
1222 public String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { 1219 public String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
1223 LwM2mClientProfile profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); 1220 LwM2mClientProfile profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
1224 - LwM2mClient lwM2mClient = clientContext.getClient(sessionInfo); 1221 + LwM2mClient lwM2mClient = clientContext.getClientBySessionInfo(sessionInfo);
1225 return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() 1222 return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
1226 .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey) 1223 .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey)
1227 .orElse(null); 1224 .orElse(null);
@@ -1256,7 +1253,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1256,7 +1253,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1256 * @param sessionInfo 1253 * @param sessionInfo
1257 */ 1254 */
1258 public void updateAttributeFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) { 1255 public void updateAttributeFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) {
1259 - LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo); 1256 + LwM2mClient lwM2MClient = clientContext.getClientBySessionInfo(sessionInfo);
1260 if (lwM2MClient != null) { 1257 if (lwM2MClient != null) {
1261 log.warn("1) UpdateAttributeFromThingsboard, tsKvProtos [{}]", tsKvProtos); 1258 log.warn("1) UpdateAttributeFromThingsboard, tsKvProtos [{}]", tsKvProtos);
1262 tsKvProtos.forEach(tsKvProto -> { 1259 tsKvProtos.forEach(tsKvProto -> {
@@ -1275,8 +1272,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1275,8 +1272,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1275 this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), 1272 this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer),
1276 getValueFromKvProto(tsKvProto.getKv()), pathIdVer); 1273 getValueFromKvProto(tsKvProto.getKv()), pathIdVer);
1277 }); 1274 });
1278 - }  
1279 - else { 1275 + } else {
1280 log.error("UpdateAttributeFromThingsboard, lwM2MClient is null"); 1276 log.error("UpdateAttributeFromThingsboard, lwM2MClient is null");
1281 } 1277 }
1282 } 1278 }
@@ -1285,14 +1281,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1285,14 +1281,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1285 * @param lwM2MClient - 1281 * @param lwM2MClient -
1286 * @return SessionInfoProto - 1282 * @return SessionInfoProto -
1287 */ 1283 */
1288 - private SessionInfoProto getSessionInfoOrCloseSession(LwM2mClient lwM2MClient) {  
1289 - if (lwM2MClient != null) {  
1290 - SessionInfoProto sessionInfoProto = lwM2MClient.getSession();  
1291 - if (sessionInfoProto == null) {  
1292 - log.info("[{}] [{}]", lwM2MClient.getEndpoint(), CLIENT_NOT_AUTHORIZED);  
1293 - this.closeClientSession(lwM2MClient.getRegistration());  
1294 - }  
1295 - return sessionInfoProto; 1284 + private SessionInfoProto getSessionInfo(LwM2mClient lwM2MClient) {
  1285 + if (lwM2MClient != null && lwM2MClient.getSession() != null) {
  1286 + return lwM2MClient.getSession();
1296 } 1287 }
1297 return null; 1288 return null;
1298 } 1289 }
@@ -1302,15 +1293,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1302,15 +1293,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1302 * @return - sessionInfo after access connect client 1293 * @return - sessionInfo after access connect client
1303 */ 1294 */
1304 public SessionInfoProto getSessionInfoOrCloseSession(Registration registration) { 1295 public SessionInfoProto getSessionInfoOrCloseSession(Registration registration) {
1305 - return getSessionInfoOrCloseSession(clientContext.getOrRegister(registration));  
1306 - }  
1307 -  
1308 - /**  
1309 - * @param registrationId -  
1310 - * @return -  
1311 - */  
1312 - private SessionInfoProto getSessionInfoOrCloseSession(String registrationId) {  
1313 - return getSessionInfoOrCloseSession(clientContext.getClientByRegistrationId(registrationId)); 1296 + return getSessionInfo(clientContext.getClientByEndpoint(registration.getEndpoint()));
1314 } 1297 }
1315 1298
1316 /** 1299 /**
@@ -1340,7 +1323,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1340,7 +1323,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1340 * @param lwM2MClient - LwM2M Client 1323 * @param lwM2MClient - LwM2M Client
1341 */ 1324 */
1342 public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) { 1325 public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) {
1343 - SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); 1326 + SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
1344 if (sessionInfo != null) { 1327 if (sessionInfo != null) {
1345 //#1.1 1328 //#1.1
1346 ConcurrentMap<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient); 1329 ConcurrentMap<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient);
@@ -1359,7 +1342,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1359,7 +1342,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1359 1342
1360 public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) { 1343 public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) {
1361 if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) { 1344 if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) {
1362 - SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); 1345 + SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
1363 if (sessionInfo != null) { 1346 if (sessionInfo != null) {
1364 DefaultLwM2MTransportMsgHandler handler = this; 1347 DefaultLwM2MTransportMsgHandler handler = this;
1365 this.transportService.process(sessionInfo, createOtaPackageRequestMsg(sessionInfo, OtaPackageType.FIRMWARE.name()), 1348 this.transportService.process(sessionInfo, createOtaPackageRequestMsg(sessionInfo, OtaPackageType.FIRMWARE.name()),
@@ -1368,16 +1351,15 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1368,16 +1351,15 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1368 public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) { 1351 public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) {
1369 if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus()) 1352 if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
1370 && response.getType().equals(OtaPackageType.FIRMWARE.name())) { 1353 && response.getType().equals(OtaPackageType.FIRMWARE.name())) {
1371 - log.warn ("7) firmware start with ver: [{}]", response.getVersion()); 1354 + log.warn("7) firmware start with ver: [{}]", response.getVersion());
1372 lwM2MClient.getFwUpdate().setRpcRequest(rpcRequest); 1355 lwM2MClient.getFwUpdate().setRpcRequest(rpcRequest);
1373 lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion()); 1356 lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion());
1374 lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle()); 1357 lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle());
1375 lwM2MClient.getFwUpdate().setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId()); 1358 lwM2MClient.getFwUpdate().setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId());
1376 if (rpcRequest == null) { 1359 if (rpcRequest == null) {
1377 lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest); 1360 lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
1378 - }  
1379 - else {  
1380 - lwM2MClient.getFwUpdate().writeFwSwWare(handler, lwM2mTransportRequest); 1361 + } else {
  1362 + lwM2MClient.getFwUpdate().writeFwSwWare(handler, lwM2mTransportRequest);
1381 } 1363 }
1382 } else { 1364 } else {
1383 log.trace("OtaPackage [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); 1365 log.trace("OtaPackage [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
@@ -1395,7 +1377,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1395,7 +1377,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1395 1377
1396 public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) { 1378 public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) {
1397 if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) { 1379 if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) {
1398 - SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); 1380 + SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
1399 if (sessionInfo != null) { 1381 if (sessionInfo != null) {
1400 DefaultLwM2MTransportMsgHandler handler = this; 1382 DefaultLwM2MTransportMsgHandler handler = this;
1401 transportService.process(sessionInfo, createOtaPackageRequestMsg(sessionInfo, OtaPackageType.SOFTWARE.name()), 1383 transportService.process(sessionInfo, createOtaPackageRequestMsg(sessionInfo, OtaPackageType.SOFTWARE.name()),
@@ -1411,9 +1393,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @@ -1411,9 +1393,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1411 lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest); 1393 lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
1412 if (rpcRequest == null) { 1394 if (rpcRequest == null) {
1413 lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest); 1395 lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
1414 - }  
1415 - else {  
1416 - lwM2MClient.getSwUpdate().writeFwSwWare(handler, lwM2mTransportRequest); 1396 + } else {
  1397 + lwM2MClient.getSwUpdate().writeFwSwWare(handler, lwM2mTransportRequest);
1417 } 1398 }
1418 } else { 1399 } else {
1419 log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); 1400 log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
@@ -36,6 +36,8 @@ import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC; @@ -36,6 +36,8 @@ import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC;
36 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer; 36 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer;
37 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MDtlsCertificateVerifier; 37 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MDtlsCertificateVerifier;
38 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 38 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
  39 +import org.thingsboard.server.transport.lwm2m.server.store.TbEditableSecurityStore;
  40 +import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
39 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; 41 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
40 42
41 import javax.annotation.PostConstruct; 43 import javax.annotation.PostConstruct;
@@ -83,7 +85,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { @@ -83,7 +85,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
83 private final LwM2mTransportServerHelper helper; 85 private final LwM2mTransportServerHelper helper;
84 private final LwM2mTransportMsgHandler handler; 86 private final LwM2mTransportMsgHandler handler;
85 private final CaliforniumRegistrationStore registrationStore; 87 private final CaliforniumRegistrationStore registrationStore;
86 - private final EditableSecurityStore securityStore; 88 + private final TbSecurityStore securityStore;
87 private final LwM2mClientContext lwM2mClientContext; 89 private final LwM2mClientContext lwM2mClientContext;
88 private final TbLwM2MDtlsCertificateVerifier certificateVerifier; 90 private final TbLwM2MDtlsCertificateVerifier certificateVerifier;
89 private final TbLwM2MAuthorizer authorizer; 91 private final TbLwM2MAuthorizer authorizer;
@@ -87,7 +87,7 @@ public class LwM2mServerListener { @@ -87,7 +87,7 @@ public class LwM2mServerListener {
87 @Override 87 @Override
88 public void cancelled(Observation observation) { 88 public void cancelled(Observation observation) {
89 String msg = String.format("%s: Canceled Observation %s.", LOG_LW2M_INFO, observation.getPath()); 89 String msg = String.format("%s: Canceled Observation %s.", LOG_LW2M_INFO, observation.getPath());
90 - service.sendLogsToThingsboard(msg, observation.getRegistrationId()); 90 + service.sendLogsToThingsboard(observation.getRegistrationId(), msg);
91 log.warn(msg); 91 log.warn(msg);
92 } 92 }
93 93
@@ -109,7 +109,7 @@ public class LwM2mServerListener { @@ -109,7 +109,7 @@ public class LwM2mServerListener {
109 String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO, 109 String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO,
110 observation.getPath()); 110 observation.getPath());
111 log.warn(msg); 111 log.warn(msg);
112 - service.sendLogsToThingsboard(msg, registration.getId()); 112 + service.sendLogsToThingsboard(registration.getId(), msg);
113 } 113 }
114 }; 114 };
115 } 115 }
@@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.Device; @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.Device;
22 import org.thingsboard.server.common.data.DeviceProfile; 22 import org.thingsboard.server.common.data.DeviceProfile;
23 import org.thingsboard.server.gen.transport.TransportProtos; 23 import org.thingsboard.server.gen.transport.TransportProtos;
24 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 24 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
  25 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
25 import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; 26 import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest;
26 27
27 import java.util.Collection; 28 import java.util.Collection;
@@ -57,13 +58,13 @@ public interface LwM2mTransportMsgHandler { @@ -57,13 +58,13 @@ public interface LwM2mTransportMsgHandler {
57 58
58 void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg toServerResponse); 59 void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg toServerResponse);
59 60
60 - void doTrigger(Registration registration, String path);  
61 -  
62 void doDisconnect(TransportProtos.SessionInfoProto sessionInfo); 61 void doDisconnect(TransportProtos.SessionInfoProto sessionInfo);
63 62
64 void onAwakeDev(Registration registration); 63 void onAwakeDev(Registration registration);
65 64
66 - void sendLogsToThingsboard(String msg, String registrationId); 65 + void sendLogsToThingsboard(LwM2mClient client, String msg);
  66 +
  67 + void sendLogsToThingsboard(String registrationId, String msg);
67 68
68 LwM2MTransportServerConfig getConfig(); 69 LwM2MTransportServerConfig getConfig();
69 } 70 }
@@ -32,10 +32,10 @@ import org.eclipse.leshan.core.observation.Observation; @@ -32,10 +32,10 @@ import org.eclipse.leshan.core.observation.Observation;
32 import org.eclipse.leshan.core.request.ContentFormat; 32 import org.eclipse.leshan.core.request.ContentFormat;
33 import org.eclipse.leshan.core.request.DeleteRequest; 33 import org.eclipse.leshan.core.request.DeleteRequest;
34 import org.eclipse.leshan.core.request.DiscoverRequest; 34 import org.eclipse.leshan.core.request.DiscoverRequest;
35 -import org.eclipse.leshan.core.request.DownlinkRequest;  
36 import org.eclipse.leshan.core.request.ExecuteRequest; 35 import org.eclipse.leshan.core.request.ExecuteRequest;
37 import org.eclipse.leshan.core.request.ObserveRequest; 36 import org.eclipse.leshan.core.request.ObserveRequest;
38 import org.eclipse.leshan.core.request.ReadRequest; 37 import org.eclipse.leshan.core.request.ReadRequest;
  38 +import org.eclipse.leshan.core.request.SimpleDownlinkRequest;
39 import org.eclipse.leshan.core.request.WriteAttributesRequest; 39 import org.eclipse.leshan.core.request.WriteAttributesRequest;
40 import org.eclipse.leshan.core.request.WriteRequest; 40 import org.eclipse.leshan.core.request.WriteRequest;
41 import org.eclipse.leshan.core.request.exception.ClientSleepingException; 41 import org.eclipse.leshan.core.request.exception.ClientSleepingException;
@@ -116,32 +116,30 @@ public class LwM2mTransportRequest { @@ -116,32 +116,30 @@ public class LwM2mTransportRequest {
116 new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL))); 116 new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL)));
117 } 117 }
118 118
119 - /**  
120 - * Device management and service enablement, including Read, Write, Execute, Discover, Create, Delete and Write-Attributes  
121 - *  
122 - * @param registration -  
123 - * @param targetIdVer -  
124 - * @param typeOper -  
125 - * @param contentFormatName -  
126 - */ 119 + public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper, Object params, long timeoutInMs, Lwm2mClientRpcRequest lwm2mClientRpcRequest) {
  120 + sendAllRequest(lwM2MClient, targetIdVer, typeOper, lwM2MClient.getDefaultContentFormat(), params, timeoutInMs, lwm2mClientRpcRequest);
  121 + }
  122 +
127 123
128 - public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper,  
129 - String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest lwm2mClientRpcRequest) { 124 + public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper,
  125 + ContentFormat contentFormat, Object params, long timeoutInMs, Lwm2mClientRpcRequest lwm2mClientRpcRequest) {
  126 + Registration registration = lwM2MClient.getRegistration();
130 try { 127 try {
131 String target = convertPathFromIdVerToObjectId(targetIdVer); 128 String target = convertPathFromIdVerToObjectId(targetIdVer);
132 - ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT;  
133 - LwM2mClient lwM2MClient = this.lwM2mClientContext.getOrRegister(registration); 129 + if(contentFormat == null){
  130 + contentFormat = ContentFormat.DEFAULT;
  131 + }
134 LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null; 132 LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null;
135 if (!OBSERVE_CANCEL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) { 133 if (!OBSERVE_CANCEL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) {
136 if (lwM2MClient.isValidObjectVersion(targetIdVer)) { 134 if (lwM2MClient.isValidObjectVersion(targetIdVer)) {
137 timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; 135 timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
138 - DownlinkRequest request = createRequest(registration, lwM2MClient, typeOper, contentFormat, target, 136 + SimpleDownlinkRequest request = createRequest(registration, lwM2MClient, typeOper, contentFormat, target,
139 targetIdVer, resultIds, params, lwm2mClientRpcRequest); 137 targetIdVer, resultIds, params, lwm2mClientRpcRequest);
140 if (request != null) { 138 if (request != null) {
141 try { 139 try {
142 this.sendRequest(registration, lwM2MClient, request, timeoutInMs, lwm2mClientRpcRequest); 140 this.sendRequest(registration, lwM2MClient, request, timeoutInMs, lwm2mClientRpcRequest);
143 } catch (ClientSleepingException e) { 141 } catch (ClientSleepingException e) {
144 - DownlinkRequest finalRequest = request; 142 + SimpleDownlinkRequest finalRequest = request;
145 long finalTimeoutInMs = timeoutInMs; 143 long finalTimeoutInMs = timeoutInMs;
146 Lwm2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest; 144 Lwm2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest;
147 lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest)); 145 lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest));
@@ -185,7 +183,7 @@ public class LwM2mTransportRequest { @@ -185,7 +183,7 @@ public class LwM2mTransportRequest {
185 } 183 }
186 String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO, 184 String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
187 typeOper.name(), paths); 185 typeOper.name(), paths);
188 - this.handler.sendLogsToThingsboard(msg, registration.getId()); 186 + this.handler.sendLogsToThingsboard(lwM2MClient, msg);
189 if (lwm2mClientRpcRequest != null) { 187 if (lwm2mClientRpcRequest != null) {
190 String valueMsg = String.format("Paths - %s", paths); 188 String valueMsg = String.format("Paths - %s", paths);
191 this.handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); 189 this.handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
@@ -204,7 +202,7 @@ public class LwM2mTransportRequest { @@ -204,7 +202,7 @@ public class LwM2mTransportRequest {
204 observeCancelMsg = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO, 202 observeCancelMsg = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO,
205 OBSERVE_CANCEL.name(), observeCancelCnt); 203 OBSERVE_CANCEL.name(), observeCancelCnt);
206 } 204 }
207 - this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsg, lwm2mClientRpcRequest); 205 + this.afterObserveCancel(lwM2MClient, observeCancelCnt, observeCancelMsg, lwm2mClientRpcRequest);
208 break; 206 break;
209 // lwm2mClientRpcRequest != null 207 // lwm2mClientRpcRequest != null
210 case FW_UPDATE: 208 case FW_UPDATE:
@@ -215,7 +213,7 @@ public class LwM2mTransportRequest { @@ -215,7 +213,7 @@ public class LwM2mTransportRequest {
215 } catch (Exception e) { 213 } catch (Exception e) {
216 String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, 214 String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR,
217 typeOper.name(), e.getMessage()); 215 typeOper.name(), e.getMessage());
218 - handler.sendLogsToThingsboard(msg, registration.getId()); 216 + handler.sendLogsToThingsboard(lwM2MClient, msg);
219 if (lwm2mClientRpcRequest != null) { 217 if (lwm2mClientRpcRequest != null) {
220 String errorMsg = String.format("Path %s type operation %s %s", targetIdVer, typeOper.name(), e.getMessage()); 218 String errorMsg = String.format("Path %s type operation %s %s", targetIdVer, typeOper.name(), e.getMessage());
221 handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); 219 handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
@@ -223,10 +221,10 @@ public class LwM2mTransportRequest { @@ -223,10 +221,10 @@ public class LwM2mTransportRequest {
223 } 221 }
224 } 222 }
225 223
226 - private DownlinkRequest createRequest(Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper, 224 + private SimpleDownlinkRequest createRequest(Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper,
227 ContentFormat contentFormat, String target, String targetIdVer, 225 ContentFormat contentFormat, String target, String targetIdVer,
228 LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) { 226 LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) {
229 - DownlinkRequest request = null; 227 + SimpleDownlinkRequest request = null;
230 switch (typeOper) { 228 switch (typeOper) {
231 case READ: 229 case READ:
232 request = new ReadRequest(contentFormat, target); 230 request = new ReadRequest(contentFormat, target);
@@ -273,7 +271,7 @@ public class LwM2mTransportRequest { @@ -273,7 +271,7 @@ public class LwM2mTransportRequest {
273 contentFormat = getContentFormatByResourceModelType(resourceModelWrite, contentFormat); 271 contentFormat = getContentFormatByResourceModelType(resourceModelWrite, contentFormat);
274 request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), 272 request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(),
275 resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModelWrite.type, 273 resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModelWrite.type,
276 - registration, rpcRequest); 274 + lwM2MClient, rpcRequest);
277 } 275 }
278 break; 276 break;
279 case WRITE_UPDATE: 277 case WRITE_UPDATE:
@@ -329,7 +327,7 @@ public class LwM2mTransportRequest { @@ -329,7 +327,7 @@ public class LwM2mTransportRequest {
329 */ 327 */
330 328
331 @SuppressWarnings({"error sendRequest"}) 329 @SuppressWarnings({"error sendRequest"})
332 - private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, 330 + private void sendRequest(Registration registration, LwM2mClient lwM2MClient, SimpleDownlinkRequest request,
333 long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { 331 long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
334 context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { 332 context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
335 333
@@ -337,11 +335,11 @@ public class LwM2mTransportRequest { @@ -337,11 +335,11 @@ public class LwM2mTransportRequest {
337 lwM2MClient.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); 335 lwM2MClient.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
338 } 336 }
339 if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { 337 if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) {
340 - this.handleResponse(registration, request.getPath().toString(), response, request, rpcRequest); 338 + this.handleResponse(lwM2MClient, request.getPath().toString(), response, request, rpcRequest);
341 } else { 339 } else {
342 String msg = String.format("%s: SendRequest %s: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(), 340 String msg = String.format("%s: SendRequest %s: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(),
343 ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString()); 341 ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString());
344 - handler.sendLogsToThingsboard(msg, registration.getId()); 342 + handler.sendLogsToThingsboard(lwM2MClient, msg);
345 log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(), 343 log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(),
346 ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString()); 344 ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString());
347 if (!lwM2MClient.isInit()) { 345 if (!lwM2MClient.isInit()) {
@@ -388,7 +386,7 @@ public class LwM2mTransportRequest { @@ -388,7 +386,7 @@ public class LwM2mTransportRequest {
388 } 386 }
389 String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s", 387 String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s",
390 LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage()); 388 LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage());
391 - handler.sendLogsToThingsboard(msg, registration.getId()); 389 + handler.sendLogsToThingsboard(lwM2MClient, msg);
392 log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString()); 390 log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString());
393 if (rpcRequest != null) { 391 if (rpcRequest != null) {
394 handler.sentRpcResponse(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); 392 handler.sentRpcResponse(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR);
@@ -398,7 +396,7 @@ public class LwM2mTransportRequest { @@ -398,7 +396,7 @@ public class LwM2mTransportRequest {
398 396
399 private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId, 397 private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId,
400 Integer resourceId, Object value, ResourceModel.Type type, 398 Integer resourceId, Object value, ResourceModel.Type type,
401 - Registration registration, Lwm2mClientRpcRequest rpcRequest) { 399 + LwM2mClient client, Lwm2mClientRpcRequest rpcRequest) {
402 try { 400 try {
403 if (type != null) { 401 if (type != null) {
404 switch (type) { 402 switch (type) {
@@ -433,7 +431,7 @@ public class LwM2mTransportRequest { @@ -433,7 +431,7 @@ public class LwM2mTransportRequest {
433 String patn = "/" + objectId + "/" + instanceId + "/" + resourceId; 431 String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
434 String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client", 432 String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client",
435 patn, type, value, e.toString()); 433 patn, type, value, e.toString());
436 - handler.sendLogsToThingsboard(msg, registration.getId()); 434 + handler.sendLogsToThingsboard(client, msg);
437 log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString()); 435 log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString());
438 if (rpcRequest != null) { 436 if (rpcRequest != null) {
439 String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value); 437 String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value);
@@ -443,13 +441,13 @@ public class LwM2mTransportRequest { @@ -443,13 +441,13 @@ public class LwM2mTransportRequest {
443 } 441 }
444 } 442 }
445 443
446 - private void handleResponse(Registration registration, final String path, LwM2mResponse response,  
447 - DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { 444 + private void handleResponse(LwM2mClient lwM2mClient, final String path, LwM2mResponse response,
  445 + SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
448 responseRequestExecutor.submit(() -> { 446 responseRequestExecutor.submit(() -> {
449 try { 447 try {
450 - this.sendResponse(registration, path, response, request, rpcRequest); 448 + this.sendResponse(lwM2mClient, path, response, request, rpcRequest);
451 } catch (Exception e) { 449 } catch (Exception e) {
452 - log.error("[{}] endpoint [{}] path [{}] Exception Unable to after send response.", registration.getEndpoint(), path, e); 450 + log.error("[{}] endpoint [{}] path [{}] Exception Unable to after send response.", lwM2mClient.getRegistration().getEndpoint(), path, e);
453 } 451 }
454 }); 452 });
455 } 453 }
@@ -461,8 +459,9 @@ public class LwM2mTransportRequest { @@ -461,8 +459,9 @@ public class LwM2mTransportRequest {
461 * @param path - 459 * @param path -
462 * @param response - 460 * @param response -
463 */ 461 */
464 - private void sendResponse(Registration registration, String path, LwM2mResponse response,  
465 - DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { 462 + private void sendResponse(LwM2mClient lwM2mClient, String path, LwM2mResponse response,
  463 + SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
  464 + Registration registration = lwM2mClient.getRegistration();
466 String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); 465 String pathIdVer = convertPathFromObjectIdToIdVer(path, registration);
467 String msgLog = ""; 466 String msgLog = "";
468 if (response instanceof ReadResponse) { 467 if (response instanceof ReadResponse) {
@@ -477,7 +476,7 @@ public class LwM2mTransportRequest { @@ -477,7 +476,7 @@ public class LwM2mTransportRequest {
477 String discoverValue = Link.serialize(((DiscoverResponse) response).getObjectLinks()); 476 String discoverValue = Link.serialize(((DiscoverResponse) response).getObjectLinks());
478 msgLog = String.format("%s: type operation: %s path: %s value: %s", 477 msgLog = String.format("%s: type operation: %s path: %s value: %s",
479 LOG_LW2M_INFO, DISCOVER.name(), request.getPath().toString(), discoverValue); 478 LOG_LW2M_INFO, DISCOVER.name(), request.getPath().toString(), discoverValue);
480 - handler.sendLogsToThingsboard(msgLog, registration.getId()); 479 + handler.sendLogsToThingsboard(lwM2mClient, msgLog);
481 log.warn("DiscoverResponse: [{}]", (DiscoverResponse) response); 480 log.warn("DiscoverResponse: [{}]", (DiscoverResponse) response);
482 if (rpcRequest != null) { 481 if (rpcRequest != null) {
483 handler.sentRpcResponse(rpcRequest, response.getCode().getName(), discoverValue, LOG_LW2M_VALUE); 482 handler.sentRpcResponse(rpcRequest, response.getCode().getName(), discoverValue, LOG_LW2M_VALUE);
@@ -486,7 +485,7 @@ public class LwM2mTransportRequest { @@ -486,7 +485,7 @@ public class LwM2mTransportRequest {
486 msgLog = String.format("%s: type operation: %s path: %s", 485 msgLog = String.format("%s: type operation: %s path: %s",
487 LOG_LW2M_INFO, EXECUTE.name(), request.getPath().toString()); 486 LOG_LW2M_INFO, EXECUTE.name(), request.getPath().toString());
488 log.warn("9) [{}] ", msgLog); 487 log.warn("9) [{}] ", msgLog);
489 - handler.sendLogsToThingsboard(msgLog, registration.getId()); 488 + handler.sendLogsToThingsboard(lwM2mClient, msgLog);
490 if (rpcRequest != null) { 489 if (rpcRequest != null) {
491 msgLog = String.format("Start %s path: %S. Preparation finished: %s", EXECUTE.name(), path, rpcRequest.getInfoMsg()); 490 msgLog = String.format("Start %s path: %S. Preparation finished: %s", EXECUTE.name(), path, rpcRequest.getInfoMsg());
492 rpcRequest.setInfoMsg(msgLog); 491 rpcRequest.setInfoMsg(msgLog);
@@ -496,7 +495,7 @@ public class LwM2mTransportRequest { @@ -496,7 +495,7 @@ public class LwM2mTransportRequest {
496 } else if (response instanceof WriteAttributesResponse) { 495 } else if (response instanceof WriteAttributesResponse) {
497 msgLog = String.format("%s: type operation: %s path: %s value: %s", 496 msgLog = String.format("%s: type operation: %s path: %s value: %s",
498 LOG_LW2M_INFO, WRITE_ATTRIBUTES.name(), request.getPath().toString(), ((WriteAttributesRequest) request).getAttributes().toString()); 497 LOG_LW2M_INFO, WRITE_ATTRIBUTES.name(), request.getPath().toString(), ((WriteAttributesRequest) request).getAttributes().toString());
499 - handler.sendLogsToThingsboard(msgLog, registration.getId()); 498 + handler.sendLogsToThingsboard(lwM2mClient, msgLog);
500 log.warn("12) [{}] Path [{}] WriteAttributesResponse", pathIdVer, response); 499 log.warn("12) [{}] Path [{}] WriteAttributesResponse", pathIdVer, response);
501 if (rpcRequest != null) { 500 if (rpcRequest != null) {
502 handler.sentRpcResponse(rpcRequest, response.getCode().getName(), response.toString(), LOG_LW2M_VALUE); 501 handler.sentRpcResponse(rpcRequest, response.getCode().getName(), response.toString(), LOG_LW2M_VALUE);
@@ -504,13 +503,14 @@ public class LwM2mTransportRequest { @@ -504,13 +503,14 @@ public class LwM2mTransportRequest {
504 } else if (response instanceof WriteResponse) { 503 } else if (response instanceof WriteResponse) {
505 msgLog = String.format("Type operation: Write path: %s", pathIdVer); 504 msgLog = String.format("Type operation: Write path: %s", pathIdVer);
506 log.warn("10) [{}] response: [{}]", msgLog, response); 505 log.warn("10) [{}] response: [{}]", msgLog, response);
507 - this.infoWriteResponse(registration, response, request, rpcRequest); 506 + this.infoWriteResponse(lwM2mClient, response, request, rpcRequest);
508 handler.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request); 507 handler.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request);
509 } 508 }
510 } 509 }
511 510
512 - private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { 511 + private void infoWriteResponse(LwM2mClient lwM2mClient, LwM2mResponse response, SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
513 try { 512 try {
  513 + Registration registration = lwM2mClient.getRegistration();
514 LwM2mNode node = ((WriteRequest) request).getNode(); 514 LwM2mNode node = ((WriteRequest) request).getNode();
515 String msg = null; 515 String msg = null;
516 Object value; 516 Object value;
@@ -545,7 +545,7 @@ public class LwM2mTransportRequest { @@ -545,7 +545,7 @@ public class LwM2mTransportRequest {
545 } 545 }
546 } 546 }
547 if (msg != null) { 547 if (msg != null) {
548 - handler.sendLogsToThingsboard(msg, registration.getId()); 548 + handler.sendLogsToThingsboard(lwM2mClient, msg);
549 if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { 549 if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
550 this.afterWriteSuccessFwSwUpdate(registration, request); 550 this.afterWriteSuccessFwSwUpdate(registration, request);
551 if (rpcRequest != null) { 551 if (rpcRequest != null) {
@@ -566,7 +566,7 @@ public class LwM2mTransportRequest { @@ -566,7 +566,7 @@ public class LwM2mTransportRequest {
566 * fw_state/sw_state = DOWNLOADED 566 * fw_state/sw_state = DOWNLOADED
567 * send operation Execute 567 * send operation Execute
568 */ 568 */
569 - private void afterWriteSuccessFwSwUpdate(Registration registration, DownlinkRequest request) { 569 + private void afterWriteSuccessFwSwUpdate(Registration registration, SimpleDownlinkRequest request) {
570 LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); 570 LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
571 if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { 571 if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
572 lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name()); 572 lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name());
@@ -581,7 +581,7 @@ public class LwM2mTransportRequest { @@ -581,7 +581,7 @@ public class LwM2mTransportRequest {
581 /** 581 /**
582 * After finish operation FwSwUpdate Write (error): fw_state = FAILED 582 * After finish operation FwSwUpdate Write (error): fw_state = FAILED
583 */ 583 */
584 - private void afterWriteFwSWUpdateError(Registration registration, DownlinkRequest request, String msgError) { 584 + private void afterWriteFwSWUpdateError(Registration registration, SimpleDownlinkRequest request, String msgError) {
585 LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); 585 LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
586 if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { 586 if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
587 lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name()); 587 lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name());
@@ -593,7 +593,7 @@ public class LwM2mTransportRequest { @@ -593,7 +593,7 @@ public class LwM2mTransportRequest {
593 } 593 }
594 } 594 }
595 595
596 - private void afterExecuteFwSwUpdateError(Registration registration, DownlinkRequest request, String msgError) { 596 + private void afterExecuteFwSwUpdateError(Registration registration, SimpleDownlinkRequest request, String msgError) {
597 LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); 597 LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
598 if (request.getPath().toString().equals(FW_UPDATE_ID) && lwM2MClient.getFwUpdate() != null) { 598 if (request.getPath().toString().equals(FW_UPDATE_ID) && lwM2MClient.getFwUpdate() != null) {
599 lwM2MClient.getFwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError); 599 lwM2MClient.getFwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError);
@@ -603,8 +603,8 @@ public class LwM2mTransportRequest { @@ -603,8 +603,8 @@ public class LwM2mTransportRequest {
603 } 603 }
604 } 604 }
605 605
606 - private void afterObserveCancel(Registration registration, int observeCancelCnt, String observeCancelMsg, Lwm2mClientRpcRequest rpcRequest) {  
607 - handler.sendLogsToThingsboard(observeCancelMsg, registration.getId()); 606 + private void afterObserveCancel(LwM2mClient lwM2mClient, int observeCancelCnt, String observeCancelMsg, Lwm2mClientRpcRequest rpcRequest) {
  607 + handler.sendLogsToThingsboard(lwM2mClient, observeCancelMsg);
608 log.warn("[{}]", observeCancelMsg); 608 log.warn("[{}]", observeCancelMsg);
609 if (rpcRequest != null) { 609 if (rpcRequest != null) {
610 rpcRequest.setInfoMsg(String.format("Count: %d", observeCancelCnt)); 610 rpcRequest.setInfoMsg(String.format("Count: %d", observeCancelCnt));
@@ -137,7 +137,7 @@ public class LwM2mTransportServerHelper { @@ -137,7 +137,7 @@ public class LwM2mTransportServerHelper {
137 public ObjectModel parseFromXmlToObjectModel(byte[] xmlByte, String streamName, DefaultDDFFileValidator ddfValidator) { 137 public ObjectModel parseFromXmlToObjectModel(byte[] xmlByte, String streamName, DefaultDDFFileValidator ddfValidator) {
138 try { 138 try {
139 DDFFileParser ddfFileParser = new DDFFileParser(ddfValidator); 139 DDFFileParser ddfFileParser = new DDFFileParser(ddfValidator);
140 - return ddfFileParser.parseEx(new ByteArrayInputStream(xmlByte), streamName).get(0); 140 + return ddfFileParser.parse(new ByteArrayInputStream(xmlByte), streamName).get(0);
141 } catch (IOException | InvalidDDFFileException e) { 141 } catch (IOException | InvalidDDFFileException e) {
142 log.error("Could not parse the XML file [{}]", streamName, e); 142 log.error("Could not parse the XML file [{}]", streamName, e);
143 return null; 143 return null;
@@ -36,7 +36,7 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance; @@ -36,7 +36,7 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance;
36 import org.eclipse.leshan.core.node.LwM2mPath; 36 import org.eclipse.leshan.core.node.LwM2mPath;
37 import org.eclipse.leshan.core.node.LwM2mSingleResource; 37 import org.eclipse.leshan.core.node.LwM2mSingleResource;
38 import org.eclipse.leshan.core.node.codec.CodecException; 38 import org.eclipse.leshan.core.node.codec.CodecException;
39 -import org.eclipse.leshan.core.request.DownlinkRequest; 39 +import org.eclipse.leshan.core.request.SimpleDownlinkRequest;
40 import org.eclipse.leshan.core.request.WriteAttributesRequest; 40 import org.eclipse.leshan.core.request.WriteAttributesRequest;
41 import org.eclipse.leshan.core.util.Hex; 41 import org.eclipse.leshan.core.util.Hex;
42 import org.eclipse.leshan.server.registration.Registration; 42 import org.eclipse.leshan.server.registration.Registration;
@@ -839,7 +839,7 @@ public class LwM2mTransportUtil { @@ -839,7 +839,7 @@ public class LwM2mTransportUtil {
839 * Attribute pmax = new Attribute(MAXIMUM_PERIOD, "60"); 839 * Attribute pmax = new Attribute(MAXIMUM_PERIOD, "60");
840 * Attribute [] attrs = {gt, st}; 840 * Attribute [] attrs = {gt, st};
841 */ 841 */
842 - public static DownlinkRequest createWriteAttributeRequest(String target, Object params, DefaultLwM2MTransportMsgHandler serviceImpl) { 842 + public static SimpleDownlinkRequest createWriteAttributeRequest(String target, Object params, DefaultLwM2MTransportMsgHandler serviceImpl) {
843 AttributeSet attrSet = new AttributeSet(createWriteAttributes(params, serviceImpl, target)); 843 AttributeSet attrSet = new AttributeSet(createWriteAttributes(params, serviceImpl, target));
844 return attrSet.getAttributes().size() > 0 ? new WriteAttributesRequest(target, attrSet) : null; 844 return attrSet.getAttributes().size() > 0 ? new WriteAttributesRequest(target, attrSet) : null;
845 } 845 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.client;
  17 +
  18 +public enum LwM2MClientState {
  19 +
  20 + CREATED, REGISTERED, UNREGISTERED
  21 +
  22 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.client;
  17 +
  18 +import lombok.Getter;
  19 +
  20 +public class LwM2MClientStateException extends Exception {
  21 +
  22 + private static final long serialVersionUID = 3307690997951364046L;
  23 +
  24 + @Getter
  25 + private final LwM2MClientState state;
  26 +
  27 + public LwM2MClientStateException(LwM2MClientState state, String message) {
  28 + super(message);
  29 + this.state = state;
  30 + }
  31 +}
@@ -26,6 +26,7 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance; @@ -26,6 +26,7 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance;
26 import org.eclipse.leshan.core.node.LwM2mPath; 26 import org.eclipse.leshan.core.node.LwM2mPath;
27 import org.eclipse.leshan.core.node.LwM2mResource; 27 import org.eclipse.leshan.core.node.LwM2mResource;
28 import org.eclipse.leshan.core.node.LwM2mSingleResource; 28 import org.eclipse.leshan.core.node.LwM2mSingleResource;
  29 +import org.eclipse.leshan.core.request.ContentFormat;
29 import org.eclipse.leshan.server.model.LwM2mModelProvider; 30 import org.eclipse.leshan.server.model.LwM2mModelProvider;
30 import org.eclipse.leshan.server.registration.Registration; 31 import org.eclipse.leshan.server.registration.Registration;
31 import org.eclipse.leshan.server.security.SecurityInfo; 32 import org.eclipse.leshan.server.security.SecurityInfo;
@@ -49,6 +50,8 @@ import java.util.UUID; @@ -49,6 +50,8 @@ import java.util.UUID;
49 import java.util.concurrent.ConcurrentHashMap; 50 import java.util.concurrent.ConcurrentHashMap;
50 import java.util.concurrent.ConcurrentLinkedQueue; 51 import java.util.concurrent.ConcurrentLinkedQueue;
51 import java.util.concurrent.CopyOnWriteArrayList; 52 import java.util.concurrent.CopyOnWriteArrayList;
  53 +import java.util.concurrent.locks.Lock;
  54 +import java.util.concurrent.locks.ReentrantLock;
52 import java.util.stream.Collectors; 55 import java.util.stream.Collectors;
53 56
54 import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; 57 import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;
@@ -62,12 +65,28 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.g @@ -62,12 +65,28 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.g
62 65
63 @Slf4j 66 @Slf4j
64 public class LwM2mClient implements Cloneable { 67 public class LwM2mClient implements Cloneable {
  68 +
  69 + private final String nodeId;
  70 + @Getter
  71 + private final String endpoint;
  72 + private final Lock lock;
  73 + @Getter
  74 + @Setter
  75 + private LwM2MClientState state;
  76 + @Getter
  77 + private final Map<String, ResourceValue> resources;
  78 + @Getter
  79 + private final Map<String, TsKvProto> delayedRequests;
  80 + @Getter
  81 + private final List<String> pendingReadRequests;
  82 + @Getter
  83 + private final Queue<LwM2mQueuedRequest> queuedRequests;
  84 +
65 @Getter 85 @Getter
66 private String deviceName; 86 private String deviceName;
67 @Getter 87 @Getter
68 private String deviceProfileName; 88 private String deviceProfileName;
69 - @Getter  
70 - private String endpoint; 89 +
71 @Getter 90 @Getter
72 private String identity; 91 private String identity;
73 @Getter 92 @Getter
@@ -93,33 +112,29 @@ public class LwM2mClient implements Cloneable { @@ -93,33 +112,29 @@ public class LwM2mClient implements Cloneable {
93 private ValidateDeviceCredentialsResponse credentials; 112 private ValidateDeviceCredentialsResponse credentials;
94 113
95 @Getter 114 @Getter
96 - private final Map<String, ResourceValue> resources;  
97 - @Getter  
98 - private final Map<String, TsKvProto> delayedRequests;  
99 - @Getter  
100 - @Setter  
101 - private final List<String> pendingReadRequests;  
102 - @Getter  
103 - private final Queue<LwM2mQueuedRequest> queuedRequests;  
104 - @Getter  
105 private boolean init; 115 private boolean init;
106 116
107 public Object clone() throws CloneNotSupportedException { 117 public Object clone() throws CloneNotSupportedException {
108 return super.clone(); 118 return super.clone();
109 } 119 }
110 120
111 - public LwM2mClient(String nodeId, String endpoint, String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponse credentials, UUID profileId, UUID sessionId) { 121 + public LwM2mClient(String nodeId, String endpoint) {
  122 + this.nodeId = nodeId;
112 this.endpoint = endpoint; 123 this.endpoint = endpoint;
113 - this.identity = identity;  
114 - this.securityInfo = securityInfo;  
115 - this.credentials = credentials; 124 + this.lock = new ReentrantLock();
116 this.delayedRequests = new ConcurrentHashMap<>(); 125 this.delayedRequests = new ConcurrentHashMap<>();
117 this.pendingReadRequests = new CopyOnWriteArrayList<>(); 126 this.pendingReadRequests = new CopyOnWriteArrayList<>();
118 this.resources = new ConcurrentHashMap<>(); 127 this.resources = new ConcurrentHashMap<>();
119 - this.profileId = profileId;  
120 - this.init = false;  
121 this.queuedRequests = new ConcurrentLinkedQueue<>(); 128 this.queuedRequests = new ConcurrentLinkedQueue<>();
  129 + this.state = LwM2MClientState.CREATED;
  130 + }
122 131
  132 + public void init(String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponse credentials, UUID profileId, UUID sessionId) {
  133 + this.identity = identity;
  134 + this.securityInfo = securityInfo;
  135 + this.credentials = credentials;
  136 + this.profileId = profileId;
  137 + this.init = false;
123 this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE); 138 this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE);
124 this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE); 139 this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE);
125 if (this.credentials != null && this.credentials.hasDeviceInfo()) { 140 if (this.credentials != null && this.credentials.hasDeviceInfo()) {
@@ -131,6 +146,14 @@ public class LwM2mClient implements Cloneable { @@ -131,6 +146,14 @@ public class LwM2mClient implements Cloneable {
131 } 146 }
132 } 147 }
133 148
  149 + public void lock() {
  150 + lock.lock();
  151 + }
  152 +
  153 + public void unlock() {
  154 + lock.unlock();
  155 + }
  156 +
134 public void onDeviceUpdate(Device device, Optional<DeviceProfile> deviceProfileOpt) { 157 public void onDeviceUpdate(Device device, Optional<DeviceProfile> deviceProfileOpt) {
135 SessionInfoProto.Builder builder = SessionInfoProto.newBuilder().mergeFrom(session); 158 SessionInfoProto.Builder builder = SessionInfoProto.newBuilder().mergeFrom(session);
136 this.deviceId = device.getUuidId(); 159 this.deviceId = device.getUuidId();
@@ -193,9 +216,7 @@ public class LwM2mClient implements Cloneable { @@ -193,9 +216,7 @@ public class LwM2mClient implements Cloneable {
193 public Object getResourceValue(String pathRezIdVer, String pathRezId) { 216 public Object getResourceValue(String pathRezIdVer, String pathRezId) {
194 String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer; 217 String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer;
195 if (this.resources.get(pathRez) != null) { 218 if (this.resources.get(pathRez) != null) {
196 - return this.resources.get(pathRez).getLwM2mResource().isMultiInstances() ?  
197 - this.resources.get(pathRez).getLwM2mResource().getValues() :  
198 - this.resources.get(pathRez).getLwM2mResource().getValue(); 219 + return this.resources.get(pathRez).getLwM2mResource().getValue();
199 } 220 }
200 return null; 221 return null;
201 } 222 }
@@ -366,5 +387,14 @@ public class LwM2mClient implements Cloneable { @@ -366,5 +387,14 @@ public class LwM2mClient implements Cloneable {
366 } 387 }
367 } 388 }
368 389
  390 + public ContentFormat getDefaultContentFormat() {
  391 + if (registration == null) {
  392 + return ContentFormat.DEFAULT;
  393 + } else if (registration.getLwM2mVersion().equals("1.0")) {
  394 + return ContentFormat.TLV;
  395 + } else {
  396 + return ContentFormat.TEXT;
  397 + }
  398 + }
369 } 399 }
370 400
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.transport.lwm2m.server.client; 16 package org.thingsboard.server.transport.lwm2m.server.client;
17 17
18 import org.eclipse.leshan.server.registration.Registration; 18 import org.eclipse.leshan.server.registration.Registration;
  19 +import org.eclipse.leshan.server.security.SecurityInfo;
19 import org.thingsboard.server.common.data.DeviceProfile; 20 import org.thingsboard.server.common.data.DeviceProfile;
20 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 21 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
21 import org.thingsboard.server.gen.transport.TransportProtos; 22 import org.thingsboard.server.gen.transport.TransportProtos;
@@ -27,21 +28,17 @@ import java.util.UUID; @@ -27,21 +28,17 @@ import java.util.UUID;
27 28
28 public interface LwM2mClientContext { 29 public interface LwM2mClientContext {
29 30
30 - void removeClientByRegistrationId(String registrationId);  
31 -  
32 - LwM2mClient getClientByEndpoint(String endpoint);  
33 -  
34 LwM2mClient getClientByRegistrationId(String registrationId); 31 LwM2mClient getClientByRegistrationId(String registrationId);
35 32
36 - LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo); 33 + LwM2mClient getClientByEndpoint(String endpoint);
37 34
38 - LwM2mClient getOrRegister(Registration registration); 35 + LwM2mClient getClientBySessionInfo(TransportProtos.SessionInfoProto sessionInfo);
39 36
40 - LwM2mClient registerOrUpdate(Registration registration); 37 + void register(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException;
41 38
42 - LwM2mClient fetchClientByEndpoint(String endpoint); 39 + void updateRegistration(LwM2mClient client, Registration registration) throws LwM2MClientStateException;
43 40
44 - Registration getRegistration(String registrationId); 41 + void unregister(LwM2mClient client, Registration registration) throws LwM2MClientStateException;
45 42
46 Collection<LwM2mClient> getLwM2mClients(); 43 Collection<LwM2mClient> getLwM2mClients();
47 44
@@ -55,9 +52,11 @@ public interface LwM2mClientContext { @@ -55,9 +52,11 @@ public interface LwM2mClientContext {
55 52
56 LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile); 53 LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile);
57 54
58 - Set<String> getSupportedIdVerInClient(Registration registration); 55 + Set<String> getSupportedIdVerInClient(LwM2mClient registration);
59 56
60 LwM2mClient getClientByDeviceId(UUID deviceId); 57 LwM2mClient getClientByDeviceId(UUID deviceId);
61 58
62 void registerClient(Registration registration, ValidateDeviceCredentialsResponse credentials); 59 void registerClient(Registration registration, ValidateDeviceCredentialsResponse credentials);
  60 +
  61 +
63 } 62 }
@@ -19,16 +19,15 @@ import lombok.RequiredArgsConstructor; @@ -19,16 +19,15 @@ import lombok.RequiredArgsConstructor;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
20 import org.eclipse.leshan.core.node.LwM2mPath; 20 import org.eclipse.leshan.core.node.LwM2mPath;
21 import org.eclipse.leshan.server.registration.Registration; 21 import org.eclipse.leshan.server.registration.Registration;
22 -import org.eclipse.leshan.server.security.EditableSecurityStore;  
23 import org.springframework.stereotype.Service; 22 import org.springframework.stereotype.Service;
24 import org.thingsboard.server.common.data.DeviceProfile; 23 import org.thingsboard.server.common.data.DeviceProfile;
25 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 24 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
26 import org.thingsboard.server.gen.transport.TransportProtos; 25 import org.thingsboard.server.gen.transport.TransportProtos;
27 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 26 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
28 -import org.thingsboard.server.transport.lwm2m.secure.EndpointSecurityInfo;  
29 -import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; 27 +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
30 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; 28 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
31 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; 29 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
  30 +import org.thingsboard.server.transport.lwm2m.server.store.TbEditableSecurityStore;
32 31
33 import java.util.Arrays; 32 import java.util.Arrays;
34 import java.util.Collection; 33 import java.util.Collection;
@@ -48,46 +47,107 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.c @@ -48,46 +47,107 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.c
48 public class LwM2mClientContextImpl implements LwM2mClientContext { 47 public class LwM2mClientContextImpl implements LwM2mClientContext {
49 48
50 private final LwM2mTransportContext context; 49 private final LwM2mTransportContext context;
  50 + private final TbEditableSecurityStore securityStore;
51 private final Map<String, LwM2mClient> lwM2mClientsByEndpoint = new ConcurrentHashMap<>(); 51 private final Map<String, LwM2mClient> lwM2mClientsByEndpoint = new ConcurrentHashMap<>();
52 private final Map<String, LwM2mClient> lwM2mClientsByRegistrationId = new ConcurrentHashMap<>(); 52 private final Map<String, LwM2mClient> lwM2mClientsByRegistrationId = new ConcurrentHashMap<>();
53 private Map<UUID, LwM2mClientProfile> profiles = new ConcurrentHashMap<>(); 53 private Map<UUID, LwM2mClientProfile> profiles = new ConcurrentHashMap<>();
54 54
55 - private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator;  
56 -  
57 - private final EditableSecurityStore securityStore;  
58 -  
59 @Override 55 @Override
60 public LwM2mClient getClientByEndpoint(String endpoint) { 56 public LwM2mClient getClientByEndpoint(String endpoint) {
61 - return lwM2mClientsByEndpoint.get(endpoint); 57 + return lwM2mClientsByEndpoint.computeIfAbsent(endpoint, ep -> new LwM2mClient(context.getNodeId(), ep));
62 } 58 }
63 59
64 @Override 60 @Override
65 - public LwM2mClient getClientByRegistrationId(String registrationId) {  
66 - return lwM2mClientsByRegistrationId.get(registrationId); 61 + public void register(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException {
  62 + lwM2MClient.lock();
  63 + try {
  64 + if (LwM2MClientState.UNREGISTERED.equals(lwM2MClient.getState())) {
  65 + throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
  66 + }
  67 + TbLwM2MSecurityInfo securityInfo = securityStore.getTbLwM2MSecurityInfoByEndpoint(lwM2MClient.getEndpoint());
  68 + if (securityInfo.getSecurityMode() != null) {
  69 + if (securityInfo.getDeviceProfile() != null) {
  70 + UUID profileUuid = profileUpdate(securityInfo.getDeviceProfile()) != null ? securityInfo.getDeviceProfile().getUuidId() : null;
  71 + if (securityInfo.getSecurityInfo() != null) {
  72 + lwM2MClient.init(securityInfo.getSecurityInfo().getIdentity(), securityInfo.getSecurityInfo(), securityInfo.getMsg(), profileUuid, UUID.randomUUID());
  73 + } else if (NO_SEC.equals(securityInfo.getSecurityMode())) {
  74 + lwM2MClient.init(null, null, securityInfo.getMsg(), profileUuid, UUID.randomUUID());
  75 + } else {
  76 + throw new RuntimeException(String.format("Registration failed: device %s not found.", lwM2MClient.getEndpoint()));
  77 + }
  78 + } else {
  79 + throw new RuntimeException(String.format("Registration failed: device %s not found.", lwM2MClient.getEndpoint()));
  80 + }
  81 + } else {
  82 + throw new RuntimeException(String.format("Registration failed: FORBIDDEN, endpointId: %s", lwM2MClient.getEndpoint()));
  83 + }
  84 + lwM2MClient.setRegistration(registration);
  85 + this.lwM2mClientsByRegistrationId.put(registration.getId(), lwM2MClient);
  86 + lwM2MClient.setState(LwM2MClientState.REGISTERED);
  87 + } finally {
  88 + lwM2MClient.unlock();
  89 + }
67 } 90 }
68 91
69 @Override 92 @Override
70 - public LwM2mClient getOrRegister(Registration registration) {  
71 - if (registration == null) {  
72 - return null; 93 + public void updateRegistration(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException {
  94 + lwM2MClient.lock();
  95 + try {
  96 + if (!LwM2MClientState.REGISTERED.equals(lwM2MClient.getState())) {
  97 + throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
  98 + }
  99 + Registration currentRegistration = lwM2MClient.getRegistration();
  100 + if (currentRegistration.getId().equals(registration.getId())) {
  101 + lwM2MClient.setRegistration(registration);
  102 + } else {
  103 + throw new LwM2MClientStateException(lwM2MClient.getState(), "Client has different registration.");
  104 + }
  105 + } finally {
  106 + lwM2MClient.unlock();
73 } 107 }
74 - LwM2mClient client = lwM2mClientsByRegistrationId.get(registration.getId());  
75 - if (client == null) {  
76 - client = lwM2mClientsByEndpoint.get(registration.getEndpoint());  
77 - if (client == null) {  
78 - client = registerOrUpdate(registration); 108 + }
  109 +
  110 + @Override
  111 + public void unregister(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException {
  112 + lwM2MClient.lock();
  113 + try {
  114 + if (!LwM2MClientState.REGISTERED.equals(lwM2MClient.getState())) {
  115 + throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
79 } 116 }
  117 + lwM2mClientsByRegistrationId.remove(registration.getId());
  118 + Registration currentRegistration = lwM2MClient.getRegistration();
  119 + if (currentRegistration.getId().equals(registration.getId())) {
  120 + lwM2MClient.setState(LwM2MClientState.UNREGISTERED);
  121 + lwM2mClientsByEndpoint.remove(lwM2MClient.getEndpoint());
  122 + this.securityStore.remove(lwM2MClient.getEndpoint());
  123 + this.lwM2mClientsByRegistrationId.remove(registration.getId());
  124 + UUID profileId = lwM2MClient.getProfileId();
  125 + if (profileId != null) {
  126 + Optional<LwM2mClient> otherClients = lwM2mClientsByRegistrationId.values().stream().filter(e -> e.getProfileId().equals(profileId)).findFirst();
  127 + if (otherClients.isEmpty()) {
  128 + profiles.remove(profileId);
  129 + }
  130 + }
  131 + } else {
  132 + throw new LwM2MClientStateException(lwM2MClient.getState(), "Client has different registration.");
  133 + }
  134 + } finally {
  135 + lwM2MClient.unlock();
80 } 136 }
81 - return client;  
82 } 137 }
83 138
84 @Override 139 @Override
85 - public LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo) {  
86 - LwM2mClient lwM2mClient = lwM2mClientsByEndpoint.values().stream().filter(c -> 140 + public LwM2mClient getClientByRegistrationId(String registrationId) {
  141 + return lwM2mClientsByRegistrationId.get(registrationId);
  142 + }
  143 +
  144 + @Override
  145 + public LwM2mClient getClientBySessionInfo(TransportProtos.SessionInfoProto sessionInfo) {
  146 + LwM2mClient lwM2mClient = lwM2mClientsByEndpoint.values().stream().filter(c ->
87 (new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())) 147 (new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()))
88 .equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB()))) 148 .equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB())))
89 149
90 - ).findAny().get(); 150 + ).findAny().orElse(null);
91 if (lwM2mClient == null) { 151 if (lwM2mClient == null) {
92 log.warn("Device TimeOut? lwM2mClient is null."); 152 log.warn("Device TimeOut? lwM2mClient is null.");
93 log.warn("SessionInfo input [{}], lwM2mClientsByEndpoint size: [{}]", sessionInfo, lwM2mClientsByEndpoint.values().size()); 153 log.warn("SessionInfo input [{}], lwM2mClientsByEndpoint size: [{}]", sessionInfo, lwM2mClientsByEndpoint.values().size());
@@ -96,60 +156,14 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { @@ -96,60 +156,14 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
96 return lwM2mClient; 156 return lwM2mClient;
97 } 157 }
98 158
99 - @Override  
100 - public LwM2mClient registerOrUpdate(Registration registration) {  
101 - LwM2mClient lwM2MClient = lwM2mClientsByEndpoint.get(registration.getEndpoint());  
102 - if (lwM2MClient == null) {  
103 - lwM2MClient = this.fetchClientByEndpoint(registration.getEndpoint());  
104 - }  
105 - lwM2MClient.setRegistration(registration);  
106 -// TODO: this remove is probably redundant. We should remove it.  
107 -// this.lwM2mClientsByEndpoint.remove(registration.getEndpoint());  
108 - this.lwM2mClientsByRegistrationId.put(registration.getId(), lwM2MClient);  
109 - return lwM2MClient;  
110 - }  
111 -  
112 public Registration getRegistration(String registrationId) { 159 public Registration getRegistration(String registrationId) {
113 return this.lwM2mClientsByRegistrationId.get(registrationId).getRegistration(); 160 return this.lwM2mClientsByRegistrationId.get(registrationId).getRegistration();
114 } 161 }
115 162
116 @Override 163 @Override
117 - public LwM2mClient fetchClientByEndpoint(String endpoint) {  
118 - EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endpoint, LwM2mTransportUtil.LwM2mTypeServer.CLIENT);  
119 - if (securityInfo.getSecurityMode() != null) {  
120 - if (securityInfo.getDeviceProfile() != null) {  
121 - UUID profileUuid = profileUpdate(securityInfo.getDeviceProfile())!= null ?  
122 - securityInfo.getDeviceProfile().getUuidId() : null;  
123 - // TODO: for tests bug.  
124 - if (profileUuid== null) {  
125 - log.trace("input parameters toClientProfile if the result is null: [{}]", securityInfo.getDeviceProfile());  
126 - }  
127 - LwM2mClient client;  
128 - if (securityInfo.getSecurityInfo() != null) {  
129 - client = new LwM2mClient(context.getNodeId(), securityInfo.getSecurityInfo().getEndpoint(),  
130 - securityInfo.getSecurityInfo().getIdentity(), securityInfo.getSecurityInfo(),  
131 - securityInfo.getMsg(), profileUuid, UUID.randomUUID());  
132 - } else if (NO_SEC.equals(securityInfo.getSecurityMode())) {  
133 - client = new LwM2mClient(context.getNodeId(), endpoint,  
134 - null, null,  
135 - securityInfo.getMsg(), profileUuid, UUID.randomUUID());  
136 - } else {  
137 - throw new RuntimeException(String.format("Registration failed: device %s not found.", endpoint));  
138 - }  
139 - lwM2mClientsByEndpoint.put(client.getEndpoint(), client);  
140 - return client;  
141 - } else {  
142 - throw new RuntimeException(String.format("Registration failed: device %s not found.", endpoint));  
143 - }  
144 - } else {  
145 - throw new RuntimeException(String.format("Registration failed: FORBIDDEN, endpointId: %s", endpoint));  
146 - }  
147 - }  
148 -  
149 - @Override  
150 public void registerClient(Registration registration, ValidateDeviceCredentialsResponse credentials) { 164 public void registerClient(Registration registration, ValidateDeviceCredentialsResponse credentials) {
151 - LwM2mClient client = new LwM2mClient(context.getNodeId(), registration.getEndpoint(), null, null, credentials, credentials.getDeviceProfile().getUuidId(), UUID.randomUUID());  
152 - lwM2mClientsByEndpoint.put(registration.getEndpoint(), client); 165 + LwM2mClient client = getClientByEndpoint(registration.getEndpoint());
  166 + client.init(null, null, credentials, credentials.getDeviceProfile().getUuidId(), UUID.randomUUID());
153 lwM2mClientsByRegistrationId.put(registration.getId(), client); 167 lwM2mClientsByRegistrationId.put(registration.getId(), client);
154 profileUpdate(credentials.getDeviceProfile()); 168 profileUpdate(credentials.getDeviceProfile());
155 } 169 }
@@ -171,7 +185,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { @@ -171,7 +185,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
171 185
172 @Override 186 @Override
173 public LwM2mClientProfile getProfile(Registration registration) { 187 public LwM2mClientProfile getProfile(Registration registration) {
174 - return this.getProfiles().get(getOrRegister(registration).getProfileId()); 188 + return this.getProfiles().get(getClientByEndpoint(registration.getEndpoint()).getProfileId());
175 } 189 }
176 190
177 @Override 191 @Override
@@ -186,25 +200,18 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { @@ -186,25 +200,18 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
186 if (lwM2MClientProfile != null) { 200 if (lwM2MClientProfile != null) {
187 profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); 201 profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
188 return lwM2MClientProfile; 202 return lwM2MClientProfile;
189 - }  
190 - else { 203 + } else {
191 return null; 204 return null;
192 } 205 }
193 } 206 }
194 207
195 - /**  
196 - * if isVer - ok or default ver=DEFAULT_LWM2M_VERSION  
197 - *  
198 - * @param registration -  
199 - * @return - all objectIdVer in client  
200 - */  
201 @Override 208 @Override
202 - public Set<String> getSupportedIdVerInClient(Registration registration) { 209 + public Set<String> getSupportedIdVerInClient(LwM2mClient client) {
203 Set<String> clientObjects = ConcurrentHashMap.newKeySet(); 210 Set<String> clientObjects = ConcurrentHashMap.newKeySet();
204 - Arrays.stream(registration.getObjectLinks()).forEach(url -> {  
205 - LwM2mPath pathIds = new LwM2mPath(url.getUrl()); 211 + Arrays.stream(client.getRegistration().getObjectLinks()).forEach(link -> {
  212 + LwM2mPath pathIds = new LwM2mPath(link.getUrl());
206 if (!pathIds.isRoot()) { 213 if (!pathIds.isRoot()) {
207 - clientObjects.add(convertPathFromObjectIdToIdVer(url.getUrl(), registration)); 214 + clientObjects.add(convertPathFromObjectIdToIdVer(link.getUrl(), client.getRegistration()));
208 } 215 }
209 }); 216 });
210 return (clientObjects.size() > 0) ? clientObjects : null; 217 return (clientObjects.size() > 0) ? clientObjects : null;
@@ -215,20 +222,4 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { @@ -215,20 +222,4 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
215 return lwM2mClientsByRegistrationId.values().stream().filter(e -> deviceId.equals(e.getDeviceId())).findFirst().orElse(null); 222 return lwM2mClientsByRegistrationId.values().stream().filter(e -> deviceId.equals(e.getDeviceId())).findFirst().orElse(null);
216 } 223 }
217 224
218 - @Override  
219 - public void removeClientByRegistrationId(String registrationId) {  
220 - LwM2mClient lwM2MClient = this.lwM2mClientsByRegistrationId.get(registrationId);  
221 - if (lwM2MClient != null) {  
222 - this.securityStore.remove(lwM2MClient.getEndpoint(), false);  
223 - this.lwM2mClientsByEndpoint.remove(lwM2MClient.getEndpoint());  
224 - this.lwM2mClientsByRegistrationId.remove(registrationId);  
225 - UUID profileId = lwM2MClient.getProfileId();  
226 - if (profileId != null) {  
227 - Optional<LwM2mClient> otherClients = lwM2mClientsByRegistrationId.values().stream().filter(e -> e.getProfileId().equals(profileId)).findFirst();  
228 - if (otherClients.isEmpty()) {  
229 - profiles.remove(profileId);  
230 - }  
231 - }  
232 - }  
233 - }  
234 } 225 }
@@ -167,9 +167,9 @@ public class LwM2mFwSwUpdate { @@ -167,9 +167,9 @@ public class LwM2mFwSwUpdate {
167 String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration()); 167 String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration());
168 String fwMsg = String.format("%s: Start type operation %s paths: %s", LOG_LW2M_INFO, 168 String fwMsg = String.format("%s: Start type operation %s paths: %s", LOG_LW2M_INFO,
169 LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), FW_PACKAGE_ID); 169 LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), FW_PACKAGE_ID);
170 - handler.sendLogsToThingsboard(fwMsg, lwM2MClient.getRegistration().getId()); 170 + handler.sendLogsToThingsboard(lwM2MClient, fwMsg);
171 log.warn("8) Start firmware Update. Send save to: [{}] ver: [{}] path: [{}]", this.lwM2MClient.getDeviceName(), this.currentVersion, targetIdVer); 171 log.warn("8) Start firmware Update. Send save to: [{}] ver: [{}] path: [{}]", this.lwM2MClient.getDeviceName(), this.currentVersion, targetIdVer);
172 - request.sendAllRequest(this.lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(), 172 + request.sendAllRequest(this.lwM2MClient, targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE,
173 firmwareChunk, handler.config.getTimeout(), this.rpcRequest); 173 firmwareChunk, handler.config.getTimeout(), this.rpcRequest);
174 } 174 }
175 else { 175 else {
@@ -190,7 +190,7 @@ public class LwM2mFwSwUpdate { @@ -190,7 +190,7 @@ public class LwM2mFwSwUpdate {
190 if (LOG_LW2M_ERROR.equals(typeInfo)) { 190 if (LOG_LW2M_ERROR.equals(typeInfo)) {
191 msg = String.format("%s Error: %s", msg, msgError); 191 msg = String.format("%s Error: %s", msg, msgError);
192 } 192 }
193 - handler.sendLogsToThingsboard(msg, lwM2MClient.getRegistration().getId()); 193 + handler.sendLogsToThingsboard(lwM2MClient, msg);
194 } 194 }
195 195
196 196
@@ -202,8 +202,7 @@ public class LwM2mFwSwUpdate { @@ -202,8 +202,7 @@ public class LwM2mFwSwUpdate {
202 public void executeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) { 202 public void executeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
203 this.setStateUpdate(UPDATING.name()); 203 this.setStateUpdate(UPDATING.name());
204 this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null); 204 this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null);
205 - request.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(),  
206 - null, 0, this.rpcRequest); 205 + request.sendAllRequest(this.lwM2MClient, this.pathInstallId, EXECUTE, null, 0, this.rpcRequest);
207 } 206 }
208 207
209 /** 208 /**
@@ -334,10 +333,10 @@ public class LwM2mFwSwUpdate { @@ -334,10 +333,10 @@ public class LwM2mFwSwUpdate {
334 } 333 }
335 334
336 private void observeStateUpdate(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) { 335 private void observeStateUpdate(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
337 - request.sendAllRequest(lwM2MClient.getRegistration(), 336 + request.sendAllRequest(lwM2MClient,
338 convertPathFromObjectIdToIdVer(this.pathStateId, this.lwM2MClient.getRegistration()), OBSERVE, 337 convertPathFromObjectIdToIdVer(this.pathStateId, this.lwM2MClient.getRegistration()), OBSERVE,
339 null, null, 0, null); 338 null, null, 0, null);
340 - request.sendAllRequest(lwM2MClient.getRegistration(), 339 + request.sendAllRequest(lwM2MClient,
341 convertPathFromObjectIdToIdVer(this.pathResultId, this.lwM2MClient.getRegistration()), OBSERVE, 340 convertPathFromObjectIdToIdVer(this.pathResultId, this.lwM2MClient.getRegistration()), OBSERVE,
342 null, null, 0, null); 341 null, null, 0, null);
343 } 342 }
@@ -364,8 +363,7 @@ public class LwM2mFwSwUpdate { @@ -364,8 +363,7 @@ public class LwM2mFwSwUpdate {
364 this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( 363 this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
365 this.pathResultId, this.lwM2MClient.getRegistration())); 364 this.pathResultId, this.lwM2MClient.getRegistration()));
366 this.pendingInfoRequestsStart.forEach(pathIdVer -> { 365 this.pendingInfoRequestsStart.forEach(pathIdVer -> {
367 - request.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, OBSERVE, ContentFormat.TLV.getName(),  
368 - null, 0, this.rpcRequest); 366 + request.sendAllRequest(this.lwM2MClient, pathIdVer, OBSERVE, null, 0, this.rpcRequest);
369 }); 367 });
370 368
371 } 369 }
@@ -273,7 +273,7 @@ public class Lwm2mClientRpcRequest { @@ -273,7 +273,7 @@ public class Lwm2mClientRpcRequest {
273 } 273 }
274 274
275 private String getRezIdByResourceNameAndObjectInstanceId(String resourceName, DefaultLwM2MTransportMsgHandler handler) { 275 private String getRezIdByResourceNameAndObjectInstanceId(String resourceName, DefaultLwM2MTransportMsgHandler handler) {
276 - LwM2mClient lwM2mClient = handler.clientContext.getClient(this.sessionInfo); 276 + LwM2mClient lwM2mClient = handler.clientContext.getClientBySessionInfo(this.sessionInfo);
277 return lwM2mClient != null ? 277 return lwM2mClient != null ?
278 lwM2mClient.getRezIdByResourceNameAndObjectInstanceId(resourceName, this.targetIdVer, handler.config.getModelProvider()) : 278 lwM2mClient.getRezIdByResourceNameAndObjectInstanceId(resourceName, this.targetIdVer, handler.config.getModelProvider()) :
279 null; 279 null;
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.store;
  17 +
  18 +import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
  19 +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
  20 +
  21 +public interface TbEditableSecurityStore extends TbSecurityStore {
  22 +
  23 + void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException;
  24 +
  25 + void remove(String endpoint);
  26 +
  27 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.store;
  17 +
  18 +import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
  19 +import org.eclipse.leshan.server.security.SecurityInfo;
  20 +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
  21 +
  22 +import java.util.HashMap;
  23 +import java.util.Map;
  24 +import java.util.concurrent.locks.Lock;
  25 +import java.util.concurrent.locks.ReadWriteLock;
  26 +import java.util.concurrent.locks.ReentrantReadWriteLock;
  27 +
  28 +public class TbInMemorySecurityStore implements TbEditableSecurityStore {
  29 + // lock for the two maps
  30 + protected final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  31 + protected final Lock readLock = readWriteLock.readLock();
  32 + protected final Lock writeLock = readWriteLock.writeLock();
  33 +
  34 + // by client end-point
  35 + protected Map<String, TbLwM2MSecurityInfo> securityByEp = new HashMap<>();
  36 +
  37 + // by PSK identity
  38 + protected Map<String, TbLwM2MSecurityInfo> securityByIdentity = new HashMap<>();
  39 +
  40 + public TbInMemorySecurityStore() {
  41 + }
  42 +
  43 + /**
  44 + * {@inheritDoc}
  45 + */
  46 + @Override
  47 + public SecurityInfo getByEndpoint(String endpoint) {
  48 + readLock.lock();
  49 + try {
  50 + TbLwM2MSecurityInfo securityInfo = securityByEp.get(endpoint);
  51 + if (securityInfo != null) {
  52 + return securityInfo.getSecurityInfo();
  53 + } else {
  54 + return null;
  55 + }
  56 + } finally {
  57 + readLock.unlock();
  58 + }
  59 + }
  60 +
  61 + /**
  62 + * {@inheritDoc}
  63 + */
  64 + @Override
  65 + public SecurityInfo getByIdentity(String identity) {
  66 + readLock.lock();
  67 + try {
  68 + TbLwM2MSecurityInfo securityInfo = securityByIdentity.get(identity);
  69 + if (securityInfo != null) {
  70 + return securityInfo.getSecurityInfo();
  71 + } else {
  72 + return null;
  73 + }
  74 + } finally {
  75 + readLock.unlock();
  76 + }
  77 + }
  78 +
  79 + @Override
  80 + public void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException {
  81 + writeLock.lock();
  82 + try {
  83 + String identity = null;
  84 + if (tbSecurityInfo.getSecurityInfo() != null) {
  85 + identity = tbSecurityInfo.getSecurityInfo().getIdentity();
  86 + if (identity != null) {
  87 + TbLwM2MSecurityInfo infoByIdentity = securityByIdentity.get(identity);
  88 + if (infoByIdentity != null && !tbSecurityInfo.getSecurityInfo().getEndpoint().equals(infoByIdentity.getEndpoint())) {
  89 + throw new NonUniqueSecurityInfoException("PSK Identity " + identity + " is already used");
  90 + }
  91 + securityByIdentity.put(tbSecurityInfo.getSecurityInfo().getIdentity(), tbSecurityInfo);
  92 + }
  93 + }
  94 +
  95 + TbLwM2MSecurityInfo previous = securityByEp.put(tbSecurityInfo.getEndpoint(), tbSecurityInfo);
  96 + if (previous != null && previous.getSecurityInfo() != null) {
  97 + String previousIdentity = previous.getSecurityInfo().getIdentity();
  98 + if (previousIdentity != null && !previousIdentity.equals(identity)) {
  99 + securityByIdentity.remove(previousIdentity);
  100 + }
  101 + }
  102 + } finally {
  103 + writeLock.unlock();
  104 + }
  105 + }
  106 +
  107 + @Override
  108 + public void remove(String endpoint) {
  109 + writeLock.lock();
  110 + try {
  111 + TbLwM2MSecurityInfo securityInfo = securityByEp.remove(endpoint);
  112 + if (securityInfo != null && securityInfo.getSecurityInfo() != null && securityInfo.getSecurityInfo().getIdentity() != null) {
  113 + securityByIdentity.remove(securityInfo.getSecurityInfo().getIdentity());
  114 + }
  115 + } finally {
  116 + writeLock.unlock();
  117 + }
  118 + }
  119 +
  120 + @Override
  121 + public TbLwM2MSecurityInfo getTbLwM2MSecurityInfoByEndpoint(String endpoint) {
  122 + readLock.lock();
  123 + try {
  124 + return securityByEp.get(endpoint);
  125 + } finally {
  126 + readLock.unlock();
  127 + }
  128 + }
  129 +
  130 +}
@@ -22,11 +22,13 @@ import org.eclipse.leshan.core.Destroyable; @@ -22,11 +22,13 @@ import org.eclipse.leshan.core.Destroyable;
22 import org.eclipse.leshan.core.Startable; 22 import org.eclipse.leshan.core.Startable;
23 import org.eclipse.leshan.core.Stoppable; 23 import org.eclipse.leshan.core.Stoppable;
24 import org.eclipse.leshan.core.observation.Observation; 24 import org.eclipse.leshan.core.observation.Observation;
  25 +import org.eclipse.leshan.core.request.Identity;
25 import org.eclipse.leshan.core.util.NamedThreadFactory; 26 import org.eclipse.leshan.core.util.NamedThreadFactory;
26 import org.eclipse.leshan.core.util.Validate; 27 import org.eclipse.leshan.core.util.Validate;
27 import org.eclipse.leshan.server.californium.observation.ObserveUtil; 28 import org.eclipse.leshan.server.californium.observation.ObserveUtil;
28 import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; 29 import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
29 import org.eclipse.leshan.server.redis.RedisRegistrationStore; 30 import org.eclipse.leshan.server.redis.RedisRegistrationStore;
  31 +import org.eclipse.leshan.server.redis.serialization.IdentitySerDes;
30 import org.eclipse.leshan.server.redis.serialization.ObservationSerDes; 32 import org.eclipse.leshan.server.redis.serialization.ObservationSerDes;
31 import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes; 33 import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes;
32 import org.eclipse.leshan.server.registration.Deregistration; 34 import org.eclipse.leshan.server.registration.Deregistration;
@@ -73,6 +75,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -73,6 +75,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
73 private static final String REG_EP = "REG:EP:"; // (Endpoint => Registration) 75 private static final String REG_EP = "REG:EP:"; // (Endpoint => Registration)
74 private static final String REG_EP_REGID_IDX = "EP:REGID:"; // secondary index key (Registration ID => Endpoint) 76 private static final String REG_EP_REGID_IDX = "EP:REGID:"; // secondary index key (Registration ID => Endpoint)
75 private static final String REG_EP_ADDR_IDX = "EP:ADDR:"; // secondary index key (Socket Address => Endpoint) 77 private static final String REG_EP_ADDR_IDX = "EP:ADDR:"; // secondary index key (Socket Address => Endpoint)
  78 + private static final String REG_EP_IDENTITY = "EP:IDENTITY:"; // secondary index key (Identity => Endpoint)
76 private static final String LOCK_EP = "LOCK:EP:"; 79 private static final String LOCK_EP = "LOCK:EP:";
77 private static final byte[] OBS_TKN = "OBS:TKN:".getBytes(UTF_8); 80 private static final byte[] OBS_TKN = "OBS:TKN:".getBytes(UTF_8);
78 private static final String OBS_TKNS_REGID_IDX = "TKNS:REGID:"; // secondary index (token list by registration) 81 private static final String OBS_TKNS_REGID_IDX = "TKNS:REGID:"; // secondary index (token list by registration)
@@ -155,6 +158,8 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -155,6 +158,8 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
155 connection.set(regid_idx, registration.getEndpoint().getBytes(UTF_8)); 158 connection.set(regid_idx, registration.getEndpoint().getBytes(UTF_8));
156 byte[] addr_idx = toRegAddrKey(registration.getSocketAddress()); 159 byte[] addr_idx = toRegAddrKey(registration.getSocketAddress());
157 connection.set(addr_idx, registration.getEndpoint().getBytes(UTF_8)); 160 connection.set(addr_idx, registration.getEndpoint().getBytes(UTF_8));
  161 + byte[] identity_idx = toRegIdentityKey(registration.getIdentity());
  162 + connection.set(identity_idx, registration.getEndpoint().getBytes(UTF_8));
158 163
159 // Add or update expiration 164 // Add or update expiration
160 addOrUpdateExpiration(connection, registration); 165 addOrUpdateExpiration(connection, registration);
@@ -167,6 +172,9 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -167,6 +172,9 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
167 if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) { 172 if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) {
168 removeAddrIndex(connection, oldRegistration); 173 removeAddrIndex(connection, oldRegistration);
169 } 174 }
  175 + if (!oldRegistration.getIdentity().equals(registration.getIdentity())) {
  176 + removeIdentityIndex(connection, oldRegistration);
  177 + }
170 // remove old observation 178 // remove old observation
171 Collection<Observation> obsRemoved = unsafeRemoveAllObservations(connection, oldRegistration.getId()); 179 Collection<Observation> obsRemoved = unsafeRemoveAllObservations(connection, oldRegistration.getId());
172 180
@@ -222,6 +230,9 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -222,6 +230,9 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
222 if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) { 230 if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) {
223 removeAddrIndex(connection, r); 231 removeAddrIndex(connection, r);
224 } 232 }
  233 + if (!r.getIdentity().equals(updatedRegistration.getIdentity())) {
  234 + removeIdentityIndex(connection, r);
  235 + }
225 236
226 return new UpdatedRegistration(r, updatedRegistration); 237 return new UpdatedRegistration(r, updatedRegistration);
227 238
@@ -269,6 +280,22 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -269,6 +280,22 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
269 } 280 }
270 281
271 @Override 282 @Override
  283 + public Registration getRegistrationByIdentity(Identity identity) {
  284 + Validate.notNull(identity);
  285 + try (var connection = connectionFactory.getConnection()) {
  286 + byte[] ep = connection.get(toRegIdentityKey(identity));
  287 + if (ep == null) {
  288 + return null;
  289 + }
  290 + byte[] data = connection.get(toEndpointKey(ep));
  291 + if (data == null) {
  292 + return null;
  293 + }
  294 + return deserializeReg(data);
  295 + }
  296 + }
  297 +
  298 + @Override
272 public Iterator<Registration> getAllRegistrations() { 299 public Iterator<Registration> getAllRegistrations() {
273 try (var connection = connectionFactory.getConnection()) { 300 try (var connection = connectionFactory.getConnection()) {
274 Collection<Registration> list = new LinkedList<>(); 301 Collection<Registration> list = new LinkedList<>();
@@ -325,6 +352,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -325,6 +352,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
325 connection.del(toEndpointKey(r.getEndpoint())); 352 connection.del(toEndpointKey(r.getEndpoint()));
326 Collection<Observation> obsRemoved = unsafeRemoveAllObservations(connection, r.getId()); 353 Collection<Observation> obsRemoved = unsafeRemoveAllObservations(connection, r.getId());
327 removeAddrIndex(connection, r); 354 removeAddrIndex(connection, r);
  355 + removeIdentityIndex(connection, r);
328 removeExpiration(connection, r); 356 removeExpiration(connection, r);
329 return new Deregistration(r, obsRemoved); 357 return new Deregistration(r, obsRemoved);
330 } 358 }
@@ -337,20 +365,27 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -337,20 +365,27 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
337 } 365 }
338 } 366 }
339 367
  368 + private void removeAddrIndex(RedisConnection connection, Registration r) {
  369 + removeSecondaryIndex(connection, toRegAddrKey(r.getSocketAddress()), r.getEndpoint());
  370 + }
  371 +
  372 + private void removeIdentityIndex(RedisConnection connection, Registration r) {
  373 + removeSecondaryIndex(connection, toRegIdentityKey(r.getIdentity()), r.getEndpoint());
  374 + }
  375 +
340 //TODO: JedisCluster didn't implement Transaction, maybe should use some advanced key creation strategies 376 //TODO: JedisCluster didn't implement Transaction, maybe should use some advanced key creation strategies
341 - private void removeAddrIndex(RedisConnection connection, Registration registration) { 377 + private void removeSecondaryIndex(RedisConnection connection, byte[] indexKey, String endpointName) {
342 // Watch the key to remove. 378 // Watch the key to remove.
343 - byte[] regAddrKey = toRegAddrKey(registration.getSocketAddress());  
344 -// connection.watch(regAddrKey); 379 +// connection.watch(indexKey);
345 380
346 - byte[] epFromAddr = connection.get(regAddrKey); 381 + byte[] epFromAddr = connection.get(indexKey);
347 // Delete the key if needed. 382 // Delete the key if needed.
348 - if (Arrays.equals(epFromAddr, registration.getEndpoint().getBytes(UTF_8))) { 383 + if (Arrays.equals(epFromAddr, endpointName.getBytes(UTF_8))) {
349 // Try to delete the key 384 // Try to delete the key
350 // connection.multi(); 385 // connection.multi();
351 - connection.del(regAddrKey); 386 + connection.del(indexKey);
352 // connection.exec(); 387 // connection.exec();
353 - // if transaction failed this is not an issue as the socket address is probably reused and we don't neeed to 388 + // if transaction failed this is not an issue as the index is probably reused and we don't need to
354 // delete it anymore. 389 // delete it anymore.
355 } else { 390 } else {
356 // the key must not be deleted. 391 // the key must not be deleted.
@@ -374,6 +409,10 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -374,6 +409,10 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
374 return toKey(REG_EP_ADDR_IDX, addr.getAddress().toString() + ":" + addr.getPort()); 409 return toKey(REG_EP_ADDR_IDX, addr.getAddress().toString() + ":" + addr.getPort());
375 } 410 }
376 411
  412 + private byte[] toRegIdentityKey(Identity identity) {
  413 + return toKey(REG_EP_IDENTITY, IdentitySerDes.serialize(identity).toString());
  414 + }
  415 +
377 private byte[] toEndpointKey(String endpoint) { 416 private byte[] toEndpointKey(String endpoint) {
378 return toKey(REG_EP, endpoint); 417 return toKey(REG_EP, endpoint);
379 } 418 }
@@ -723,7 +762,6 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto @@ -723,7 +762,6 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
723 762
724 @Override 763 @Override
725 public void run() { 764 public void run() {
726 -  
727 try (var connection = connectionFactory.getConnection()) { 765 try (var connection = connectionFactory.getConnection()) {
728 Set<byte[]> endpointsExpired = connection.zRangeByScore(EXP_EP, Double.NEGATIVE_INFINITY, 766 Set<byte[]> endpointsExpired = connection.zRangeByScore(EXP_EP, Double.NEGATIVE_INFINITY,
729 System.currentTimeMillis(), 0, cleanLimit); 767 System.currentTimeMillis(), 0, cleanLimit);
@@ -24,13 +24,14 @@ import org.springframework.data.redis.connection.RedisClusterConnection; @@ -24,13 +24,14 @@ import org.springframework.data.redis.connection.RedisClusterConnection;
24 import org.springframework.data.redis.connection.RedisConnectionFactory; 24 import org.springframework.data.redis.connection.RedisConnectionFactory;
25 import org.springframework.data.redis.core.Cursor; 25 import org.springframework.data.redis.core.Cursor;
26 import org.springframework.data.redis.core.ScanOptions; 26 import org.springframework.data.redis.core.ScanOptions;
  27 +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
27 28
28 import java.util.ArrayList; 29 import java.util.ArrayList;
29 import java.util.Collection; 30 import java.util.Collection;
30 import java.util.LinkedList; 31 import java.util.LinkedList;
31 import java.util.List; 32 import java.util.List;
32 33
33 -public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { 34 +public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore {
34 private static final String SEC_EP = "SEC#EP#"; 35 private static final String SEC_EP = "SEC#EP#";
35 36
36 private static final String PSKID_SEC = "PSKID#SEC"; 37 private static final String PSKID_SEC = "PSKID#SEC";
@@ -72,73 +73,89 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { @@ -72,73 +73,89 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore {
72 } 73 }
73 74
74 @Override 75 @Override
75 - public Collection<SecurityInfo> getAll() {  
76 - try (var connection = connectionFactory.getConnection()) {  
77 - Collection<SecurityInfo> list = new LinkedList<>();  
78 - ScanOptions scanOptions = ScanOptions.scanOptions().count(100).match(SEC_EP + "*").build();  
79 - List<Cursor<byte[]>> scans = new ArrayList<>();  
80 - if (connection instanceof RedisClusterConnection) {  
81 - ((RedisClusterConnection) connection).clusterGetNodes().forEach(node -> {  
82 - scans.add(((RedisClusterConnection) connection).scan(node, scanOptions));  
83 - });  
84 - } else {  
85 - scans.add(connection.scan(scanOptions));  
86 - }  
87 -  
88 - scans.forEach(scan -> {  
89 - scan.forEachRemaining(key -> {  
90 - byte[] element = connection.get(key);  
91 - list.add(deserialize(element));  
92 - });  
93 - });  
94 - return list;  
95 - } 76 + public void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException {
  77 + //TODO: implement
96 } 78 }
97 79
98 @Override 80 @Override
99 - public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {  
100 - byte[] data = serialize(info);  
101 - try (var connection = connectionFactory.getConnection()) {  
102 - if (info.getIdentity() != null) {  
103 - // populate the secondary index (security info by PSK id)  
104 - String oldEndpoint = new String(connection.hGet(PSKID_SEC.getBytes(), info.getIdentity().getBytes()));  
105 - if (!oldEndpoint.equals(info.getEndpoint())) {  
106 - throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used");  
107 - }  
108 - connection.hSet(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes());  
109 - }  
110 -  
111 - byte[] previousData = connection.getSet((SEC_EP + info.getEndpoint()).getBytes(), data);  
112 - SecurityInfo previous = previousData == null ? null : deserialize(previousData);  
113 - String previousIdentity = previous == null ? null : previous.getIdentity();  
114 - if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) {  
115 - connection.hDel(PSKID_SEC.getBytes(), previousIdentity.getBytes());  
116 - }  
117 -  
118 - return previous;  
119 - } 81 + public TbLwM2MSecurityInfo getTbLwM2MSecurityInfoByEndpoint(String endpoint) {
  82 + //TODO: implement
  83 + return null;
120 } 84 }
121 85
122 @Override 86 @Override
123 - public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {  
124 - try (var connection = connectionFactory.getConnection()) {  
125 - byte[] data = connection.get((SEC_EP + endpoint).getBytes());  
126 -  
127 - if (data != null) {  
128 - SecurityInfo info = deserialize(data);  
129 - if (info.getIdentity() != null) {  
130 - connection.hDel(PSKID_SEC.getBytes(), info.getIdentity().getBytes());  
131 - }  
132 - connection.del((SEC_EP + endpoint).getBytes());  
133 - if (listener != null) {  
134 - listener.securityInfoRemoved(infosAreCompromised, info);  
135 - }  
136 - return info;  
137 - }  
138 - }  
139 - return null; 87 + public void remove(String endpoint) {
  88 + //TODO: implement
140 } 89 }
141 90
  91 + // @Override
  92 +// public Collection<SecurityInfo> getAll() {
  93 +// try (var connection = connectionFactory.getConnection()) {
  94 +// Collection<SecurityInfo> list = new LinkedList<>();
  95 +// ScanOptions scanOptions = ScanOptions.scanOptions().count(100).match(SEC_EP + "*").build();
  96 +// List<Cursor<byte[]>> scans = new ArrayList<>();
  97 +// if (connection instanceof RedisClusterConnection) {
  98 +// ((RedisClusterConnection) connection).clusterGetNodes().forEach(node -> {
  99 +// scans.add(((RedisClusterConnection) connection).scan(node, scanOptions));
  100 +// });
  101 +// } else {
  102 +// scans.add(connection.scan(scanOptions));
  103 +// }
  104 +//
  105 +// scans.forEach(scan -> {
  106 +// scan.forEachRemaining(key -> {
  107 +// byte[] element = connection.get(key);
  108 +// list.add(deserialize(element));
  109 +// });
  110 +// });
  111 +// return list;
  112 +// }
  113 +// }
  114 +//
  115 +// @Override
  116 +// public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {
  117 +// byte[] data = serialize(info);
  118 +// try (var connection = connectionFactory.getConnection()) {
  119 +// if (info.getIdentity() != null) {
  120 +// // populate the secondary index (security info by PSK id)
  121 +// String oldEndpoint = new String(connection.hGet(PSKID_SEC.getBytes(), info.getIdentity().getBytes()));
  122 +// if (!oldEndpoint.equals(info.getEndpoint())) {
  123 +// throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used");
  124 +// }
  125 +// connection.hSet(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes());
  126 +// }
  127 +//
  128 +// byte[] previousData = connection.getSet((SEC_EP + info.getEndpoint()).getBytes(), data);
  129 +// SecurityInfo previous = previousData == null ? null : deserialize(previousData);
  130 +// String previousIdentity = previous == null ? null : previous.getIdentity();
  131 +// if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) {
  132 +// connection.hDel(PSKID_SEC.getBytes(), previousIdentity.getBytes());
  133 +// }
  134 +//
  135 +// return previous;
  136 +// }
  137 +// }
  138 +//
  139 +// @Override
  140 +// public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {
  141 +// try (var connection = connectionFactory.getConnection()) {
  142 +// byte[] data = connection.get((SEC_EP + endpoint).getBytes());
  143 +//
  144 +// if (data != null) {
  145 +// SecurityInfo info = deserialize(data);
  146 +// if (info.getIdentity() != null) {
  147 +// connection.hDel(PSKID_SEC.getBytes(), info.getIdentity().getBytes());
  148 +// }
  149 +// connection.del((SEC_EP + endpoint).getBytes());
  150 +// if (listener != null) {
  151 +// listener.securityInfoRemoved(infosAreCompromised, info);
  152 +// }
  153 +// return info;
  154 +// }
  155 +// }
  156 +// return null;
  157 +// }
  158 +
142 private byte[] serialize(SecurityInfo secInfo) { 159 private byte[] serialize(SecurityInfo secInfo) {
143 return SecurityInfoSerDes.serialize(secInfo); 160 return SecurityInfoSerDes.serialize(secInfo);
144 } 161 }
@@ -147,8 +164,4 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { @@ -147,8 +164,4 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore {
147 return SecurityInfoSerDes.deserialize(data); 164 return SecurityInfoSerDes.deserialize(data);
148 } 165 }
149 166
150 - @Override  
151 - public void setListener(SecurityStoreListener listener) {  
152 - this.listener = listener;  
153 - }  
154 } 167 }
@@ -19,63 +19,39 @@ import lombok.extern.slf4j.Slf4j; @@ -19,63 +19,39 @@ import lombok.extern.slf4j.Slf4j;
19 import org.eclipse.leshan.server.security.EditableSecurityStore; 19 import org.eclipse.leshan.server.security.EditableSecurityStore;
20 import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; 20 import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
21 import org.eclipse.leshan.server.security.SecurityInfo; 21 import org.eclipse.leshan.server.security.SecurityInfo;
  22 +import org.eclipse.leshan.server.security.SecurityStore;
22 import org.eclipse.leshan.server.security.SecurityStoreListener; 23 import org.eclipse.leshan.server.security.SecurityStoreListener;
  24 +import org.jetbrains.annotations.Nullable;
23 import org.springframework.stereotype.Component; 25 import org.springframework.stereotype.Component;
24 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 26 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
25 -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 27 +import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
  28 +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
  29 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
26 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 30 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
27 31
28 import java.util.Collection; 32 import java.util.Collection;
29 33
30 @Slf4j 34 @Slf4j
31 -@Component  
32 -@TbLwM2mTransportComponent  
33 -public class TbLwM2mSecurityStore implements EditableSecurityStore { 35 +public class TbLwM2mSecurityStore implements TbEditableSecurityStore {
34 36
35 - private final LwM2mClientContext clientContext;  
36 - private final EditableSecurityStore securityStore; 37 + private final TbEditableSecurityStore securityStore;
  38 + private final LwM2mCredentialsSecurityInfoValidator validator;
37 39
38 - public TbLwM2mSecurityStore(LwM2mClientContext clientContext, EditableSecurityStore securityStore) {  
39 - this.clientContext = clientContext; 40 + public TbLwM2mSecurityStore(TbEditableSecurityStore securityStore, LwM2mCredentialsSecurityInfoValidator validator) {
40 this.securityStore = securityStore; 41 this.securityStore = securityStore;
  42 + this.validator = validator;
41 } 43 }
42 44
43 @Override 45 @Override
44 - public Collection<SecurityInfo> getAll() {  
45 - return securityStore.getAll();  
46 - }  
47 -  
48 - @Override  
49 - public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {  
50 - return securityStore.add(info);  
51 - }  
52 -  
53 - @Override  
54 - public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {  
55 - return securityStore.remove(endpoint, infosAreCompromised);  
56 - }  
57 -  
58 - @Override  
59 - public void setListener(SecurityStoreListener listener) {  
60 - securityStore.setListener(listener); 46 + public TbLwM2MSecurityInfo getTbLwM2MSecurityInfoByEndpoint(String endpoint) {
  47 + return securityStore.getTbLwM2MSecurityInfoByEndpoint(endpoint);
61 } 48 }
62 49
63 @Override 50 @Override
64 public SecurityInfo getByEndpoint(String endpoint) { 51 public SecurityInfo getByEndpoint(String endpoint) {
65 SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint); 52 SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint);
66 if (securityInfo == null) { 53 if (securityInfo == null) {
67 - LwM2mClient lwM2mClient = clientContext.getClientByEndpoint(endpoint);  
68 - if (lwM2mClient != null && lwM2mClient.getRegistration() != null && !lwM2mClient.getRegistration().getIdentity().isSecure()) {  
69 - return null;  
70 - }  
71 - securityInfo = clientContext.fetchClientByEndpoint(endpoint).getSecurityInfo();  
72 - try {  
73 - if (securityInfo != null) {  
74 - add(securityInfo);  
75 - }  
76 - } catch (NonUniqueSecurityInfoException e) {  
77 - log.trace("Failed to add security info: {}", securityInfo, e);  
78 - } 54 + securityInfo = fetchAndPutSecurityInfo(endpoint);
79 } 55 }
80 return securityInfo; 56 return securityInfo;
81 } 57 }
@@ -84,15 +60,31 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore { @@ -84,15 +60,31 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore {
84 public SecurityInfo getByIdentity(String pskIdentity) { 60 public SecurityInfo getByIdentity(String pskIdentity) {
85 SecurityInfo securityInfo = securityStore.getByIdentity(pskIdentity); 61 SecurityInfo securityInfo = securityStore.getByIdentity(pskIdentity);
86 if (securityInfo == null) { 62 if (securityInfo == null) {
87 - securityInfo = clientContext.fetchClientByEndpoint(pskIdentity).getSecurityInfo();  
88 - try {  
89 - if (securityInfo != null) {  
90 - add(securityInfo);  
91 - }  
92 - } catch (NonUniqueSecurityInfoException e) {  
93 - log.trace("Failed to add security info: {}", securityInfo, e);  
94 - } 63 + securityInfo = fetchAndPutSecurityInfo(pskIdentity);
95 } 64 }
96 return securityInfo; 65 return securityInfo;
97 } 66 }
  67 +
  68 + @Nullable
  69 + public SecurityInfo fetchAndPutSecurityInfo(String credentialsId) {
  70 + TbLwM2MSecurityInfo securityInfo = validator.getEndpointSecurityInfoByCredentialsId(credentialsId, LwM2mTransportUtil.LwM2mTypeServer.CLIENT);
  71 + try {
  72 + if (securityInfo != null) {
  73 + securityStore.put(securityInfo);
  74 + }
  75 + } catch (NonUniqueSecurityInfoException e) {
  76 + log.trace("Failed to add security info: {}", securityInfo, e);
  77 + }
  78 + return securityInfo != null ? securityInfo.getSecurityInfo() : null;
  79 + }
  80 +
  81 + @Override
  82 + public void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException {
  83 + securityStore.put(tbSecurityInfo);
  84 + }
  85 +
  86 + @Override
  87 + public void remove(String endpoint) {
  88 + securityStore.remove(endpoint);
  89 + }
98 } 90 }
@@ -17,17 +17,14 @@ package org.thingsboard.server.transport.lwm2m.server.store; @@ -17,17 +17,14 @@ package org.thingsboard.server.transport.lwm2m.server.store;
17 17
18 import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; 18 import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
19 import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore; 19 import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore;
20 -import org.eclipse.leshan.server.security.EditableSecurityStore;  
21 -import org.eclipse.leshan.server.security.InMemorySecurityStore;  
22 import org.springframework.beans.factory.annotation.Autowired; 20 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.beans.factory.annotation.Value; 21 import org.springframework.beans.factory.annotation.Value;
24 import org.springframework.context.annotation.Bean; 22 import org.springframework.context.annotation.Bean;
25 -import org.springframework.context.annotation.Lazy;  
26 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
27 import org.thingsboard.server.cache.TBRedisCacheConfiguration; 24 import org.thingsboard.server.cache.TBRedisCacheConfiguration;
28 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 25 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
29 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 26 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
30 -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 27 +import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
31 28
32 import java.util.Optional; 29 import java.util.Optional;
33 30
@@ -42,8 +39,7 @@ public class TbLwM2mStoreFactory { @@ -42,8 +39,7 @@ public class TbLwM2mStoreFactory {
42 private LwM2MTransportServerConfig config; 39 private LwM2MTransportServerConfig config;
43 40
44 @Autowired 41 @Autowired
45 - @Lazy  
46 - private LwM2mClientContext clientContext; 42 + private LwM2mCredentialsSecurityInfoValidator validator;
47 43
48 @Value("${transport.lwm2m.redis.enabled:false}") 44 @Value("${transport.lwm2m.redis.enabled:false}")
49 private boolean useRedis; 45 private boolean useRedis;
@@ -55,9 +51,9 @@ public class TbLwM2mStoreFactory { @@ -55,9 +51,9 @@ public class TbLwM2mStoreFactory {
55 } 51 }
56 52
57 @Bean 53 @Bean
58 - private EditableSecurityStore securityStore() {  
59 - return new TbLwM2mSecurityStore(clientContext, redisConfiguration.isPresent() && useRedis ?  
60 - new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new InMemorySecurityStore()); 54 + private TbEditableSecurityStore securityStore() {
  55 + return new TbLwM2mSecurityStore(redisConfiguration.isPresent() && useRedis ?
  56 + new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new TbInMemorySecurityStore(), validator);
61 } 57 }
62 58
63 @Bean 59 @Bean
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.store;
  17 +
  18 +import org.eclipse.leshan.server.security.SecurityStore;
  19 +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
  20 +
  21 +public interface TbSecurityStore extends SecurityStore {
  22 +
  23 + TbLwM2MSecurityInfo getTbLwM2MSecurityInfoByEndpoint(String endpoint);
  24 +
  25 +}
@@ -69,9 +69,7 @@ @@ -69,9 +69,7 @@
69 <jackson-core.version>2.12.1</jackson-core.version> 69 <jackson-core.version>2.12.1</jackson-core.version>
70 <json-schema-validator.version>2.2.6</json-schema-validator.version> 70 <json-schema-validator.version>2.2.6</json-schema-validator.version>
71 <californium.version>2.6.1</californium.version> 71 <californium.version>2.6.1</californium.version>
72 - <leshan-server.version>1.3.1</leshan-server.version>  
73 - <leshan-core.version>1.3.1</leshan-core.version>  
74 - <leshan-client.version>1.3.1</leshan-client.version> 72 + <leshan.version>2.0.0-M3</leshan.version>
75 <gson.version>2.6.2</gson.version> 73 <gson.version>2.6.2</gson.version>
76 <freemarker.version>2.3.30</freemarker.version> 74 <freemarker.version>2.3.30</freemarker.version>
77 <mail.version>1.6.2</mail.version> 75 <mail.version>1.6.2</mail.version>
@@ -1222,22 +1220,22 @@ @@ -1222,22 +1220,22 @@
1222 <dependency> 1220 <dependency>
1223 <groupId>org.eclipse.leshan</groupId> 1221 <groupId>org.eclipse.leshan</groupId>
1224 <artifactId>leshan-server-cf</artifactId> 1222 <artifactId>leshan-server-cf</artifactId>
1225 - <version>${leshan-server.version}</version> 1223 + <version>${leshan.version}</version>
1226 </dependency> 1224 </dependency>
1227 <dependency> 1225 <dependency>
1228 <groupId>org.eclipse.leshan</groupId> 1226 <groupId>org.eclipse.leshan</groupId>
1229 <artifactId>leshan-client-cf</artifactId> 1227 <artifactId>leshan-client-cf</artifactId>
1230 - <version>${leshan-client.version}</version> 1228 + <version>${leshan.version}</version>
1231 </dependency> 1229 </dependency>
1232 <dependency> 1230 <dependency>
1233 <groupId>org.eclipse.leshan</groupId> 1231 <groupId>org.eclipse.leshan</groupId>
1234 <artifactId>leshan-server-redis</artifactId> 1232 <artifactId>leshan-server-redis</artifactId>
1235 - <version>${leshan-server.version}</version> 1233 + <version>${leshan.version}</version>
1236 </dependency> 1234 </dependency>
1237 <dependency> 1235 <dependency>
1238 <groupId>org.eclipse.leshan</groupId> 1236 <groupId>org.eclipse.leshan</groupId>
1239 <artifactId>leshan-core</artifactId> 1237 <artifactId>leshan-core</artifactId>
1240 - <version>${leshan-core.version}</version> 1238 + <version>${leshan.version}</version>
1241 </dependency> 1239 </dependency>
1242 <dependency> 1240 <dependency>
1243 <groupId>org.eclipse.californium</groupId> 1241 <groupId>org.eclipse.californium</groupId>