Showing
6 changed files
with
93 additions
and
180 deletions
... | ... | @@ -60,6 +60,53 @@ import java.util.concurrent.ScheduledExecutorService; |
60 | 60 | @DaoSqlTest |
61 | 61 | public class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { |
62 | 62 | |
63 | + protected final String TRANSPORT_CONFIGURATION = "{\n" + | |
64 | + " \"type\": \"LWM2M\",\n" + | |
65 | + " \"observeAttr\": {\n" + | |
66 | + " \"keyName\": {\n" + | |
67 | + " \"/3_1.0/0/9\": \"batteryLevel\"\n" + | |
68 | + " },\n" + | |
69 | + " \"observe\": [],\n" + | |
70 | + " \"attribute\": [\n" + | |
71 | + " ],\n" + | |
72 | + " \"telemetry\": [\n" + | |
73 | + " \"/3_1.0/0/9\"\n" + | |
74 | + " ],\n" + | |
75 | + " \"attributeLwm2m\": {}\n" + | |
76 | + " },\n" + | |
77 | + " \"bootstrap\": {\n" + | |
78 | + " \"servers\": {\n" + | |
79 | + " \"binding\": \"U\",\n" + | |
80 | + " \"shortId\": 123,\n" + | |
81 | + " \"lifetime\": 300,\n" + | |
82 | + " \"notifIfDisabled\": true,\n" + | |
83 | + " \"defaultMinPeriod\": 1\n" + | |
84 | + " },\n" + | |
85 | + " \"lwm2mServer\": {\n" + | |
86 | + " \"host\": \"localhost\",\n" + | |
87 | + " \"port\": 5686,\n" + | |
88 | + " \"serverId\": 123,\n" + | |
89 | + " \"serverPublicKey\": \"\",\n" + | |
90 | + " \"bootstrapServerIs\": false,\n" + | |
91 | + " \"clientHoldOffTime\": 1,\n" + | |
92 | + " \"bootstrapServerAccountTimeout\": 0\n" + | |
93 | + " },\n" + | |
94 | + " \"bootstrapServer\": {\n" + | |
95 | + " \"host\": \"localhost\",\n" + | |
96 | + " \"port\": 5687,\n" + | |
97 | + " \"serverId\": 111,\n" + | |
98 | + " \"securityMode\": \"NO_SEC\",\n" + | |
99 | + " \"serverPublicKey\": \"\",\n" + | |
100 | + " \"bootstrapServerIs\": true,\n" + | |
101 | + " \"clientHoldOffTime\": 1,\n" + | |
102 | + " \"bootstrapServerAccountTimeout\": 0\n" + | |
103 | + " }\n" + | |
104 | + " },\n" + | |
105 | + " \"clientLwM2mSettings\": {\n" + | |
106 | + " \"clientOnlyObserveAfterConnect\": 1\n" + | |
107 | + " }\n" + | |
108 | + "}"; | |
109 | + | |
63 | 110 | protected DeviceProfile deviceProfile; |
64 | 111 | protected ScheduledExecutorService executor; |
65 | 112 | protected TbTestWebSocketClient wsClient; | ... | ... |
... | ... | @@ -22,6 +22,7 @@ import org.junit.Assert; |
22 | 22 | import org.junit.Test; |
23 | 23 | import org.thingsboard.common.util.JacksonUtil; |
24 | 24 | import org.thingsboard.server.common.data.Device; |
25 | +import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredentials; | |
25 | 26 | import org.thingsboard.server.common.data.query.EntityData; |
26 | 27 | import org.thingsboard.server.common.data.query.EntityDataPageLink; |
27 | 28 | import org.thingsboard.server.common.data.query.EntityDataQuery; |
... | ... | @@ -36,7 +37,6 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate; |
36 | 37 | import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd; |
37 | 38 | import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; |
38 | 39 | import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; |
39 | -import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredentials; | |
40 | 40 | |
41 | 41 | import java.util.Collections; |
42 | 42 | import java.util.List; |
... | ... | @@ -46,60 +46,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. |
46 | 46 | |
47 | 47 | public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
48 | 48 | |
49 | - protected final String TRANSPORT_CONFIGURATION = "{\n" + | |
50 | - " \"type\": \"LWM2M\",\n" + | |
51 | - " \"observeAttr\": {\n" + | |
52 | - " \"keyName\": {\n" + | |
53 | - " \"/3_1.0/0/9\": \"batteryLevel\"\n" + | |
54 | - " },\n" + | |
55 | - " \"observe\": [],\n" + | |
56 | - " \"attribute\": [\n" + | |
57 | - " ],\n" + | |
58 | - " \"telemetry\": [\n" + | |
59 | - " \"/3_1.0/0/9\"\n" + | |
60 | - " ],\n" + | |
61 | - " \"attributeLwm2m\": {}\n" + | |
62 | - " },\n" + | |
63 | - " \"bootstrap\": {\n" + | |
64 | - " \"servers\": {\n" + | |
65 | - " \"binding\": \"UQ\",\n" + | |
66 | - " \"shortId\": 123,\n" + | |
67 | - " \"lifetime\": 300,\n" + | |
68 | - " \"notifIfDisabled\": true,\n" + | |
69 | - " \"defaultMinPeriod\": 1\n" + | |
70 | - " },\n" + | |
71 | - " \"lwm2mServer\": {\n" + | |
72 | - " \"host\": \"localhost\",\n" + | |
73 | - " \"port\": 5685,\n" + | |
74 | - " \"serverId\": 123,\n" + | |
75 | - " \"securityMode\": \"NO_SEC\",\n" + | |
76 | - " \"serverPublicKey\": \"\",\n" + | |
77 | - " \"bootstrapServerIs\": false,\n" + | |
78 | - " \"clientHoldOffTime\": 1,\n" + | |
79 | - " \"bootstrapServerAccountTimeout\": 0\n" + | |
80 | - " },\n" + | |
81 | - " \"bootstrapServer\": {\n" + | |
82 | - " \"host\": \"localhost\",\n" + | |
83 | - " \"port\": 5687,\n" + | |
84 | - " \"serverId\": 111,\n" + | |
85 | - " \"securityMode\": \"NO_SEC\",\n" + | |
86 | - " \"serverPublicKey\": \"\",\n" + | |
87 | - " \"bootstrapServerIs\": true,\n" + | |
88 | - " \"clientHoldOffTime\": 1,\n" + | |
89 | - " \"bootstrapServerAccountTimeout\": 0\n" + | |
90 | - " }\n" + | |
91 | - " },\n" + | |
92 | - " \"clientLwM2mSettings\": {\n" + | |
93 | - " \"clientOnlyObserveAfterConnect\": 1\n" + | |
94 | - " }\n" + | |
95 | - "}"; | |
96 | - | |
97 | - private final int port = 5685; | |
98 | - private final Security security = noSec("coap://localhost:" + port, 123); | |
99 | - private final NetworkConfig coapConfig = new NetworkConfig().setString("COAP_PORT", Integer.toString(port)); | |
49 | + private final int PORT = 5685; | |
50 | + private final Security SECURITY = noSec("coap://localhost:" + PORT, 123); | |
51 | + private final NetworkConfig COAP_CONFIG = new NetworkConfig().setString("COAP_PORT", Integer.toString(PORT)); | |
52 | + private final String ENDPOINT = "deviceAEndpoint"; | |
100 | 53 | |
101 | 54 | @NotNull |
102 | - private Device createDevice(String deviceAEndpoint) throws Exception { | |
55 | + private Device createDevice() throws Exception { | |
103 | 56 | Device device = new Device(); |
104 | 57 | device.setName("Device A"); |
105 | 58 | device.setDeviceProfileId(deviceProfile.getId()); |
... | ... | @@ -114,20 +67,18 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
114 | 67 | |
115 | 68 | LwM2MCredentials noSecCredentials = new LwM2MCredentials(); |
116 | 69 | NoSecClientCredentials clientCredentials = new NoSecClientCredentials(); |
117 | - clientCredentials.setEndpoint(deviceAEndpoint); | |
70 | + clientCredentials.setEndpoint(ENDPOINT); | |
118 | 71 | noSecCredentials.setClient(clientCredentials); |
119 | 72 | deviceCredentials.setCredentialsValue(JacksonUtil.toString(noSecCredentials)); |
120 | 73 | doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk()); |
121 | 74 | return device; |
122 | 75 | } |
123 | 76 | |
124 | -// @Test | |
77 | + @Test | |
125 | 78 | public void testConnectAndObserveTelemetry() throws Exception { |
126 | 79 | createDeviceProfile(TRANSPORT_CONFIGURATION); |
127 | 80 | |
128 | - String deviceAEndpoint = "deviceAEndpoint"; | |
129 | - | |
130 | - Device device = createDevice(deviceAEndpoint); | |
81 | + Device device = createDevice(); | |
131 | 82 | |
132 | 83 | SingleEntityFilter sef = new SingleEntityFilter(); |
133 | 84 | sef.setSingleEntity(device.getId()); |
... | ... | @@ -144,8 +95,8 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
144 | 95 | wsClient.waitForReply(); |
145 | 96 | |
146 | 97 | wsClient.registerWaitForUpdate(); |
147 | - LwM2MTestClient client = new LwM2MTestClient(executor, deviceAEndpoint); | |
148 | - client.init(security, coapConfig); | |
98 | + LwM2MTestClient client = new LwM2MTestClient(executor, ENDPOINT); | |
99 | + client.init(SECURITY, COAP_CONFIG); | |
149 | 100 | String msg = wsClient.waitForUpdate(); |
150 | 101 | |
151 | 102 | EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class); | ... | ... |
... | ... | @@ -47,54 +47,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. |
47 | 47 | |
48 | 48 | public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
49 | 49 | |
50 | - protected final String TRANSPORT_CONFIGURATION = "{\n" + | |
51 | - " \"type\": \"LWM2M\",\n" + | |
52 | - " \"observeAttr\": {\n" + | |
53 | - " \"keyName\": {\n" + | |
54 | - " \"/3_1.0/0/9\": \"batteryLevel\"\n" + | |
55 | - " },\n" + | |
56 | - " \"observe\": [],\n" + | |
57 | - " \"attribute\": [\n" + | |
58 | - " ],\n" + | |
59 | - " \"telemetry\": [\n" + | |
60 | - " \"/3_1.0/0/9\"\n" + | |
61 | - " ],\n" + | |
62 | - " \"attributeLwm2m\": {}\n" + | |
63 | - " },\n" + | |
64 | - " \"bootstrap\": {\n" + | |
65 | - " \"servers\": {\n" + | |
66 | - " \"binding\": \"UQ\",\n" + | |
67 | - " \"shortId\": 123,\n" + | |
68 | - " \"lifetime\": 300,\n" + | |
69 | - " \"notifIfDisabled\": true,\n" + | |
70 | - " \"defaultMinPeriod\": 1\n" + | |
71 | - " },\n" + | |
72 | - " \"lwm2mServer\": {\n" + | |
73 | - " \"host\": \"localhost\",\n" + | |
74 | - " \"port\": 5686,\n" + | |
75 | - " \"serverId\": 123,\n" + | |
76 | - " \"serverPublicKey\": \"\",\n" + | |
77 | - " \"bootstrapServerIs\": false,\n" + | |
78 | - " \"clientHoldOffTime\": 1,\n" + | |
79 | - " \"bootstrapServerAccountTimeout\": 0\n" + | |
80 | - " },\n" + | |
81 | - " \"bootstrapServer\": {\n" + | |
82 | - " \"host\": \"localhost\",\n" + | |
83 | - " \"port\": 5687,\n" + | |
84 | - " \"serverId\": 111,\n" + | |
85 | - " \"securityMode\": \"NO_SEC\",\n" + | |
86 | - " \"serverPublicKey\": \"\",\n" + | |
87 | - " \"bootstrapServerIs\": true,\n" + | |
88 | - " \"clientHoldOffTime\": 1,\n" + | |
89 | - " \"bootstrapServerAccountTimeout\": 0\n" + | |
90 | - " }\n" + | |
91 | - " },\n" + | |
92 | - " \"clientLwM2mSettings\": {\n" + | |
93 | - " \"clientOnlyObserveAfterConnect\": 1\n" + | |
94 | - " }\n" + | |
95 | - "}"; | |
96 | - | |
97 | - | |
98 | 50 | private final int port = 5686; |
99 | 51 | private final NetworkConfig coapConfig = new NetworkConfig().setString("COAP_SECURE_PORT", Integer.toString(port)); |
100 | 52 | private final String endpoint = "deviceAEndpoint"; | ... | ... |
... | ... | @@ -17,18 +17,11 @@ package org.thingsboard.server.transport.lwm2m.client; |
17 | 17 | |
18 | 18 | import lombok.Data; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | +import org.eclipse.californium.core.network.CoapEndpoint; | |
20 | 21 | import org.eclipse.californium.core.network.config.NetworkConfig; |
21 | -import org.eclipse.californium.elements.Connector; | |
22 | +import org.eclipse.californium.core.observe.ObservationStore; | |
22 | 23 | import org.eclipse.californium.scandium.DTLSConnector; |
23 | 24 | import org.eclipse.californium.scandium.config.DtlsConnectorConfig; |
24 | -import org.eclipse.californium.scandium.dtls.ClientHandshaker; | |
25 | -import org.eclipse.californium.scandium.dtls.DTLSSession; | |
26 | -import org.eclipse.californium.scandium.dtls.HandshakeException; | |
27 | -import org.eclipse.californium.scandium.dtls.Handshaker; | |
28 | -import org.eclipse.californium.scandium.dtls.ResumingClientHandshaker; | |
29 | -import org.eclipse.californium.scandium.dtls.ResumingServerHandshaker; | |
30 | -import org.eclipse.californium.scandium.dtls.ServerHandshaker; | |
31 | -import org.eclipse.californium.scandium.dtls.SessionAdapter; | |
32 | 25 | import org.eclipse.leshan.client.californium.LeshanClient; |
33 | 26 | import org.eclipse.leshan.client.californium.LeshanClientBuilder; |
34 | 27 | import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory; |
... | ... | @@ -40,7 +33,7 @@ import org.eclipse.leshan.client.resource.ObjectsInitializer; |
40 | 33 | import org.eclipse.leshan.client.servers.ServerIdentity; |
41 | 34 | import org.eclipse.leshan.core.LwM2mId; |
42 | 35 | import org.eclipse.leshan.core.ResponseCode; |
43 | -import org.eclipse.leshan.core.californium.DefaultEndpointFactory; | |
36 | +import org.eclipse.leshan.core.californium.EndpointFactory; | |
44 | 37 | import org.eclipse.leshan.core.model.InvalidDDFFileException; |
45 | 38 | import org.eclipse.leshan.core.model.LwM2mModel; |
46 | 39 | import org.eclipse.leshan.core.model.ObjectLoader; |
... | ... | @@ -54,6 +47,7 @@ import org.eclipse.leshan.core.request.RegisterRequest; |
54 | 47 | import org.eclipse.leshan.core.request.UpdateRequest; |
55 | 48 | |
56 | 49 | import java.io.IOException; |
50 | +import java.net.InetSocketAddress; | |
57 | 51 | import java.util.ArrayList; |
58 | 52 | import java.util.List; |
59 | 53 | import java.util.concurrent.ScheduledExecutorService; |
... | ... | @@ -81,80 +75,49 @@ public class LwM2MTestClient { |
81 | 75 | initializer.setInstancesForObject(SECURITY, security); |
82 | 76 | initializer.setInstancesForObject(SERVER, new Server(123, 300)); |
83 | 77 | initializer.setInstancesForObject(DEVICE, new SimpleLwM2MDevice()); |
78 | + initializer.setClassForObject(LwM2mId.ACCESS_CONTROL, DummyInstanceEnabler.class); | |
84 | 79 | |
85 | 80 | DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); |
86 | 81 | dtlsConfig.setRecommendedCipherSuitesOnly(true); |
82 | + dtlsConfig.setClientOnly(); | |
87 | 83 | |
88 | 84 | DefaultRegistrationEngineFactory engineFactory = new DefaultRegistrationEngineFactory(); |
89 | 85 | engineFactory.setReconnectOnUpdate(false); |
90 | 86 | engineFactory.setResumeOnConnect(true); |
91 | 87 | |
92 | - DefaultEndpointFactory endpointFactory = new DefaultEndpointFactory(endpoint) { | |
88 | + EndpointFactory endpointFactory = new EndpointFactory() { | |
89 | + | |
90 | + @Override | |
91 | + public CoapEndpoint createUnsecuredEndpoint(InetSocketAddress address, NetworkConfig coapConfig, | |
92 | + ObservationStore store) { | |
93 | + CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); | |
94 | + builder.setInetSocketAddress(address); | |
95 | + builder.setNetworkConfig(coapConfig); | |
96 | + return builder.build(); | |
97 | + } | |
98 | + | |
93 | 99 | @Override |
94 | - protected Connector createSecuredConnector(DtlsConnectorConfig dtlsConfig) { | |
95 | - | |
96 | - return new DTLSConnector(dtlsConfig) { | |
97 | - @Override | |
98 | - protected void onInitializeHandshaker(Handshaker handshaker) { | |
99 | - handshaker.addSessionListener(new SessionAdapter() { | |
100 | - | |
101 | - @Override | |
102 | - public void handshakeStarted(Handshaker handshaker) throws HandshakeException { | |
103 | - if (handshaker instanceof ServerHandshaker) { | |
104 | - log.info("DTLS Full Handshake initiated by server : STARTED ..."); | |
105 | - } else if (handshaker instanceof ResumingServerHandshaker) { | |
106 | - log.info("DTLS abbreviated Handshake initiated by server : STARTED ..."); | |
107 | - } else if (handshaker instanceof ClientHandshaker) { | |
108 | - log.info("DTLS Full Handshake initiated by client : STARTED ..."); | |
109 | - } else if (handshaker instanceof ResumingClientHandshaker) { | |
110 | - log.info("DTLS abbreviated Handshake initiated by client : STARTED ..."); | |
111 | - } | |
112 | - } | |
113 | - | |
114 | - @Override | |
115 | - public void sessionEstablished(Handshaker handshaker, DTLSSession establishedSession) | |
116 | - throws HandshakeException { | |
117 | - if (handshaker instanceof ServerHandshaker) { | |
118 | - log.info("DTLS Full Handshake initiated by server : SUCCEED, handshaker {}", handshaker); | |
119 | - } else if (handshaker instanceof ResumingServerHandshaker) { | |
120 | - log.info("DTLS abbreviated Handshake initiated by server : SUCCEED, handshaker {}", handshaker); | |
121 | - } else if (handshaker instanceof ClientHandshaker) { | |
122 | - log.info("DTLS Full Handshake initiated by client : SUCCEED, handshaker {}", handshaker); | |
123 | - } else if (handshaker instanceof ResumingClientHandshaker) { | |
124 | - log.info("DTLS abbreviated Handshake initiated by client : SUCCEED, handshaker {}", handshaker); | |
125 | - } | |
126 | - } | |
127 | - | |
128 | - @Override | |
129 | - public void handshakeFailed(Handshaker handshaker, Throwable error) { | |
130 | - /** get cause */ | |
131 | - String cause; | |
132 | - if (error != null) { | |
133 | - if (error.getMessage() != null) { | |
134 | - cause = error.getMessage(); | |
135 | - } else { | |
136 | - cause = error.getClass().getName(); | |
137 | - } | |
138 | - } else { | |
139 | - cause = "unknown cause"; | |
140 | - } | |
141 | - | |
142 | - if (handshaker instanceof ServerHandshaker) { | |
143 | - log.info("DTLS Full Handshake initiated by server : FAILED [{}]", cause); | |
144 | - } else if (handshaker instanceof ResumingServerHandshaker) { | |
145 | - log.info("DTLS abbreviated Handshake initiated by server : FAILED [{}]", cause); | |
146 | - } else if (handshaker instanceof ClientHandshaker) { | |
147 | - log.info("DTLS Full Handshake initiated by client : FAILED [{}]", cause); | |
148 | - } else if (handshaker instanceof ResumingClientHandshaker) { | |
149 | - log.info("DTLS abbreviated Handshake initiated by client : FAILED [{}]", cause); | |
150 | - } | |
151 | - } | |
152 | - }); | |
153 | - } | |
154 | - }; | |
100 | + public CoapEndpoint createSecuredEndpoint(DtlsConnectorConfig dtlsConfig, NetworkConfig coapConfig, | |
101 | + ObservationStore store) { | |
102 | + CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); | |
103 | + DtlsConnectorConfig.Builder dtlsConfigBuilder = new DtlsConnectorConfig.Builder(dtlsConfig); | |
104 | + | |
105 | + // tricks to be able to change psk information on the fly | |
106 | +// AdvancedPskStore pskStore = dtlsConfig.getAdvancedPskStore(); | |
107 | +// if (pskStore != null) { | |
108 | +// PskPublicInformation identity = pskStore.getIdentity(null, null); | |
109 | +// SecretKey key = pskStore | |
110 | +// .requestPskSecretResult(ConnectionId.EMPTY, null, identity, null, null, null).getSecret(); | |
111 | +// singlePSKStore = new SinglePSKStore(identity, key); | |
112 | +// dtlsConfigBuilder.setAdvancedPskStore(singlePSKStore); | |
113 | +// } | |
114 | + builder.setConnector(new DTLSConnector(dtlsConfigBuilder.build())); | |
115 | + builder.setNetworkConfig(coapConfig); | |
116 | + return builder.build(); | |
155 | 117 | } |
156 | 118 | }; |
157 | 119 | |
120 | + | |
158 | 121 | LeshanClientBuilder builder = new LeshanClientBuilder(endpoint); |
159 | 122 | builder.setLocalAddress("0.0.0.0", 11000); |
160 | 123 | builder.setObjects(initializer.createAll()); | ... | ... |
No preview for this file type
No preview for this file type