From b6f317a3b7b8c56a02acfbbfc35e242b6d0f3506 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 9 Feb 2022 18:11:02 +0200 Subject: [PATCH] lwm2m: fix bugs: init client after connect Lwm2m Server -> awaitClientAfterStartConnectLw() and null pointer exception in getObjectModel --- .../lwm2m/client/LwM2MTestClient.java | 47 +++++++++++++++---- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 5 +- .../AbstractSecurityLwM2MIntegrationTest.java | 14 +++--- .../sql/NoSecLwM2MIntegrationTest.java | 8 ++-- .../security/sql/PskLwm2mIntegrationTest.java | 6 ++- .../security/sql/RpkLwM2MIntegrationTest.java | 6 ++- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 6 ++- .../sql/X509_TrustLwM2MIntegrationTest.java | 6 ++- .../lwm2m/server/client/LwM2mClient.java | 23 +++++++-- .../uplink/DefaultLwM2mUplinkMsgHandler.java | 2 +- 10 files changed, 85 insertions(+), 38 deletions(-) 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 a40922d136..23ae26a0ca 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 @@ -1,12 +1,12 @@ /** * Copyright © 2016-2022 The Thingsboard Authors - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -42,14 +42,21 @@ import org.eclipse.leshan.core.request.DeregisterRequest; import org.eclipse.leshan.core.request.RegisterRequest; import org.eclipse.leshan.core.request.UpdateRequest; import org.junit.Assert; +import org.mockito.Mockito; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; +import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2mUplinkMsgHandler; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; + import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import static org.awaitility.Awaitility.await; 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; @@ -105,9 +112,12 @@ public class LwM2MTestClient { private LwM2mTemperatureSensor lwM2MTemperatureSensor; private LwM2MClientState clientState; private Set clientStates; + private DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; - public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, int shortServerId, int shortServerIdBs, Security securityBs) throws InvalidDDFFileException, IOException { + public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, + int shortServerId, int shortServerIdBs, Security securityBs, DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", leshanClient); + this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler; List models = new ArrayList<>(); for (String resourceName : resources) { models.addAll(ObjectLoader.loadDdfFile(LwM2MTestClient.class.getClassLoader().getResourceAsStream("lwm2m/" + resourceName), resourceName)); @@ -277,7 +287,7 @@ public class LwM2MTestClient { this.leshanClient.addObserver(observer); if (!isRpc) { - leshanClient.start(); + this.start(true); } } @@ -294,7 +304,7 @@ public class LwM2MTestClient { if (lwm2mServerBs != null) { lwm2mServerBs = null; } - if (lwm2mServer != null) { + if (lwm2mServer != null) { lwm2mServer = null; } if (lwM2MDevice != null) { @@ -314,9 +324,30 @@ public class LwM2MTestClient { } } - public void start() { + public void start(boolean isStartLw) { if (leshanClient != null) { leshanClient.start(); + if (isStartLw) { + this.awaitClientAfterStartConnectLw(); + } + } + } + + private void awaitClientAfterStartConnectLw() { + LwM2mClient lwM2MClient = this.defaultLwM2mUplinkMsgHandlerTest.clientContext.getClientByEndpoint(endpoint); + CountDownLatch latch = new CountDownLatch(1); + Mockito.doAnswer(invocation -> { +// Object result = invocation.callRealMethod(); + latch.countDown(); + return null; + }).when(defaultLwM2mUplinkMsgHandlerTest).initAttributes(lwM2MClient, true); + + try { + if (!latch.await(1, TimeUnit.SECONDS)) { + throw new RuntimeException("Failed to await TimeOut lwm2m client initialization!"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Exception Failed to await lwm2m client initialization! ", e); } } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index d80b556d72..28fd86a383 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -146,10 +146,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg final Device device = createDevice(deviceCredentials, endpoint); deviceId = device.getId().getId().toString(); - lwM2MTestClient.start(); - - Thread.sleep(1000); - + lwM2MTestClient.start(true); } protected String pathIdVerToObjectId(String pathIdVer) { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index 15ddf062f7..e357b23afe 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -176,7 +176,8 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M awaitAlias, expectedStatuses, true, - finishState); + finishState, + false); } protected void basicTestConnection(Security security, @@ -187,14 +188,13 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M String awaitAlias, Set expectedStatuses, boolean isBootstrap, - LwM2MClientState finishState) throws Exception { + LwM2MClientState finishState, + boolean isStartLw) throws Exception { createNewClient(security, coapConfig, true, endpoint, isBootstrap, null); createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); device.getId().getId().toString(); - lwM2MTestClient.start(); - Thread.sleep(1000); - + lwM2MTestClient.start(isStartLw); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) .until(() -> finishState.equals(lwM2MTestClient.getClientState())); @@ -232,9 +232,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); String deviceId = device.getId().getId().toString(); - lwM2MTestClient.start(); - Thread.sleep(1000); - + lwM2MTestClient.start(true); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) .until(() -> ON_REGISTRATION_SUCCESS.equals(lwM2MTestClient.getClientState())); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java index 345902aa6e..203b1f56c7 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java @@ -66,28 +66,28 @@ public class NoSecLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationT } @Test - public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateTwoSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + public void testWithNoSecConnectLwm2mSuccessBootstrapRequestTriggerConnectBsSuccess_UpdateTwoSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + BOTH.name(); String awaitAlias = "await on client state (NoSecBS Trigger Two section)"; basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOTH); } @Test - public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateBootstrapSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + public void testWithNoSecConnectLwm2mSuccessBootstrapRequestTriggerConnectBsSuccess_UpdateBootstrapSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + BOOTSTRAP_ONLY.name(); String awaitAlias = "await on client state (NoSecBS Trigger Bootstrap section)"; basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOOTSTRAP_ONLY); } @Test - public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateLwm2mSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + public void testWithNoSecConnectLwm2mSuccessBootstrapRequestTriggerConnectBsSuccess_UpdateLwm2mSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + LWM2M_ONLY.name(); String awaitAlias = "await on client state (NoSecBS Trigger Lwm2m section)"; basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, LWM2M_ONLY); } @Test - public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateNoneSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + public void testWithNoSecConnectLwm2mSuccessBootstrapRequestTriggerConnectBsSuccess_UpdateNoneSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + NONE.name(); String awaitAlias = "await on client state (NoSecBS Trigger None section)"; basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, NONE); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index feff1ee926..7eeb4b4090 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -62,7 +62,8 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (Psk_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } @Test @@ -107,6 +108,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (PskBS two section)", expectedStatusesRegistrationBsSuccess, true, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index cfc55fae9a..16c34550c2 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -64,7 +64,8 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (Rpk_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } @Test @@ -124,6 +125,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (RpkBS two section)", expectedStatusesRegistrationBsSuccess, true, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index 6e9dc615e5..57e26c060e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -64,7 +64,8 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg "await on client state (X509_Trust_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } @Test @@ -124,6 +125,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg "await on client state (X509NoTrust two section)", expectedStatusesRegistrationBsSuccess, true, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java index 59c7360d20..cd0cec1c16 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java @@ -58,7 +58,8 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra "await on client state (X509_Trust_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } // Bootstrap + Lwm2m @@ -84,6 +85,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra "await on client state (X509Trust two section)", expectedStatusesRegistrationBsSuccess, true, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } } 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 9b04efa646..f1e4ea1b2c 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 @@ -297,11 +297,24 @@ public class LwM2mClient implements Serializable { } public ObjectModel getObjectModel(String pathIdVer, LwM2mModelProvider modelProvider) { - LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)); - String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); - String verRez = getVerFromPathIdVerOrId(pathIdVer); - return verRez != null && verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration) - .getObjectModel(pathIds.getObjectId()) : null; + try { + LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)); + String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); + String verRez = getVerFromPathIdVerOrId(pathIdVer); + return verRez != null && verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration) + .getObjectModel(pathIds.getObjectId()) : null; + } catch (Exception e) { + if (registration == null) { + log.error("Failed Registration is null, GetObjectModelRegistration. ", e); + } + else if (registration.getSupportedObject() == null) { + log.error("Failed SupportedObject in Registration == null, GetObjectModelRegistration.", e); + } + else { + log.error("Failed ModelProvider.getObjectModel [{}] in Registration. ", registration.getSupportedObject(), e); + } + return null; + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index f193a929e6..70863be6eb 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -150,7 +150,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl private final LwM2MTelemetryLogService logService; private final LwM2mTransportServerHelper helper; private final TbLwM2MDtlsSessionStore sessionStore; - private final LwM2mClientContext clientContext; + public final LwM2mClientContext clientContext; private final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler; private final LwM2mVersionedModelProvider modelProvider; private final RegistrationStore registrationStore;