diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java index f44664c256..cc648d52d5 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java @@ -52,6 +52,8 @@ import static org.junit.Assert.assertNotNull; @Slf4j public abstract class AbstractCoapIntegrationTest extends AbstractTransportIntegrationTest { + protected final byte[] EMPTY_PAYLOAD = new byte[0]; + protected CoapClient client; @Override diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/AbstractCoapAttributesUpdatesProtoIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/AbstractCoapAttributesUpdatesProtoIntegrationTest.java index d4dea4382a..3cf1884bc5 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/AbstractCoapAttributesUpdatesProtoIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/AbstractCoapAttributesUpdatesProtoIntegrationTest.java @@ -25,15 +25,13 @@ import org.thingsboard.server.common.data.CoapDeviceType; import org.thingsboard.server.common.data.TransportPayloadType; import org.thingsboard.server.gen.transport.TransportProtos; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertTrue; @Slf4j @@ -88,7 +86,7 @@ public abstract class AbstractCoapAttributesUpdatesProtoIntegrationTest extends } protected void validateEmptyCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { - assertNull(callback.getPayloadBytes()); + assertArrayEquals(EMPTY_PAYLOAD, callback.getPayloadBytes()); assertNotNull(callback.getObserve()); assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode()); assertEquals(0, callback.getObserve().intValue()); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java index 4ba151c857..d598a82ccb 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java @@ -31,13 +31,12 @@ import org.thingsboard.server.common.data.TransportPayloadType; import org.thingsboard.server.common.msg.session.FeatureType; import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; -import java.nio.charset.StandardCharsets; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -186,7 +185,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC } private void validateCurrentStateNotification(TestCoapCallback callback) { - assertNull(callback.getPayloadBytes()); + assertArrayEquals(EMPTY_PAYLOAD, callback.getPayloadBytes()); assertNotNull(callback.getObserve()); assertEquals(callback.getResponseCode(), CoAP.ResponseCode.VALID); assertEquals(0, callback.getObserve().intValue()); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 44f9f3d52d..fd4c748f85 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -17,7 +17,7 @@ package org.thingsboard.server.transport.lwm2m; import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.io.IOUtils; -import org.eclipse.californium.core.network.config.NetworkConfig; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; import org.junit.After; import org.junit.Assert; @@ -174,7 +174,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest public void basicTestConnectionObserveTelemetry(Security security, LwM2MClientCredential credentials, - NetworkConfig coapConfig, + Configuration coapConfig, String endpoint) throws Exception { createDeviceProfile(TRANSPORT_CONFIGURATION); Device device = createDevice(credentials); @@ -259,7 +259,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest this.resources = resources; } - public void createNewClient(Security security, NetworkConfig coapConfig, boolean isRpc, String endpoint) throws Exception { + public void createNewClient(Security security, Configuration coapConfig, boolean isRpc, String endpoint) throws Exception { clientDestroy(); client = new LwM2MTestClient(this.executor, endpoint); int clientPort = SocketUtils.findAvailableTcpPort(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java index 29771e1db8..2d10c50bc4 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java @@ -15,9 +15,11 @@ */ package org.thingsboard.server.transport.lwm2m; -import org.eclipse.californium.core.network.config.NetworkConfig; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; +import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; +import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; import static org.eclipse.leshan.client.object.Security.noSec; public class Lwm2mTestHelper { @@ -32,10 +34,10 @@ public class Lwm2mTestHelper { public static final int SHORT_SERVER_ID = 123; public static final int SHORT_SERVER_ID_BS = 111; - public static final NetworkConfig SECURE_COAP_CONFIG = new NetworkConfig().setString("COAP_SECURE_PORT", Integer.toString(SECURE_PORT)); + public static final Configuration SECURE_COAP_CONFIG = new Configuration().set(COAP_SECURE_PORT, SECURE_PORT); public static final String SECURE_URI = "coaps://" + HOST + ":" + SECURE_PORT; public static final Security SECURITY = noSec("coap://"+ HOST +":" + PORT, SHORT_SERVER_ID); - public static final NetworkConfig COAP_CONFIG = new NetworkConfig().setString("COAP_PORT", Integer.toString(PORT)); + public static final Configuration COAP_CONFIG = new Configuration().set(COAP_PORT, PORT); // Models public static final String[] resources = new String[]{"0.xml", "1.xml", "2.xml", "3.xml", "5.xml", "6.xml", "9.xml", "19.xml", "3303.xml"}; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/FwLwM2MDevice.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/FwLwM2MDevice.java index 2b9df30df9..81159e6584 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/FwLwM2MDevice.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/FwLwM2MDevice.java @@ -131,10 +131,10 @@ public class FwLwM2MDevice extends BaseInstanceEnabler implements Destroyable { scheduler.schedule(() -> { try { state.set(1); - fireResourcesChange(3); + fireResourceChange(3); Thread.sleep(100); state.set(2); - fireResourcesChange(3); + fireResourceChange(3); } catch (Exception e) { } }, 100, TimeUnit.MILLISECONDS); @@ -144,10 +144,10 @@ public class FwLwM2MDevice extends BaseInstanceEnabler implements Destroyable { scheduler.schedule(() -> { try { state.set(3); - fireResourcesChange(3); + fireResourceChange(3); Thread.sleep(100); updateResult.set(1); - fireResourcesChange(5); + fireResourceChange(5); } catch (Exception e) { } }, 100, TimeUnit.MILLISECONDS); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index 41248efd56..9180617846 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -17,10 +17,7 @@ package org.thingsboard.server.transport.lwm2m.client; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.eclipse.californium.core.network.CoapEndpoint; -import org.eclipse.californium.core.network.config.NetworkConfig; -import org.eclipse.californium.core.observe.ObservationStore; -import org.eclipse.californium.scandium.DTLSConnector; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.leshan.client.californium.LeshanClient; import org.eclipse.leshan.client.californium.LeshanClientBuilder; @@ -32,7 +29,6 @@ import org.eclipse.leshan.client.resource.DummyInstanceEnabler; import org.eclipse.leshan.client.resource.ObjectsInitializer; import org.eclipse.leshan.client.servers.ServerIdentity; import org.eclipse.leshan.core.ResponseCode; -import org.eclipse.leshan.core.californium.EndpointFactory; import org.eclipse.leshan.core.model.InvalidDDFFileException; import org.eclipse.leshan.core.model.LwM2mModel; import org.eclipse.leshan.core.model.ObjectLoader; @@ -44,15 +40,15 @@ import org.eclipse.leshan.core.request.BootstrapRequest; import org.eclipse.leshan.core.request.DeregisterRequest; import org.eclipse.leshan.core.request.RegisterRequest; import org.eclipse.leshan.core.request.UpdateRequest; -import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import org.junit.Assert; +import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import java.io.IOException; -import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ScheduledExecutorService; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; import static org.eclipse.leshan.core.LwM2mId.DEVICE; import static org.eclipse.leshan.core.LwM2mId.FIRMWARE; @@ -61,10 +57,10 @@ import static org.eclipse.leshan.core.LwM2mId.SECURITY; import static org.eclipse.leshan.core.LwM2mId.SERVER; import static org.eclipse.leshan.core.LwM2mId.SOFTWARE_MANAGEMENT; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.TEMPERATURE_SENSOR; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_1; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_12; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.TEMPERATURE_SENSOR; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.resources; @@ -84,7 +80,7 @@ public class LwM2MTestClient { private LwM2MLocationParams locationParams; private LwM2mTemperatureSensor lwM2MTemperatureSensor; - public void init(Security security, NetworkConfig coapConfig, int port, boolean isRpc) throws InvalidDDFFileException, IOException { + public void init(Security security, Configuration coapConfig, int port, boolean isRpc) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", client); List models = new ArrayList<>(); for (String resourceName : resources) { @@ -106,44 +102,19 @@ public class LwM2MTestClient { initializer.setInstancesForObject(LOCATION, new LwM2mLocation(locationParams.getLatitude(), locationParams.getLongitude(), locationParams.getScaleFactor(), executor, OBJECT_INSTANCE_ID_0)); initializer.setInstancesForObject(TEMPERATURE_SENSOR, lwM2MTemperatureSensor = new LwM2mTemperatureSensor(executor, OBJECT_INSTANCE_ID_0), new LwM2mTemperatureSensor(executor, OBJECT_INSTANCE_ID_12)); - DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); - dtlsConfig.setRecommendedCipherSuitesOnly(true); - dtlsConfig.setClientOnly(); + DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(coapConfig); + dtlsConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, true); DefaultRegistrationEngineFactory engineFactory = new DefaultRegistrationEngineFactory(); engineFactory.setReconnectOnUpdate(false); engineFactory.setResumeOnConnect(true); - EndpointFactory endpointFactory = new EndpointFactory() { - - @Override - public CoapEndpoint createUnsecuredEndpoint(InetSocketAddress address, NetworkConfig coapConfig, - ObservationStore store) { - CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); - builder.setInetSocketAddress(address); - builder.setNetworkConfig(coapConfig); - return builder.build(); - } - - @Override - public CoapEndpoint createSecuredEndpoint(DtlsConnectorConfig dtlsConfig, NetworkConfig coapConfig, - ObservationStore store) { - CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); - DtlsConnectorConfig.Builder dtlsConfigBuilder = new DtlsConnectorConfig.Builder(dtlsConfig); - builder.setConnector(new DTLSConnector(dtlsConfigBuilder.build())); - builder.setNetworkConfig(coapConfig); - return builder.build(); - } - }; - - LeshanClientBuilder builder = new LeshanClientBuilder(endpoint); builder.setLocalAddress("0.0.0.0", port); builder.setObjects(initializer.createAll()); builder.setCoapConfig(coapConfig); builder.setDtlsConfig(dtlsConfig); builder.setRegistrationEngineFactory(engineFactory); - builder.setEndpointFactory(endpointFactory); builder.setSharedExecutor(executor); builder.setDecoder(new DefaultLwM2mDecoder(false)); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java index d8a54b59bd..a88c795f9c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java @@ -81,8 +81,11 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements public LwM2mBinaryAppDataContainer(ScheduledExecutorService executorService, Integer id) { try { if (id != null) this.setId(id); - executorService.scheduleWithFixedDelay(() -> - fireResourcesChange(0, 2), 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN + executorService.scheduleWithFixedDelay(() -> { + fireResourceChange(0); + fireResourceChange(2); + } + , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN } catch (Throwable e) { log.error("[{}]Throwable", e.toString()); e.printStackTrace(); @@ -126,23 +129,23 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements } case 1: setPriority((Integer) (value.getValue() instanceof Long ? ((Long) value.getValue()).intValue() : value.getValue())); - fireResourcesChange(resourceId); + fireResourceChange(resourceId); return WriteResponse.success(); case 2: setTimestamp(((Date) value.getValue()).getTime()); - fireResourcesChange(resourceId); + fireResourceChange(resourceId); return WriteResponse.success(); case 3: setDescription((String) value.getValue()); - fireResourcesChange(resourceId); + fireResourceChange(resourceId); return WriteResponse.success(); case 4: setDataFormat((String) value.getValue()); - fireResourcesChange(resourceId); + fireResourceChange(resourceId); return WriteResponse.success(); case 5: setAppID((Integer) value.getValue()); - fireResourcesChange(resourceId); + fireResourceChange(resourceId); return WriteResponse.success(); default: return super.write(identity, replace, resourceId, value); @@ -185,7 +188,7 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements try { if (value instanceof LwM2mMultipleResource) { if (replace || this.data == null) { - this.data = new HashMap<>(); + this.data = new HashMap<>(); } value.getInstances().values().forEach(v -> { this.data.put(v.getId(), (byte[]) v.getValue()); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mLocation.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mLocation.java index 590f35e7e0..d9fef9eab3 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mLocation.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mLocation.java @@ -74,8 +74,10 @@ public class LwM2mLocation extends BaseInstanceEnabler implements Destroyable { } this.scaleFactor = scaleFactor; timestamp = new Date(); - executorService.scheduleWithFixedDelay(() -> - fireResourcesChange(0, 1), 10000, 10000, TimeUnit.MILLISECONDS); + executorService.scheduleWithFixedDelay(() -> { + fireResourceChange(0); + fireResourceChange(1); + }, 10000, 10000, TimeUnit.MILLISECONDS); } catch (Throwable e) { log.error("[{}]Throwable", e.toString()); e.printStackTrace(); @@ -117,13 +119,16 @@ public class LwM2mLocation extends BaseInstanceEnabler implements Destroyable { private void moveLatitude(float delta) { latitude = latitude + delta * scaleFactor; timestamp = new Date(); - fireResourcesChange(0, 5); + fireResourceChange(0); + fireResourceChange(5); } private void moveLongitude(float delta) { longitude = longitude + delta * scaleFactor; timestamp = new Date(); - fireResourcesChange(1, 5); + fireResourceChange(1); + fireResourceChange(5); + } public float getLatitude() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mTemperatureSensor.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mTemperatureSensor.java index 53060096f7..919d69d919 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mTemperatureSensor.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mTemperatureSensor.java @@ -93,10 +93,9 @@ public class LwM2mTemperatureSensor extends BaseInstanceEnabler implements Destr float delta = (RANDOM.nextInt(20) - 10) / 10f; currentTemp += delta; Integer changedResource = adjustMinMaxMeasuredValue(currentTemp); + fireResourceChange(5700); if (changedResource != null) { - fireResourcesChange(5700, changedResource); - } else { - fireResourcesChange(5700); + fireResourceChange(changedResource); } } @@ -127,5 +126,4 @@ public class LwM2mTemperatureSensor extends BaseInstanceEnabler implements Destr } - } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java index c14a473d63..37d93279bf 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.lwm2m.client; import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.client.resource.BaseInstanceEnabler; import org.eclipse.leshan.client.servers.ServerIdentity; +import org.eclipse.leshan.core.Destroyable; import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.node.LwM2mResource; @@ -25,7 +26,6 @@ import org.eclipse.leshan.core.response.ExecuteResponse; import org.eclipse.leshan.core.response.ReadResponse; import org.eclipse.leshan.core.response.WriteResponse; -import javax.security.auth.Destroyable; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; @@ -103,11 +103,11 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl return WriteResponse.notFound(); case 14: setUtcOffset((String) value.getValue()); - fireResourcesChange(resourceId); + fireResourceChange(resourceId); return WriteResponse.success(); case 15: setTimezone((String) value.getValue()); - fireResourcesChange(resourceId); + fireResourceChange(resourceId); return WriteResponse.success(); default: return super.write(identity, replace, resourceId, value); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SwLwM2MDevice.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SwLwM2MDevice.java index 0d3400c959..b623f4fa19 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SwLwM2MDevice.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SwLwM2MDevice.java @@ -128,16 +128,17 @@ public class SwLwM2MDevice extends BaseInstanceEnabler implements Destroyable { try { state.set(1); updateResult.set(1); - fireResourcesChange(7, 9); + fireResourceChange(7); + fireResourceChange(9); Thread.sleep(100); state.set(2); - fireResourcesChange(7); + fireResourceChange(7); Thread.sleep(100); state.set(3); - fireResourcesChange(7); + fireResourceChange(7); Thread.sleep(100); updateResult.set(3); - fireResourcesChange(9); + fireResourceChange(9); } catch (Exception e) { } @@ -148,7 +149,8 @@ public class SwLwM2MDevice extends BaseInstanceEnabler implements Destroyable { scheduler.schedule(() -> { state.set(4); updateResult.set(2); - fireResourcesChange(7, 9); + fireResourceChange(7); + fireResourceChange(9); }, 100, TimeUnit.MILLISECONDS); } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index f3cb4e5770..3095f28f28 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -201,9 +201,9 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { @Test public void testSoftwareUpdateByObject9() throws Exception { createDeviceProfile(OTA_TRANSPORT_CONFIGURATION); - NoSecClientCredential credentials = createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9); + NoSecClientCredential credentials = createNoSecClientCredentials(CLIENT_ENDPOINT_OTA9); final Device device = createDevice(credentials); - createNewClient(SECURITY, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9); + createNewClient(SECURITY, COAP_CONFIG, false, CLIENT_ENDPOINT_OTA9); Thread.sleep(1000); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java index 9cea6a8380..a4870b3486 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java @@ -52,8 +52,8 @@ public class RpcLwm2mIntegrationDiscoverTest extends AbstractRpcLwM2MIntegration Set actualObjects = ConcurrentHashMap.newKeySet(); Set actualInstances = ConcurrentHashMap.newKeySet(); rpcActualValue.forEach(node -> { - if (!node.get("url").asText().equals("/")) { - LwM2mPath path = new LwM2mPath(node.get("url").asText()); + if (!node.get("uriReference").asText().equals("/")) { + LwM2mPath path = new LwM2mPath(node.get("uriReference").asText()); actualObjects.add("/" + path.getObjectId()); if (path.isObjectInstance()) { actualInstances.add("/" + path.getObjectId() + "/" + path.getObjectInstanceId()); diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/CoapServerService.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/CoapServerService.java index 1f312da533..8dbbc5a620 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/CoapServerService.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/CoapServerService.java @@ -17,6 +17,7 @@ package org.thingsboard.server.coapserver; import org.eclipse.californium.core.CoapServer; +import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.concurrent.ConcurrentMap; @@ -24,7 +25,7 @@ public interface CoapServerService { CoapServer getCoapServer() throws UnknownHostException; - ConcurrentMap getDtlsSessionsMap(); + ConcurrentMap getDtlsSessionsMap(); long getTimeout(); diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java index 25dfade5a3..3aa0d0c122 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java @@ -18,8 +18,9 @@ package org.thingsboard.server.coapserver; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.CoapServer; import org.eclipse.californium.core.network.CoapEndpoint; -import org.eclipse.californium.core.network.config.NetworkConfig; +import org.eclipse.californium.core.config.CoapConfig; import org.eclipse.californium.core.server.resources.Resource; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +38,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import static org.eclipse.californium.core.network.config.NetworkConfigDefaults.DEFAULT_BLOCKWISE_STATUS_LIFETIME; +import static org.eclipse.californium.core.config.CoapConfig.DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS; @Slf4j @Component @@ -78,8 +79,8 @@ public class DefaultCoapServerService implements CoapServerService { } @Override - public ConcurrentMap getDtlsSessionsMap() { - return tbDtlsCertificateVerifier != null ? tbDtlsCertificateVerifier.getTbCoapDtlsSessionIdsMap() : null; + public ConcurrentMap getDtlsSessionsMap() { + return tbDtlsCertificateVerifier != null ? tbDtlsCertificateVerifier.getTbCoapDtlsSessionsMap() : null; } @Override @@ -88,16 +89,16 @@ public class DefaultCoapServerService implements CoapServerService { } private CoapServer createCoapServer() throws UnknownHostException { - NetworkConfig networkConfig = new NetworkConfig(); - networkConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_STRICT_BLOCK2_OPTION, true); - networkConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true); - networkConfig.setLong(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, DEFAULT_BLOCKWISE_STATUS_LIFETIME); - networkConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 256 * 1024 * 1024); - networkConfig.setString(NetworkConfig.Keys.RESPONSE_MATCHING, "RELAXED"); - networkConfig.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE, 1024); - networkConfig.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE, 1024); - networkConfig.setInt(NetworkConfig.Keys.MAX_RETRANSMIT, 4); - networkConfig.setInt(NetworkConfig.Keys.COAP_PORT, coapServerContext.getPort()); + Configuration networkConfig = new Configuration(); + networkConfig.set(CoapConfig.BLOCKWISE_STRICT_BLOCK2_OPTION, true); + networkConfig.set(CoapConfig.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true); + networkConfig.set(CoapConfig.BLOCKWISE_STATUS_LIFETIME, DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS, TimeUnit.SECONDS); + networkConfig.set(CoapConfig.MAX_RESOURCE_BODY_SIZE, 256 * 1024 * 1024); + networkConfig.set(CoapConfig.RESPONSE_MATCHING, CoapConfig.MatcherMode.RELAXED); + networkConfig.set(CoapConfig.PREFERRED_BLOCK_SIZE, 1024); + networkConfig.set(CoapConfig.MAX_MESSAGE_SIZE, 1024); + networkConfig.set(CoapConfig.MAX_RETRANSMIT, 4); + networkConfig.set(CoapConfig.COAP_PORT, coapServerContext.getPort()); server = new CoapServer(networkConfig); CoapEndpoint.Builder noSecCoapEndpointBuilder = new CoapEndpoint.Builder(); @@ -105,15 +106,15 @@ public class DefaultCoapServerService implements CoapServerService { InetSocketAddress sockAddr = new InetSocketAddress(addr, coapServerContext.getPort()); noSecCoapEndpointBuilder.setInetSocketAddress(sockAddr); - noSecCoapEndpointBuilder.setNetworkConfig(networkConfig); + noSecCoapEndpointBuilder.setConfiguration(networkConfig); CoapEndpoint noSecCoapEndpoint = noSecCoapEndpointBuilder.build(); server.addEndpoint(noSecCoapEndpoint); if (isDtlsEnabled()) { CoapEndpoint.Builder dtlsCoapEndpointBuilder = new CoapEndpoint.Builder(); TbCoapDtlsSettings dtlsSettings = coapServerContext.getDtlsSettings(); - DtlsConnectorConfig dtlsConnectorConfig = dtlsSettings.dtlsConnectorConfig(); - networkConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT, dtlsConnectorConfig.getAddress().getPort()); - dtlsCoapEndpointBuilder.setNetworkConfig(networkConfig); + DtlsConnectorConfig dtlsConnectorConfig = dtlsSettings.dtlsConnectorConfig(networkConfig); + networkConfig.set(CoapConfig.COAP_SECURE_PORT, dtlsConnectorConfig.getAddress().getPort()); + dtlsCoapEndpointBuilder.setConfiguration(networkConfig); DTLSConnector connector = new DTLSConnector(dtlsConnectorConfig); dtlsCoapEndpointBuilder.setConnector(connector); CoapEndpoint dtlsCoapEndpoint = dtlsCoapEndpointBuilder.build(); diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java index 1954ae900e..ce8b093b4d 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsCertificateVerifier.java @@ -23,7 +23,6 @@ import org.eclipse.californium.scandium.dtls.CertificateMessage; import org.eclipse.californium.scandium.dtls.CertificateType; import org.eclipse.californium.scandium.dtls.CertificateVerificationResult; import org.eclipse.californium.scandium.dtls.ConnectionId; -import org.eclipse.californium.scandium.dtls.DTLSSession; import org.eclipse.californium.scandium.dtls.HandshakeException; import org.eclipse.californium.scandium.dtls.HandshakeResultHandler; import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier; @@ -34,13 +33,13 @@ import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.msg.EncryptionUtil; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.common.transport.util.SslUtil; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import javax.security.auth.x500.X500Principal; +import java.net.InetSocketAddress; import java.security.cert.CertPath; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateExpiredException; @@ -48,7 +47,6 @@ import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.List; -import java.util.UUID; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -71,12 +69,12 @@ public class TbCoapDtlsCertificateVerifier implements NewAdvancedCertificateVeri } @Override - public List getSupportedCertificateType() { + public List getSupportedCertificateTypes() { return Collections.singletonList(CertificateType.X_509); } @Override - public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, Boolean clientUsage, boolean truncateCertificatePath, CertificateMessage message, DTLSSession session) { + public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, InetSocketAddress remotePeer, boolean clientUsage, boolean verifySubject, boolean truncateCertificatePath, CertificateMessage message) { try { CertPath certpath = message.getCertificateChain(); X509Certificate[] chain = certpath.getCertificates().toArray(new X509Certificate[0]); @@ -111,7 +109,7 @@ public class TbCoapDtlsCertificateVerifier implements NewAdvancedCertificateVeri if (msg != null && strCert.equals(msg.getCredentials())) { DeviceProfile deviceProfile = msg.getDeviceProfile(); if (msg.hasDeviceInfo() && deviceProfile != null) { - tbCoapDtlsSessionInMemoryStorage.put(session.getSessionIdentifier().toString(), new TbCoapDtlsSessionInfo(msg, deviceProfile)); + tbCoapDtlsSessionInMemoryStorage.put(remotePeer, new TbCoapDtlsSessionInfo(msg, deviceProfile)); } break; } @@ -120,8 +118,7 @@ public class TbCoapDtlsCertificateVerifier implements NewAdvancedCertificateVeri CertificateExpiredException | CertificateNotYetValidException e) { log.error(e.getMessage(), e); - AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.BAD_CERTIFICATE, - session.getPeer()); + AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.BAD_CERTIFICATE); throw new HandshakeException("Certificate chain could not be validated", alert); } } @@ -141,8 +138,8 @@ public class TbCoapDtlsCertificateVerifier implements NewAdvancedCertificateVeri public void setResultHandler(HandshakeResultHandler resultHandler) { } - public ConcurrentMap getTbCoapDtlsSessionIdsMap() { - return tbCoapDtlsSessionInMemoryStorage.getDtlsSessionIdMap(); + public ConcurrentMap getTbCoapDtlsSessionsMap() { + return tbCoapDtlsSessionInMemoryStorage.getDtlsSessionsMap(); } public void evictTimeoutSessions() { diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSessionInMemoryStorage.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSessionInMemoryStorage.java index 085bd035ca..8584246f0d 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSessionInMemoryStorage.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSessionInMemoryStorage.java @@ -18,6 +18,7 @@ package org.thingsboard.server.coapserver; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import java.net.InetSocketAddress; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -25,7 +26,7 @@ import java.util.concurrent.ConcurrentMap; @Data public class TbCoapDtlsSessionInMemoryStorage { - private final ConcurrentMap dtlsSessionIdMap = new ConcurrentHashMap<>(); + private final ConcurrentMap dtlsSessionsMap = new ConcurrentHashMap<>(); private long dtlsSessionInactivityTimeout; private long dtlsSessionReportTimeout; @@ -35,14 +36,14 @@ public class TbCoapDtlsSessionInMemoryStorage { this.dtlsSessionReportTimeout = dtlsSessionReportTimeout; } - public void put(String dtlsSessionId, TbCoapDtlsSessionInfo dtlsSessionInfo) { - log.trace("DTLS session added to in-memory store: [{}] timestamp: [{}]", dtlsSessionId, dtlsSessionInfo.getLastActivityTime()); - dtlsSessionIdMap.putIfAbsent(dtlsSessionId, dtlsSessionInfo); + public void put(InetSocketAddress remotePeer, TbCoapDtlsSessionInfo dtlsSessionInfo) { + log.trace("DTLS session added to in-memory store: [{}] timestamp: [{}]", remotePeer, dtlsSessionInfo.getLastActivityTime()); + dtlsSessionsMap.putIfAbsent(remotePeer, dtlsSessionInfo); } public void evictTimeoutSessions() { long expTime = System.currentTimeMillis() - dtlsSessionInactivityTimeout; - dtlsSessionIdMap.entrySet().removeIf(entry -> { + dtlsSessionsMap.entrySet().removeIf(entry -> { if (entry.getValue().getLastActivityTime() < expTime) { log.trace("DTLS session was removed from in-memory store: [{}]", entry.getKey()); return true; diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java index ff778b57ab..7d5c17bf6d 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java @@ -16,9 +16,13 @@ package org.thingsboard.server.coapserver; import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.elements.config.CertificateAuthenticationMode; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.californium.elements.util.SslContextUtil; +import org.eclipse.californium.scandium.config.DtlsConfig; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.californium.scandium.dtls.CertificateType; +import org.eclipse.californium.scandium.dtls.x509.SingleCertificateProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; @@ -26,17 +30,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.ResourceUtils; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.config.ssl.SslCredentials; import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; -import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; -import java.security.GeneralSecurityException; import java.util.Collections; @Slf4j @@ -75,15 +76,14 @@ public class TbCoapDtlsSettings { @Autowired private TbServiceInfoProvider serviceInfoProvider; - public DtlsConnectorConfig dtlsConnectorConfig() throws UnknownHostException { - DtlsConnectorConfig.Builder configBuilder = new DtlsConnectorConfig.Builder(); + public DtlsConnectorConfig dtlsConnectorConfig(Configuration configuration) throws UnknownHostException { + DtlsConnectorConfig.Builder configBuilder = new DtlsConnectorConfig.Builder(configuration); configBuilder.setAddress(getInetSocketAddress()); SslCredentials sslCredentials = this.coapDtlsCredentialsConfig.getCredentials(); SslContextUtil.Credentials serverCredentials = new SslContextUtil.Credentials(sslCredentials.getPrivateKey(), null, sslCredentials.getCertificateChain()); - configBuilder.setServerOnly(true); - configBuilder.setClientAuthenticationRequired(false); - configBuilder.setClientAuthenticationWanted(true); + configBuilder.set(DtlsConfig.DTLS_ROLE, DtlsConfig.DtlsRole.SERVER_ONLY); + configBuilder.set(DtlsConfig.DTLS_CLIENT_AUTHENTICATION_MODE, CertificateAuthenticationMode.WANTED); configBuilder.setAdvancedCertificateVerifier( new TbCoapDtlsCertificateVerifier( transportService, @@ -93,8 +93,8 @@ public class TbCoapDtlsSettings { skipValidityCheckForClientCert ) ); - configBuilder.setIdentity(serverCredentials.getPrivateKey(), serverCredentials.getCertificateChain(), - Collections.singletonList(CertificateType.X_509)); + configBuilder.setCertificateIdentityProvider(new SingleCertificateProvider(serverCredentials.getPrivateKey(), serverCredentials.getCertificateChain(), + Collections.singletonList(CertificateType.X_509))); return configBuilder.build(); } diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapServerMessageDeliverer.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapServerMessageDeliverer.java index b52d08fdd9..1d8e4d45f9 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapServerMessageDeliverer.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapServerMessageDeliverer.java @@ -18,6 +18,7 @@ package org.thingsboard.server.coapserver; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.coap.OptionSet; import org.eclipse.californium.core.network.Exchange; +import org.eclipse.californium.core.server.DelivererException; import org.eclipse.californium.core.server.ServerMessageDeliverer; import org.eclipse.californium.core.server.resources.Resource; import org.springframework.util.CollectionUtils; @@ -32,7 +33,7 @@ public class TbCoapServerMessageDeliverer extends ServerMessageDeliverer { } @Override - protected Resource findResource(Exchange exchange) { + protected Resource findResource(Exchange exchange) throws DelivererException { validateUriPath(exchange); return findResource(exchange.getRequest().getOptions().getUriPath()); } diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java index 0c3ce2a530..3e291a8177 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java @@ -30,7 +30,6 @@ import org.thingsboard.server.coapserver.TbCoapDtlsSessionInfo; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceTransportType; -import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.TransportPayloadType; import org.thingsboard.server.common.data.security.DeviceTokenCredentials; import org.thingsboard.server.common.msg.session.FeatureType; @@ -48,6 +47,7 @@ import org.thingsboard.server.transport.coap.callback.ToServerRpcSyncSessionCall import org.thingsboard.server.transport.coap.client.CoapClientContext; import org.thingsboard.server.transport.coap.client.TbCoapClientState; +import java.net.InetSocketAddress; import java.util.List; import java.util.Optional; import java.util.Random; @@ -56,6 +56,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import static org.eclipse.californium.elements.DtlsEndpointContext.KEY_SESSION_ID; + @Slf4j public class CoapTransportResource extends AbstractCoapTransportResource { private static final int ACCESS_TOKEN_POSITION = 3; @@ -64,9 +66,8 @@ public class CoapTransportResource extends AbstractCoapTransportResource { private static final int FEATURE_TYPE_POSITION_CERTIFICATE_REQUEST = 3; private static final int REQUEST_ID_POSITION_CERTIFICATE_REQUEST = 4; - private static final String DTLS_SESSION_ID_KEY = "DTLS_SESSION_ID"; - private final ConcurrentMap dtlsSessionIdMap; + private final ConcurrentMap dtlsSessionsMap; private final long timeout; private final CoapClientContext clients; @@ -74,7 +75,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { super(ctx, name); this.setObservable(true); // enable observing this.addObserver(new CoapResourceObserver()); - this.dtlsSessionIdMap = coapServerService.getDtlsSessionsMap(); + this.dtlsSessionsMap = coapServerService.getDtlsSessionsMap(); this.timeout = coapServerService.getTimeout(); this.clients = ctx.getClientContext(); long sessionReportTimeout = ctx.getSessionReportTimeout(); @@ -91,7 +92,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { if (relation == null || relation.isCanceled()) { return; // because request did not try to establish a relation } - if (CoAP.ResponseCode.isSuccess(response.getCode())) { + if (response.getCode().isSuccess()) { if (!relation.isEstablished()) { relation.setEstablished(); addObserveRelation(relation); @@ -198,10 +199,10 @@ public class CoapTransportResource extends AbstractCoapTransportResource { Exchange advanced = exchange.advanced(); Request request = advanced.getRequest(); - String dtlsSessionIdStr = request.getSourceContext().get(DTLS_SESSION_ID_KEY); - if (dtlsSessionIdMap != null && StringUtils.isNotEmpty(dtlsSessionIdStr)) { - TbCoapDtlsSessionInfo tbCoapDtlsSessionInfo = dtlsSessionIdMap - .computeIfPresent(dtlsSessionIdStr, (dtlsSessionId, dtlsSessionInfo) -> { + var dtlsSessionId = request.getSourceContext().get(KEY_SESSION_ID); + if (dtlsSessionsMap != null && dtlsSessionId != null && !dtlsSessionId.isEmpty()) { + TbCoapDtlsSessionInfo tbCoapDtlsSessionInfo = dtlsSessionsMap + .computeIfPresent(request.getSourceContext().getPeerAddress(), (dtlsSessionIdStr, dtlsSessionInfo) -> { dtlsSessionInfo.setLastActivityTime(System.currentTimeMillis()); return dtlsSessionInfo; }); diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/TbCoapMessageObserver.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/TbCoapMessageObserver.java index f5ff256fef..0e45c52f62 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/TbCoapMessageObserver.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/TbCoapMessageObserver.java @@ -29,6 +29,11 @@ public class TbCoapMessageObserver implements MessageObserver { private final Consumer onAcknowledge; private final Consumer onTimeout; + @Override + public boolean isInternal() { + return false; + } + @Override public void onRetransmission() { @@ -86,13 +91,18 @@ public class TbCoapMessageObserver implements MessageObserver { } + @Override + public void onResponseHandlingError(Throwable cause) { + + } + @Override public void onContextEstablished(EndpointContext endpointContext) { } @Override - public void onComplete() { + public void onTransferComplete() { } } diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/SecureClientNoAuth.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/SecureClientNoAuth.java index f23ae9deb4..fc0ab5a26c 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/SecureClientNoAuth.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/SecureClientNoAuth.java @@ -21,11 +21,13 @@ import org.eclipse.californium.core.Utils; import org.eclipse.californium.core.network.CoapEndpoint; import org.eclipse.californium.elements.DtlsEndpointContext; import org.eclipse.californium.elements.EndpointContext; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.californium.elements.exception.ConnectorException; import org.eclipse.californium.elements.util.SslContextUtil; import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.californium.scandium.dtls.CertificateType; +import org.eclipse.californium.scandium.dtls.x509.SingleCertificateProvider; import org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier; import org.thingsboard.common.util.ThingsBoardThreadFactory; @@ -118,7 +120,7 @@ public class SecureClientNoAuth { String keyStorePassword = args[6]; - DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(); + DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(new Configuration()); setupCredentials(builder, keyStoreUriPath, keyStoreAlias, trustedAliasPattern, keyStorePassword); DTLSConnector dtlsConnector = new DTLSConnector(builder.build()); SecureClientNoAuth client = new SecureClientNoAuth(dtlsConnector, host, port, accessToken, clientKeys, sharedKeys); @@ -134,7 +136,7 @@ public class SecureClientNoAuth { keyStoreUriPath, trustedAliasPattern, keyStorePassword.toCharArray()); trustBuilder.setTrustedCertificates(trustedCertificates); config.setAdvancedCertificateVerifier(trustBuilder.build()); - config.setIdentity(serverCredentials.getPrivateKey(), serverCredentials.getCertificateChain(), Collections.singletonList(CertificateType.X_509)); + config.setCertificateIdentityProvider(new SingleCertificateProvider(serverCredentials.getPrivateKey(), serverCredentials.getCertificateChain(), Collections.singletonList(CertificateType.X_509))); } catch (GeneralSecurityException e) { System.err.println("certificates are invalid!"); throw new IllegalArgumentException(e.getMessage()); diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/SecureClientX509.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/SecureClientX509.java index e67055f4e5..700dee7ed9 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/SecureClientX509.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/SecureClientX509.java @@ -21,11 +21,13 @@ import org.eclipse.californium.core.Utils; import org.eclipse.californium.core.network.CoapEndpoint; import org.eclipse.californium.elements.DtlsEndpointContext; import org.eclipse.californium.elements.EndpointContext; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.californium.elements.exception.ConnectorException; import org.eclipse.californium.elements.util.SslContextUtil; import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.californium.scandium.dtls.CertificateType; +import org.eclipse.californium.scandium.dtls.x509.SingleCertificateProvider; import org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier; import org.thingsboard.common.util.ThingsBoardThreadFactory; @@ -117,7 +119,7 @@ public class SecureClientX509 { String keyStorePassword = args[5]; - DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(); + DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(new Configuration()); setupCredentials(builder, keyStoreUriPath, keyStoreAlias, trustedAliasPattern, keyStorePassword); DTLSConnector dtlsConnector = new DTLSConnector(builder.build()); SecureClientX509 client = new SecureClientX509(dtlsConnector, host, port, clientKeys, sharedKeys); @@ -133,7 +135,7 @@ public class SecureClientX509 { keyStoreUriPath, trustedAliasPattern, keyStorePassword.toCharArray()); trustBuilder.setTrustedCertificates(trustedCertificates); config.setAdvancedCertificateVerifier(trustBuilder.build()); - config.setIdentity(serverCredentials.getPrivateKey(), serverCredentials.getCertificateChain(), Collections.singletonList(CertificateType.X_509)); + config.setCertificateIdentityProvider(new SingleCertificateProvider(serverCredentials.getPrivateKey(), serverCredentials.getCertificateChain(), Collections.singletonList(CertificateType.X_509))); } catch (GeneralSecurityException e) { System.err.println("certificates are invalid!"); throw new IllegalArgumentException(e.getMessage()); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index b7af551e30..23f9b26a20 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.bootstrap; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.scandium.config.DtlsConfig; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.leshan.server.bootstrap.BootstrapSessionManager; import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer; @@ -37,6 +38,8 @@ import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.security.cert.X509Certificate; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CURVES_ONLY; import static org.thingsboard.server.transport.lwm2m.server.DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES; import static org.thingsboard.server.transport.lwm2m.server.LwM2MNetworkConfig.getCoapConfig; @@ -80,12 +83,11 @@ public class LwM2MTransportBootstrapService { /* Create and Set DTLS Config */ - DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); - dtlsConfig.setRecommendedSupportedGroupsOnly(serverConfig.isRecommendedSupportedGroups()); - dtlsConfig.setRecommendedCipherSuitesOnly(serverConfig.isRecommendedCiphers()); - dtlsConfig.setSupportedCipherSuites(this.pskMode ? DefaultLwM2mTransportService.PSK_CIPHER_SUITES : DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES); - /* Create credentials */ - this.setServerWithCredentials(builder, dtlsConfig); + DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(getCoapConfig(bootstrapConfig.getPort(), bootstrapConfig.getSecurePort(), serverConfig)); + dtlsConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, serverConfig.isRecommendedSupportedGroups()); + dtlsConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, serverConfig.isRecommendedCiphers()); + dtlsConfig.setAsList(DtlsConfig.DTLS_CIPHER_SUITES, this.pskMode ? DefaultLwM2mTransportService.PSK_CIPHER_SUITES : DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES); + setServerWithCredentials(builder, dtlsConfig); /* Set DTLS Config */ builder.setDtlsConfig(dtlsConfig); @@ -110,7 +112,7 @@ public class LwM2MTransportBootstrapService { builder.setPublicKey(sslCredentials.getPublicKey()); builder.setPrivateKey(sslCredentials.getPrivateKey()); builder.setCertificateChain(sslCredentials.getCertificateChain()); - dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES); + dtlsConfig.setAsList(DtlsConfig.DTLS_CIPHER_SUITES, this.pskMode ? DefaultLwM2mTransportService.PSK_CIPHER_SUITES : DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES); dtlsConfig.setAdvancedCertificateVerifier(certificateVerifier); } else { /* by default trust all */ diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/TbLwM2MDtlsBootstrapCertificateVerifier.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/TbLwM2MDtlsBootstrapCertificateVerifier.java index eff4cc3871..ca621f2618 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/TbLwM2MDtlsBootstrapCertificateVerifier.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/TbLwM2MDtlsBootstrapCertificateVerifier.java @@ -17,19 +17,18 @@ package org.thingsboard.server.transport.lwm2m.bootstrap.secure; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.elements.auth.RawPublicKeyIdentity; import org.eclipse.californium.elements.util.CertPathUtil; import org.eclipse.californium.scandium.dtls.AlertMessage; import org.eclipse.californium.scandium.dtls.CertificateMessage; import org.eclipse.californium.scandium.dtls.CertificateType; import org.eclipse.californium.scandium.dtls.CertificateVerificationResult; import org.eclipse.californium.scandium.dtls.ConnectionId; -import org.eclipse.californium.scandium.dtls.DTLSSession; import org.eclipse.californium.scandium.dtls.HandshakeException; import org.eclipse.californium.scandium.dtls.HandshakeResultHandler; import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier; -import org.eclipse.californium.scandium.dtls.x509.StaticCertificateVerifier; +import org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier; import org.eclipse.californium.scandium.util.ServerNames; -import org.eclipse.leshan.server.security.SecurityChecker; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; @@ -39,14 +38,12 @@ import org.thingsboard.server.common.transport.util.SslUtil; import org.thingsboard.server.queue.util.TbLwM2mBootstrapTransportComponent; import org.thingsboard.server.transport.lwm2m.bootstrap.store.LwM2MBootstrapSecurityStore; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; -import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo; import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException; -import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; -import org.thingsboard.server.transport.lwm2m.server.store.TbMainSecurityStore; import javax.annotation.PostConstruct; import javax.security.auth.x500.X500Principal; +import java.net.InetSocketAddress; import java.security.PublicKey; import java.security.cert.CertPath; import java.security.cert.CertificateEncodingException; @@ -65,14 +62,13 @@ public class TbLwM2MDtlsBootstrapCertificateVerifier implements NewAdvancedCerti private final LwM2MTransportServerConfig config; private final LwM2MBootstrapSecurityStore bsSecurityStore; - @SuppressWarnings("deprecation") - private StaticCertificateVerifier staticCertificateVerifier; + private StaticNewAdvancedCertificateVerifier staticCertificateVerifier; @Value("${transport.lwm2m.server.security.skip_validity_check_for_client_cert:false}") private boolean skipValidityCheckForClientCert; @Override - public List getSupportedCertificateType() { + public List getSupportedCertificateTypes() { return Arrays.asList(CertificateType.X_509, CertificateType.RAW_PUBLIC_KEY); } @@ -83,17 +79,17 @@ public class TbLwM2MDtlsBootstrapCertificateVerifier implements NewAdvancedCerti /* by default trust all */ if (config.getTrustSslCredentials() != null) { X509Certificate[] trustedCertificates = config.getTrustSslCredentials().getTrustedCertificates(); - staticCertificateVerifier = new StaticCertificateVerifier(trustedCertificates); + staticCertificateVerifier = new StaticNewAdvancedCertificateVerifier(trustedCertificates, new RawPublicKeyIdentity[0], null); } } catch (Exception e) { - log.info("Failed to initialize the certificate verifier", e); + log.warn("ailed to initialize the LwM2M certificate verifier", e); } } @Override - public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, Boolean clientUsage, - boolean truncateCertificatePath, CertificateMessage message, - DTLSSession session) { + public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, InetSocketAddress remotePeer, + boolean clientUsage, boolean verifySubject, boolean truncateCertificatePath, + CertificateMessage message) { CertPath certChain = message.getCertificateChain(); if (certChain == null) { //We trust all RPK on this layer, and use TbLwM2MAuthorizer @@ -111,14 +107,14 @@ public class TbLwM2MDtlsBootstrapCertificateVerifier implements NewAdvancedCerti TbLwM2MSecurityInfo securityInfo = null; // verify if trust if (staticCertificateVerifier != null) { - try { - staticCertificateVerifier.verifyCertificate(message, session); + HandshakeException exception = staticCertificateVerifier.verifyCertificate(cid, serverName, remotePeer, clientUsage, verifySubject, truncateCertificatePath, message).getException(); + if (exception == null) { String endpoint = config.getTrustSslCredentials().getValueFromSubjectNameByKey(cert.getSubjectX500Principal().getName(), "CN"); if (StringUtils.isNotEmpty(endpoint)) { securityInfo = bsSecurityStore.getX509ByEndpoint(endpoint); } - } catch (HandshakeException e) { - log.trace("Certificate validation failed.", e); + } else { + log.trace("Certificate validation failed.", exception); } } // if not trust or cert trust securityInfo == null @@ -143,8 +139,7 @@ public class TbLwM2MDtlsBootstrapCertificateVerifier implements NewAdvancedCerti } } if (!x509CredentialsFound) { - AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.INTERNAL_ERROR, - session.getPeer()); + AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.INTERNAL_ERROR); throw new HandshakeException("x509 verification not enabled!", alert); } return new CertificateVerificationResult(cid, certChain, null); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java index f315fbe48d..0582ff5450 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java @@ -16,7 +16,7 @@ package org.thingsboard.server.transport.lwm2m.bootstrap.store; import lombok.extern.slf4j.Slf4j; -import org.eclipse.leshan.core.Link; +import org.eclipse.leshan.core.link.Link; import org.eclipse.leshan.core.node.LwM2mObject; import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.request.BootstrapDeleteRequest; @@ -134,18 +134,18 @@ public class LwM2MBootstrapConfigStoreTaskProvider implements BootstrapTaskProvi log.info("Object after discover: [{}]", objectLinks); this.securityInstances = new HashMap<>(); for (Link link : objectLinks) { - if (link.getUrl().startsWith("/0/")) { + if (link.getUriReference().startsWith("/0/")) { try { - LwM2mPath path = new LwM2mPath(link.getUrl()); + LwM2mPath path = new LwM2mPath(link.getUriReference()); if (path.isObjectInstance()) { - if (link.getAttributes().containsKey("ssid")) { - int serverId = Integer.parseInt(link.getAttributes().get("ssid")); + if (link.getLinkParams().containsKey("ssid")) { + int serverId = Integer.parseInt(link.getLinkParams().get("ssid").getUnquoted()); if (!this.securityInstances.containsKey(serverId)) { this.securityInstances.put(serverId, path.getObjectInstanceId()); } else { log.error("Invalid lwm2mSecurityInstance by [{}]", path.getObjectInstanceId()); } - this.securityInstances.put(Integer.valueOf(link.getAttributes().get("ssid")), path.getObjectInstanceId()); + this.securityInstances.put(Integer.valueOf(link.getLinkParams().get("ssid").getUnquoted()), path.getObjectInstanceId()); } else { if (!this.securityInstances.containsKey(0)) { this.securityInstances.put(0, path.getObjectInstanceId()); @@ -188,10 +188,10 @@ public class LwM2MBootstrapConfigStoreTaskProvider implements BootstrapTaskProvi private void initAfterBootstrapDiscover(BootstrapDiscoverResponse response) { Link[] links = response.getObjectLinks(); Arrays.stream(links).forEach(link -> { - LwM2mPath path = new LwM2mPath(link.getUrl()); + LwM2mPath path = new LwM2mPath(link.getUriReference()); if (!path.isRoot() && path.getObjectId() < 3) { if (path.isObject()) { - String ver = link.getAttributes().get("ver") != null ? link.getAttributes().get("ver") : "1.0"; + String ver = link.getLinkParams().get("ver") != null ? link.getLinkParams().get("ver").getUnquoted() : "1.0"; this.supportedObjects.put(path.getObjectId(), ver); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapSecurityStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapSecurityStore.java index e20fac8fb9..0cc6cc1b94 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapSecurityStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapSecurityStore.java @@ -80,7 +80,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { TbLwM2MSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfoByCredentialsId(identity, BOOTSTRAP); if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) { /* add value to store from BootstrapJson */ - this.setBootstrapConfigScurityInfo(store); + this.setBootstrapConfigSecurityInfo(store); BootstrapConfig bsConfig = store.getBootstrapConfig(); if (bsConfig.security != null) { try { @@ -99,18 +99,13 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { } public TbLwM2MSecurityInfo getX509ByEndpoint(String endPoint) { - try { TbLwM2MSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfoByCredentialsId(endPoint, BOOTSTRAP); this.addValueToStore(store, store.getEndpoint()); return store; - } catch (LwM2MAuthException e) { - log.trace("Failed find security info: {}", endPoint, e); - } - return null; } - private void setBootstrapConfigScurityInfo(TbLwM2MSecurityInfo store) { + private void setBootstrapConfigSecurityInfo(TbLwM2MSecurityInfo store) { /* BootstrapConfig */ LwM2MBootstrapConfig lwM2MBootstrapConfig = this.getParametersBootstrap(store); if (lwM2MBootstrapConfig != null) { @@ -182,7 +177,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { SecurityInfo securityInfo = null; if (store != null && store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) { securityInfo = store.getSecurityInfo(); - this.setBootstrapConfigScurityInfo(store); + this.setBootstrapConfigSecurityInfo(store); BootstrapConfig bsConfigNew = store.getBootstrapConfig(); if (bsConfigNew != null) { try { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2mVersion.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/TbLwM2mVersion.java similarity index 70% rename from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2mVersion.java rename to common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/TbLwM2mVersion.java index 3c12b8f6be..699f57481f 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2mVersion.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/TbLwM2mVersion.java @@ -16,31 +16,31 @@ package org.thingsboard.server.transport.lwm2m.config; import lombok.Getter; -import org.eclipse.leshan.core.LwM2m.Version; +import org.eclipse.leshan.core.LwM2m.LwM2mVersion; import org.eclipse.leshan.core.request.ContentFormat; -public enum LwM2mVersion { - VERSION_1_0(0, Version.V1_0, ContentFormat.TLV, false), - VERSION_1_1(1, Version.V1_1, ContentFormat.TEXT, true); +public enum TbLwM2mVersion { + VERSION_1_0(0, LwM2mVersion.V1_0, ContentFormat.TLV, false), + VERSION_1_1(1, LwM2mVersion.V1_1, ContentFormat.TEXT, true); @Getter private final int code; @Getter - private final Version version; + private final LwM2mVersion version; @Getter private final ContentFormat contentFormat; @Getter private final boolean composite; - LwM2mVersion(int code, Version version, ContentFormat contentFormat, boolean composite) { + TbLwM2mVersion(int code, LwM2mVersion version, ContentFormat contentFormat, boolean composite) { this.code = code; this.version = version; this.contentFormat = contentFormat; this.composite = composite; } - public static LwM2mVersion fromVersion(Version version) { - for (LwM2mVersion to : LwM2mVersion.values()) { + public static TbLwM2mVersion fromVersion(LwM2mVersion version) { + for (TbLwM2mVersion to : TbLwM2mVersion.values()) { if (to.version.equals(version)) { return to; } @@ -48,8 +48,8 @@ public enum LwM2mVersion { throw new IllegalArgumentException(String.format("Unsupported typeLwM2mVersion type : %s", version)); } - public static LwM2mVersion fromVersionStr(String versionStr) { - for (LwM2mVersion to : LwM2mVersion.values()) { + public static TbLwM2mVersion fromVersionStr(String versionStr) { + for (TbLwM2mVersion to : TbLwM2mVersion.values()) { if (to.version.toString().equals(versionStr)) { return to; } @@ -57,8 +57,8 @@ public enum LwM2mVersion { throw new IllegalArgumentException(String.format("Unsupported contentFormatLwM2mVersion version : %s", versionStr)); } - public static LwM2mVersion fromCode(int code) { - for (LwM2mVersion to : LwM2mVersion.values()) { + public static TbLwM2mVersion fromCode(int code) { + for (TbLwM2mVersion to : TbLwM2mVersion.values()) { if (to.code == code) { return to; } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java index 93ba7934dc..917ff4821a 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java @@ -17,17 +17,17 @@ package org.thingsboard.server.transport.lwm2m.secure; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.elements.auth.RawPublicKeyIdentity; import org.eclipse.californium.elements.util.CertPathUtil; import org.eclipse.californium.scandium.dtls.AlertMessage; import org.eclipse.californium.scandium.dtls.CertificateMessage; import org.eclipse.californium.scandium.dtls.CertificateType; import org.eclipse.californium.scandium.dtls.CertificateVerificationResult; import org.eclipse.californium.scandium.dtls.ConnectionId; -import org.eclipse.californium.scandium.dtls.DTLSSession; import org.eclipse.californium.scandium.dtls.HandshakeException; import org.eclipse.californium.scandium.dtls.HandshakeResultHandler; import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier; -import org.eclipse.californium.scandium.dtls.x509.StaticCertificateVerifier; +import org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier; import org.eclipse.californium.scandium.util.ServerNames; import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; import org.springframework.beans.factory.annotation.Value; @@ -49,6 +49,7 @@ import org.thingsboard.server.transport.lwm2m.server.store.TbMainSecurityStore; import javax.annotation.PostConstruct; import javax.security.auth.x500.X500Principal; +import java.net.InetSocketAddress; import java.security.PublicKey; import java.security.cert.CertPath; import java.security.cert.CertificateEncodingException; @@ -71,34 +72,33 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer private final LwM2mCredentialsSecurityInfoValidator securityInfoValidator; private final TbMainSecurityStore securityStore; - @SuppressWarnings("deprecation") - private StaticCertificateVerifier staticCertificateVerifier; + private StaticNewAdvancedCertificateVerifier staticCertificateVerifier; @Value("${transport.lwm2m.server.security.skip_validity_check_for_client_cert:false}") private boolean skipValidityCheckForClientCert; @Override - public List getSupportedCertificateType() { + public List getSupportedCertificateTypes() { return Arrays.asList(CertificateType.X_509, CertificateType.RAW_PUBLIC_KEY); } - @SuppressWarnings("deprecation") @PostConstruct public void init() { try { /* by default trust all */ if (config.getTrustSslCredentials() != null) { X509Certificate[] trustedCertificates = config.getTrustSslCredentials().getTrustedCertificates(); - staticCertificateVerifier = new StaticCertificateVerifier(trustedCertificates); + staticCertificateVerifier = new StaticNewAdvancedCertificateVerifier(trustedCertificates, new RawPublicKeyIdentity[0], null); } - } catch (Exception e) { - log.info("Failed to initialize the "); + log.warn("Failed to initialize the LwM2M certificate verifier", e); } } @Override - public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, Boolean clientUsage, boolean truncateCertificatePath, CertificateMessage message, DTLSSession session) { + public CertificateVerificationResult verifyCertificate(ConnectionId cid, ServerNames serverName, InetSocketAddress remotePeer, + boolean clientUsage, boolean verifySubject, boolean truncateCertificatePath, + CertificateMessage message) { CertPath certChain = message.getCertificateChain(); if (certChain == null) { //We trust all RPK on this layer, and use TbLwM2MAuthorizer @@ -115,21 +115,24 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer } TbLwM2MSecurityInfo securityInfo = null; if (staticCertificateVerifier != null) { - try { - staticCertificateVerifier.verifyCertificate(message, session); - String endpoint = config.getTrustSslCredentials().getValueFromSubjectNameByKey(cert.getSubjectX500Principal().getName(), "CN"); - if (StringUtils.isNotEmpty(endpoint)) { - securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(endpoint, CLIENT); + HandshakeException exception = staticCertificateVerifier.verifyCertificate(cid, serverName, remotePeer, clientUsage, verifySubject, truncateCertificatePath, message).getException(); + if (exception == null) { + try { + String endpoint = config.getTrustSslCredentials().getValueFromSubjectNameByKey(cert.getSubjectX500Principal().getName(), "CN"); + if (StringUtils.isNotEmpty(endpoint)) { + securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(endpoint, CLIENT); + } + } catch (LwM2MAuthException e) { + log.trace("Certificate trust validation failed.", e); } - } catch (HandshakeException | LwM2MAuthException e) { - log.trace("Certificate trust validation failed.", e); + } else { + log.trace("Certificate trust validation failed.", exception); } } // if not trust or cert trust securityInfo == null String strCert = SslUtil.getCertificateString(cert); String sha3Hash = EncryptionUtil.getSha3Hash(strCert); if (securityInfo == null || securityInfo.getMsg() == null) { - try { securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(sha3Hash, CLIENT); } catch (LwM2MAuthException e) { @@ -168,8 +171,7 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer } } if (!x509CredentialsFound) { - AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.INTERNAL_ERROR, - session.getPeer()); + AlertMessage alert = new AlertMessage(AlertMessage.AlertLevel.FATAL, AlertMessage.AlertDescription.INTERNAL_ERROR); throw new HandshakeException("x509 verification not enabled!", alert); } return new CertificateVerificationResult(cid, certChain, null); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 1245aeb9ea..23238a07a5 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.scandium.config.DtlsConfig; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.californium.scandium.dtls.cipher.CipherSuite; import org.eclipse.leshan.core.node.codec.DefaultLwM2mDecoder; @@ -40,6 +41,8 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import javax.annotation.PreDestroy; import java.security.cert.X509Certificate; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CURVES_ONLY; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; @@ -121,11 +124,12 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { /* Create DTLS Config */ - DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); + DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(getCoapConfig(config.getPort(), config.getSecurePort(), config)); + + dtlsConfig.set(DtlsConfig.DTLS_ROLE, DtlsConfig.DtlsRole.SERVER_ONLY); + dtlsConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, config.isRecommendedSupportedGroups()); + dtlsConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, config.isRecommendedCiphers()); - dtlsConfig.setServerOnly(true); - dtlsConfig.setRecommendedSupportedGroupsOnly(config.isRecommendedSupportedGroups()); - dtlsConfig.setRecommendedCipherSuitesOnly(config.isRecommendedCiphers()); /* Create credentials */ this.setServerWithCredentials(builder, dtlsConfig); @@ -144,12 +148,12 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { builder.setCertificateChain(sslCredentials.getCertificateChain()); dtlsConfig.setAdvancedCertificateVerifier(certificateVerifier); builder.setAuthorizer(authorizer); - dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES); + dtlsConfig.setAsList(DtlsConfig.DTLS_CIPHER_SUITES, RPK_OR_X509_CIPHER_SUITES); } else { /* by default trust all */ builder.setTrustedCertificates(new X509Certificate[0]); log.info("Unable to load X509 files for LWM2MServer"); - dtlsConfig.setSupportedCipherSuites(PSK_CIPHER_SUITES); + dtlsConfig.setAsList(DtlsConfig.DTLS_CIPHER_SUITES, PSK_CIPHER_SUITES); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java index 31e0ae4de5..b47e548b56 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java @@ -15,27 +15,30 @@ */ package org.thingsboard.server.transport.lwm2m.server; -import org.eclipse.californium.core.network.config.NetworkConfig; -import org.eclipse.californium.core.network.config.NetworkConfigDefaults; +import org.eclipse.californium.core.config.CoapConfig; +import org.eclipse.californium.elements.config.Configuration; import org.springframework.util.CollectionUtils; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; -import static org.eclipse.californium.core.network.config.NetworkConfigDefaults.DEFAULT_BLOCKWISE_STATUS_LIFETIME; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +import static org.eclipse.californium.core.config.CoapConfig.DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS; public class LwM2MNetworkConfig { - public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort, LwM2MTransportServerConfig config) { - NetworkConfig coapConfig = new NetworkConfig(); - coapConfig.setInt(NetworkConfig.Keys.COAP_PORT, serverPortNoSec); - coapConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT, serverSecurePort); + public static Configuration getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort, LwM2MTransportServerConfig config) { + Configuration coapConfig = new Configuration(); + coapConfig.set(CoapConfig.COAP_PORT, serverPortNoSec); + coapConfig.set(CoapConfig.COAP_SECURE_PORT, serverSecurePort); /** Example:Property for large packet: #NetworkConfig config = new NetworkConfig(); - #config.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE,32); - #config.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE,32); - #config.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE,2048); - #config.setInt(NetworkConfig.Keys.MAX_RETRANSMIT,3); - #config.setInt(NetworkConfig.Keys.MAX_TRANSMIT_WAIT,120000); + #config.setInt(CoapConfig.MAX_MESSAGE_SIZE,32); + #config.setInt(CoapConfig.PREFERRED_BLOCK_SIZE,32); + #config.setInt(CoapConfig.MAX_RESOURCE_BODY_SIZE,2048); + #config.setInt(CoapConfig.MAX_RETRANSMIT,3); + #config.setInt(CoapConfig.MAX_TRANSMIT_WAIT,120000); */ /** @@ -46,14 +49,14 @@ public class LwM2MNetworkConfig { CoAP client will try to use block mode or adapt the block size when receiving a 4.13 Entity too large response code */ - coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_STRICT_BLOCK2_OPTION, true); + coapConfig.set(CoapConfig.BLOCKWISE_STRICT_BLOCK2_OPTION, true); /** Property to indicate if the response should always include the Block2 option \ when client request early blockwise negociation but the response can be sent on one packet. - value of false indicate that the server will respond without block2 option if no further blocks are required. - value of true indicate that the server will response with block2 option event if no further blocks are required. */ - coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true); + coapConfig.set(CoapConfig.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true); /** * The maximum amount of time (in milliseconds) allowed between * transfers of individual blocks in a blockwise transfer before the @@ -62,7 +65,7 @@ public class LwM2MNetworkConfig { * The default value of this property is * {@link NetworkConfigDefaults#DEFAULT_BLOCKWISE_STATUS_LIFETIME} = 5 * 60 * 1000; // 5 mins [ms]. */ - coapConfig.setLong(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, DEFAULT_BLOCKWISE_STATUS_LIFETIME); + coapConfig.set(CoapConfig.BLOCKWISE_STATUS_LIFETIME, DEFAULT_BLOCKWISE_STATUS_LIFETIME_IN_SECONDS, TimeUnit.SECONDS); /** !!! REQUEST_ENTITY_TOO_LARGE CODE=4.13 The maximum size of a resource body (in bytes) that will be accepted @@ -77,7 +80,7 @@ public class LwM2MNetworkConfig { The default value of this property is DEFAULT_MAX_RESOURCE_BODY_SIZE = 8192 A value of {@code 0} turns off transparent handling of blockwise transfers altogether. */ - coapConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 256 * 1024 * 1024); + coapConfig.set(CoapConfig.MAX_RESOURCE_BODY_SIZE, 256 * 1024 * 1024); /** The default DTLS response matcher. Supported values are STRICT, RELAXED, or PRINCIPAL. @@ -88,13 +91,13 @@ public class LwM2MNetworkConfig { – true with address check, (STRICT, UDP) - if port Registration of client is changed - it is bad - false, without */ - coapConfig.setString(NetworkConfig.Keys.RESPONSE_MATCHING, "RELAXED"); + coapConfig.set(CoapConfig.RESPONSE_MATCHING, CoapConfig.MatcherMode.RELAXED); /** https://tools.ietf.org/html/rfc7959#section-2.9.3 The block size (number of bytes) to use when doing a blockwise transfer. \ This value serves as the upper limit for block size in blockwise transfers */ - coapConfig.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE, 1024); + coapConfig.set(CoapConfig.PREFERRED_BLOCK_SIZE, 1024); /** The maximum payload size (in bytes) that can be transferred in a single message, i.e. without requiring a blockwise transfer. @@ -102,12 +105,14 @@ public class LwM2MNetworkConfig { In particular, this value cannot exceed the network's MTU if UDP is used as the transport protocol DEFAULT_VALUE = 1024 */ - coapConfig.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE, 1024); + coapConfig.set(CoapConfig.MAX_MESSAGE_SIZE, 1024); - coapConfig.setInt(NetworkConfig.Keys.MAX_RETRANSMIT, 10); + coapConfig.set(CoapConfig.MAX_RETRANSMIT, 10); if (!CollectionUtils.isEmpty(config.getNetworkConfig())) { - config.getNetworkConfig().forEach(p -> coapConfig.setString(p.getKey(), p.getValue())); + Properties networkProps = new Properties(); + config.getNetworkConfig().forEach(p -> networkProps.put(p.getKey(), p.getValue())); + coapConfig.add(networkProps); } return coapConfig; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java index 7ffcf88e31..5c0e225f8b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java @@ -16,7 +16,10 @@ package org.thingsboard.server.transport.lwm2m.server; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.observation.CompositeObservation; import org.eclipse.leshan.core.observation.Observation; +import org.eclipse.leshan.core.observation.SingleObservation; +import org.eclipse.leshan.core.response.ObserveCompositeResponse; import org.eclipse.leshan.core.response.ObserveResponse; import org.eclipse.leshan.server.observation.ObservationListener; import org.eclipse.leshan.server.queue.PresenceListener; @@ -86,26 +89,34 @@ public class LwM2mServerListener { @Override public void cancelled(Observation observation) { - log.trace("Canceled Observation {}.", observation.getPath()); + //TODO: should be able to use CompositeObservation + log.trace("Canceled Observation {}.", ((SingleObservation)observation).getPath()); } @Override - public void onResponse(Observation observation, Registration registration, ObserveResponse response) { + public void onResponse(SingleObservation observation, Registration registration, ObserveResponse response) { if (registration != null) { service.onUpdateValueAfterReadResponse(registration, convertObjectIdToVersionedId(observation.getPath().toString(), registration), response); } } + @Override + public void onResponse(CompositeObservation observation, Registration registration, ObserveCompositeResponse response) { + throw new RuntimeException("Not implemented yet!"); + } + @Override public void onError(Observation observation, Registration registration, Exception error) { if (error != null) { - log.debug("Unable to handle notification of [{}:{}] [{}]", observation.getRegistrationId(), observation.getPath(), error.getMessage()); + //TODO: should be able to use CompositeObservation + log.debug("Unable to handle notification of [{}:{}] [{}]", observation.getRegistrationId(), ((SingleObservation)observation).getPath(), error.getMessage()); } } @Override public void newObservation(Observation observation, Registration registration) { - log.trace("Successful start newObservation {}.", observation.getPath()); + //TODO: should be able to use CompositeObservation + log.trace("Successful start newObservation {}.", ((SingleObservation)observation).getPath()); } }; } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java index 53bb650868..fdf5e5f8bc 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java @@ -56,7 +56,7 @@ public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { if (relation == null || relation.isCanceled()) { return; // because request did not try to establish a relation } - if (CoAP.ResponseCode.isSuccess(response.getCode())) { + if (response.getCode().isSuccess()) { if (!relation.isEstablished()) { relation.setEstablished(); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java index 6f25e752d0..04b8f858c6 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java @@ -39,7 +39,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; -import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion; +import org.thingsboard.server.transport.lwm2m.config.TbLwM2mVersion; import java.io.IOException; import java.io.ObjectInputStream; @@ -423,14 +423,14 @@ public class LwM2mClient implements Serializable { if (registration == null) { return ContentFormat.DEFAULT; } else{ - return LwM2mVersion.fromVersion(registration.getLwM2mVersion()).getContentFormat(); + return TbLwM2mVersion.fromVersion(registration.getLwM2mVersion()).getContentFormat(); } } static private Set clientSupportContentFormat(Registration registration) { Set contentFormats = new HashSet<>(); contentFormats.add(ContentFormat.DEFAULT); - String code = Arrays.stream(registration.getObjectLinks()).filter(link -> link.getUrl().equals("/")).findFirst().get().getAttributes().get("ct"); + String code = Arrays.stream(registration.getObjectLinks()).filter(link -> link.getUriReference().equals("/")).findFirst().get().getLinkParams().get("ct").getUnquoted(); if (code != null) { Set codes = Stream.of(code.replaceAll("\"", "").split(" ", -1)) .map(String::trim) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index 5fcb532c10..eb675c9461 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java @@ -393,9 +393,9 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { public Set getSupportedIdVerInClient(LwM2mClient client) { Set clientObjects = ConcurrentHashMap.newKeySet(); Arrays.stream(client.getRegistration().getObjectLinks()).forEach(link -> { - LwM2mPath pathIds = new LwM2mPath(link.getUrl()); + LwM2mPath pathIds = new LwM2mPath(link.getUriReference()); if (!pathIds.isRoot()) { - clientObjects.add(convertObjectIdToVersionedId(link.getUrl(), client.getRegistration())); + clientObjects.add(convertObjectIdToVersionedId(link.getUriReference(), client.getRegistration())); } }); return (clientObjects.size() > 0) ? clientObjects : null; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java index 48292c92d0..89d461c76b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java @@ -17,7 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.downlink; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.eclipse.leshan.core.Link; +import org.eclipse.leshan.core.link.Link; import org.eclipse.leshan.core.LwM2m; import org.eclipse.leshan.core.attributes.Attribute; import org.eclipse.leshan.core.attributes.AttributeSet; @@ -29,6 +29,7 @@ import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mResource; import org.eclipse.leshan.core.node.ObjectLink; import org.eclipse.leshan.core.observation.Observation; +import org.eclipse.leshan.core.observation.SingleObservation; import org.eclipse.leshan.core.request.CompositeDownlinkRequest; import org.eclipse.leshan.core.request.ContentFormat; import org.eclipse.leshan.core.request.CreateRequest; @@ -160,7 +161,8 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im validateVersionedId(client, request); LwM2mPath resultIds = new LwM2mPath(request.getObjectId()); Set observations = context.getServer().getObservationService().getObservations(client.getRegistration()); - if (observations.stream().noneMatch(observation -> observation.getPath().equals(resultIds))) { + //TODO: should be able to use CompositeObservation + if (observations.stream().noneMatch(observation -> ((SingleObservation)observation).getPath().equals(resultIds))) { ObserveRequest downlink; ContentFormat contentFormat = getReadRequestContentFormat(client, request, modelProvider); if (resultIds.isResource()) { @@ -183,7 +185,8 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @Override public void sendObserveAllRequest(LwM2mClient client, TbLwM2MObserveAllRequest request, DownlinkRequestCallback> callback) { Set observations = context.getServer().getObservationService().getObservations(client.getRegistration()); - Set paths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); + //TODO: should be able to use CompositeObservation + Set paths = observations.stream().map(observation -> ((SingleObservation)observation).getPath().toString()).collect(Collectors.toUnmodifiableSet()); callback.onSuccess(request, paths); } @@ -620,9 +623,9 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im } private static ContentFormat getContentFormatForComplex(LwM2mClient client) { - if (LwM2m.Version.V1_0.equals(client.getRegistration().getLwM2mVersion())) { + if (LwM2m.LwM2mVersion.V1_0.equals(client.getRegistration().getLwM2mVersion())) { return ContentFormat.TLV; - } else if (LwM2m.Version.V1_1.equals(client.getRegistration().getLwM2mVersion())) { + } else if (LwM2m.LwM2mVersion.V1_1.equals(client.getRegistration().getLwM2mVersion())) { ContentFormat result = findFirst(client.getClientSupportContentFormats(), null, ContentFormat.SENML_CBOR, ContentFormat.SENML_JSON, ContentFormat.TLV, ContentFormat.JSON); if (result != null) { return result; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java index b6f2c37c1d..9f5bf80cf6 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.transport.lwm2m.server.downlink; -import org.eclipse.leshan.core.Link; +import org.eclipse.leshan.core.link.Link; import org.eclipse.leshan.core.request.ContentFormat; import org.eclipse.leshan.core.request.CreateRequest; import org.eclipse.leshan.core.request.DeleteRequest; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/RpcDiscoverCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/RpcDiscoverCallback.java index d9c213604c..c221f598a2 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/RpcDiscoverCallback.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/RpcDiscoverCallback.java @@ -15,7 +15,8 @@ */ package org.thingsboard.server.transport.lwm2m.server.rpc; -import org.eclipse.leshan.core.Link; +import org.eclipse.leshan.core.link.DefaultLinkSerializer; +import org.eclipse.leshan.core.link.LinkSerializer; import org.eclipse.leshan.core.request.DiscoverRequest; import org.eclipse.leshan.core.response.DiscoverResponse; import org.thingsboard.server.common.transport.TransportService; @@ -27,12 +28,14 @@ import java.util.Optional; public class RpcDiscoverCallback extends RpcLwM2MDownlinkCallback { + private final LinkSerializer serializer = new DefaultLinkSerializer(); + public RpcDiscoverCallback(TransportService transportService, LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, DownlinkRequestCallback callback) { super(transportService, client, requestMsg, callback); } protected Optional serializeSuccessfulResponse(DiscoverResponse response) { - return Optional.of(Link.serialize(response.getObjectLinks())); + return Optional.of(serializer.serialize(response.getObjectLinks())); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java index afa5eae53a..0b1254115e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java @@ -22,10 +22,11 @@ import org.eclipse.leshan.core.Destroyable; import org.eclipse.leshan.core.Startable; import org.eclipse.leshan.core.Stoppable; import org.eclipse.leshan.core.observation.Observation; +import org.eclipse.leshan.core.observation.SingleObservation; import org.eclipse.leshan.core.request.Identity; import org.eclipse.leshan.core.util.NamedThreadFactory; import org.eclipse.leshan.core.util.Validate; -import org.eclipse.leshan.server.californium.observation.ObserveUtil; +import org.eclipse.leshan.core.californium.ObserveUtil; import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; import org.eclipse.leshan.server.redis.RedisRegistrationStore; import org.eclipse.leshan.server.redis.serialization.IdentitySerDes; @@ -455,7 +456,8 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto // cancel existing observations for the same path and registration id. for (Observation obs : getObservations(connection, registrationId)) { - if (observation.getPath().equals(obs.getPath()) + //TODO: should be able to use CompositeObservation + if (((SingleObservation)observation).getPath().equals(((SingleObservation)obs).getPath()) && !Arrays.equals(observation.getId(), obs.getId())) { removed.add(obs); unsafeRemoveObservation(connection, registrationId, obs.getId()); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java index b1f6637085..e415858755 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java @@ -30,7 +30,6 @@ import org.eclipse.leshan.core.node.LwM2mMultipleResource; import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mResource; import org.eclipse.leshan.core.node.LwM2mSingleResource; -import org.eclipse.leshan.core.node.ObjectLink; import org.eclipse.leshan.core.node.codec.CodecException; import org.eclipse.leshan.core.request.SimpleDownlinkRequest; import org.eclipse.leshan.core.request.WriteAttributesRequest; @@ -44,7 +43,7 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.ota.OtaPackageKey; import org.thingsboard.server.common.transport.util.JsonUtils; -import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion; +import org.thingsboard.server.transport.lwm2m.config.TbLwM2mVersion; import org.thingsboard.server.transport.lwm2m.server.LwM2mOtaConvert; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; @@ -236,7 +235,7 @@ public class LwM2MTransportUtil { public static String convertObjectIdToVersionedId(String path, Registration registration) { String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId()); - ver = ver != null ? ver : LwM2mVersion.VERSION_1_0.getVersion().toString(); + ver = ver != null ? ver : TbLwM2mVersion.VERSION_1_0.getVersion().toString(); try { String[] keyArray = path.split(LWM2M_SEPARATOR_PATH); if (keyArray.length > 1) { diff --git a/pom.xml b/pom.xml index 96ff02f20f..295e01f2d3 100755 --- a/pom.xml +++ b/pom.xml @@ -68,8 +68,8 @@ 2.12.1 1.3.4 2.2.6 - 2.6.1 - 2.0.0-M4 + 3.0.0 + 2.0.0-M5 2.6.2 2.3.30 1.6.2