lwm2m: fix bugs: init client after connect Lwm2m Server -> awaitClientAfterStartConnectLw() and null pointer exception in getObjectModel

This commit is contained in:
nickAS21 2022-02-09 18:11:02 +02:00
parent 974d4cb338
commit b6f317a3b7
10 changed files with 85 additions and 38 deletions

View File

@ -1,12 +1,12 @@
/** /**
* Copyright © 2016-2022 The Thingsboard Authors * Copyright © 2016-2022 The Thingsboard Authors
* * <p>
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* * <p>
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* * <p>
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 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.RegisterRequest;
import org.eclipse.leshan.core.request.UpdateRequest; import org.eclipse.leshan.core.request.UpdateRequest;
import org.junit.Assert; 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 org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledExecutorService; 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.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.ACCESS_CONTROL;
import static org.eclipse.leshan.core.LwM2mId.DEVICE; import static org.eclipse.leshan.core.LwM2mId.DEVICE;
@ -105,9 +112,12 @@ public class LwM2MTestClient {
private LwM2mTemperatureSensor lwM2MTemperatureSensor; private LwM2mTemperatureSensor lwM2MTemperatureSensor;
private LwM2MClientState clientState; private LwM2MClientState clientState;
private Set<LwM2MClientState> clientStates; private Set<LwM2MClientState> 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); Assert.assertNull("client already initialized", leshanClient);
this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler;
List<ObjectModel> models = new ArrayList<>(); List<ObjectModel> models = new ArrayList<>();
for (String resourceName : resources) { for (String resourceName : resources) {
models.addAll(ObjectLoader.loadDdfFile(LwM2MTestClient.class.getClassLoader().getResourceAsStream("lwm2m/" + resourceName), resourceName)); models.addAll(ObjectLoader.loadDdfFile(LwM2MTestClient.class.getClassLoader().getResourceAsStream("lwm2m/" + resourceName), resourceName));
@ -277,7 +287,7 @@ public class LwM2MTestClient {
this.leshanClient.addObserver(observer); this.leshanClient.addObserver(observer);
if (!isRpc) { if (!isRpc) {
leshanClient.start(); this.start(true);
} }
} }
@ -294,7 +304,7 @@ public class LwM2MTestClient {
if (lwm2mServerBs != null) { if (lwm2mServerBs != null) {
lwm2mServerBs = null; lwm2mServerBs = null;
} }
if (lwm2mServer != null) { if (lwm2mServer != null) {
lwm2mServer = null; lwm2mServer = null;
} }
if (lwM2MDevice != null) { if (lwM2MDevice != null) {
@ -314,9 +324,30 @@ public class LwM2MTestClient {
} }
} }
public void start() { public void start(boolean isStartLw) {
if (leshanClient != null) { if (leshanClient != null) {
leshanClient.start(); 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);
} }
} }
} }

View File

@ -146,10 +146,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
final Device device = createDevice(deviceCredentials, endpoint); final Device device = createDevice(deviceCredentials, endpoint);
deviceId = device.getId().getId().toString(); deviceId = device.getId().getId().toString();
lwM2MTestClient.start(); lwM2MTestClient.start(true);
Thread.sleep(1000);
} }
protected String pathIdVerToObjectId(String pathIdVer) { protected String pathIdVerToObjectId(String pathIdVer) {

View File

@ -176,7 +176,8 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
awaitAlias, awaitAlias,
expectedStatuses, expectedStatuses,
true, true,
finishState); finishState,
false);
} }
protected void basicTestConnection(Security security, protected void basicTestConnection(Security security,
@ -187,14 +188,13 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
String awaitAlias, String awaitAlias,
Set<LwM2MClientState> expectedStatuses, Set<LwM2MClientState> expectedStatuses,
boolean isBootstrap, boolean isBootstrap,
LwM2MClientState finishState) throws Exception { LwM2MClientState finishState,
boolean isStartLw) throws Exception {
createNewClient(security, coapConfig, true, endpoint, isBootstrap, null); createNewClient(security, coapConfig, true, endpoint, isBootstrap, null);
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
final Device device = createDevice(deviceCredentials, endpoint); final Device device = createDevice(deviceCredentials, endpoint);
device.getId().getId().toString(); device.getId().getId().toString();
lwM2MTestClient.start(); lwM2MTestClient.start(isStartLw);
Thread.sleep(1000);
await(awaitAlias) await(awaitAlias)
.atMost(1000, TimeUnit.MILLISECONDS) .atMost(1000, TimeUnit.MILLISECONDS)
.until(() -> finishState.equals(lwM2MTestClient.getClientState())); .until(() -> finishState.equals(lwM2MTestClient.getClientState()));
@ -232,9 +232,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
final Device device = createDevice(deviceCredentials, endpoint); final Device device = createDevice(deviceCredentials, endpoint);
String deviceId = device.getId().getId().toString(); String deviceId = device.getId().getId().toString();
lwM2MTestClient.start(); lwM2MTestClient.start(true);
Thread.sleep(1000);
await(awaitAlias) await(awaitAlias)
.atMost(1000, TimeUnit.MILLISECONDS) .atMost(1000, TimeUnit.MILLISECONDS)
.until(() -> ON_REGISTRATION_SUCCESS.equals(lwM2MTestClient.getClientState())); .until(() -> ON_REGISTRATION_SUCCESS.equals(lwM2MTestClient.getClientState()));

View File

@ -66,28 +66,28 @@ public class NoSecLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationT
} }
@Test @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 clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + BOTH.name();
String awaitAlias = "await on client state (NoSecBS Trigger Two section)"; String awaitAlias = "await on client state (NoSecBS Trigger Two section)";
basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOTH); basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOTH);
} }
@Test @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 clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + BOOTSTRAP_ONLY.name();
String awaitAlias = "await on client state (NoSecBS Trigger Bootstrap section)"; String awaitAlias = "await on client state (NoSecBS Trigger Bootstrap section)";
basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOOTSTRAP_ONLY); basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOOTSTRAP_ONLY);
} }
@Test @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 clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + LWM2M_ONLY.name();
String awaitAlias = "await on client state (NoSecBS Trigger Lwm2m section)"; String awaitAlias = "await on client state (NoSecBS Trigger Lwm2m section)";
basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, LWM2M_ONLY); basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, LWM2M_ONLY);
} }
@Test @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 clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + NONE.name();
String awaitAlias = "await on client state (NoSecBS Trigger None section)"; String awaitAlias = "await on client state (NoSecBS Trigger None section)";
basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, NONE); basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, NONE);

View File

@ -62,7 +62,8 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes
"await on client state (Psk_Lwm2m)", "await on client state (Psk_Lwm2m)",
expectedStatusesRegistrationLwm2mSuccess, expectedStatusesRegistrationLwm2mSuccess,
false, false,
ON_REGISTRATION_SUCCESS); ON_REGISTRATION_SUCCESS,
true);
} }
@Test @Test
@ -107,6 +108,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes
"await on client state (PskBS two section)", "await on client state (PskBS two section)",
expectedStatusesRegistrationBsSuccess, expectedStatusesRegistrationBsSuccess,
true, true,
ON_REGISTRATION_SUCCESS); ON_REGISTRATION_SUCCESS,
true);
} }
} }

View File

@ -64,7 +64,8 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes
"await on client state (Rpk_Lwm2m)", "await on client state (Rpk_Lwm2m)",
expectedStatusesRegistrationLwm2mSuccess, expectedStatusesRegistrationLwm2mSuccess,
false, false,
ON_REGISTRATION_SUCCESS); ON_REGISTRATION_SUCCESS,
true);
} }
@Test @Test
@ -124,6 +125,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes
"await on client state (RpkBS two section)", "await on client state (RpkBS two section)",
expectedStatusesRegistrationBsSuccess, expectedStatusesRegistrationBsSuccess,
true, true,
ON_REGISTRATION_SUCCESS); ON_REGISTRATION_SUCCESS,
true);
} }
} }

View File

@ -64,7 +64,8 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg
"await on client state (X509_Trust_Lwm2m)", "await on client state (X509_Trust_Lwm2m)",
expectedStatusesRegistrationLwm2mSuccess, expectedStatusesRegistrationLwm2mSuccess,
false, false,
ON_REGISTRATION_SUCCESS); ON_REGISTRATION_SUCCESS,
true);
} }
@Test @Test
@ -124,6 +125,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg
"await on client state (X509NoTrust two section)", "await on client state (X509NoTrust two section)",
expectedStatusesRegistrationBsSuccess, expectedStatusesRegistrationBsSuccess,
true, true,
ON_REGISTRATION_SUCCESS); ON_REGISTRATION_SUCCESS,
true);
} }
} }

View File

@ -58,7 +58,8 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra
"await on client state (X509_Trust_Lwm2m)", "await on client state (X509_Trust_Lwm2m)",
expectedStatusesRegistrationLwm2mSuccess, expectedStatusesRegistrationLwm2mSuccess,
false, false,
ON_REGISTRATION_SUCCESS); ON_REGISTRATION_SUCCESS,
true);
} }
// Bootstrap + Lwm2m // Bootstrap + Lwm2m
@ -84,6 +85,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra
"await on client state (X509Trust two section)", "await on client state (X509Trust two section)",
expectedStatusesRegistrationBsSuccess, expectedStatusesRegistrationBsSuccess,
true, true,
ON_REGISTRATION_SUCCESS); ON_REGISTRATION_SUCCESS,
true);
} }
} }

View File

@ -297,11 +297,24 @@ public class LwM2mClient implements Serializable {
} }
public ObjectModel getObjectModel(String pathIdVer, LwM2mModelProvider modelProvider) { public ObjectModel getObjectModel(String pathIdVer, LwM2mModelProvider modelProvider) {
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)); try {
String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer));
String verRez = getVerFromPathIdVerOrId(pathIdVer); String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
return verRez != null && verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration) String verRez = getVerFromPathIdVerOrId(pathIdVer);
.getObjectModel(pathIds.getObjectId()) : null; 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;
}
} }

View File

@ -150,7 +150,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
private final LwM2MTelemetryLogService logService; private final LwM2MTelemetryLogService logService;
private final LwM2mTransportServerHelper helper; private final LwM2mTransportServerHelper helper;
private final TbLwM2MDtlsSessionStore sessionStore; private final TbLwM2MDtlsSessionStore sessionStore;
private final LwM2mClientContext clientContext; public final LwM2mClientContext clientContext;
private final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler; private final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler;
private final LwM2mVersionedModelProvider modelProvider; private final LwM2mVersionedModelProvider modelProvider;
private final RegistrationStore registrationStore; private final RegistrationStore registrationStore;