Commit 4bc417456b04e08f988a0db718a619a931a842b2
Committed by
GitHub
1 parent
ad7c314b
lwm2m: back transport newKey start (#4278)
* lwm2m: back transport newKey start * lwm2m: back transport newKey start1 * lwm2m: back transport newKey fix bug save * lwm2m: back transport newKey test All security - ok * lwm2m: back transport newKey fix bug updateAttrShared
Showing
14 changed files
with
215 additions
and
405 deletions
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data.lwm2m; | |
17 | + | |
18 | +public interface LwM2mConstants { | |
19 | + | |
20 | + String LWM2M_SEPARATOR_PATH = "/"; | |
21 | + String LWM2M_SEPARATOR_KEY = "_"; | |
22 | + String LWM2M_SEPARATOR_SEARCH_TEXT = ":"; | |
23 | +} | ... | ... |
... | ... | @@ -41,6 +41,10 @@ |
41 | 41 | <artifactId>transport-api</artifactId> |
42 | 42 | </dependency> |
43 | 43 | <dependency> |
44 | + <groupId>org.thingsboard.common</groupId> | |
45 | + <artifactId>data</artifactId> | |
46 | + </dependency> | |
47 | + <dependency> | |
44 | 48 | <groupId>org.springframework</groupId> |
45 | 49 | <artifactId>spring-context-support</artifactId> |
46 | 50 | </dependency> | ... | ... |
... | ... | @@ -26,6 +26,8 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; |
26 | 26 | |
27 | 27 | import java.util.Collection; |
28 | 28 | |
29 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId; | |
30 | + | |
29 | 31 | @Slf4j |
30 | 32 | public class LwM2mServerListener { |
31 | 33 | |
... | ... | @@ -90,7 +92,7 @@ public class LwM2mServerListener { |
90 | 92 | public void onResponse(Observation observation, Registration registration, ObserveResponse response) { |
91 | 93 | if (registration != null) { |
92 | 94 | try { |
93 | - service.onObservationResponse(registration, observation.getPath().toString(), response); | |
95 | + service.onObservationResponse(registration, convertToIdVerFromObjectId(observation.getPath().toString(), registration), response); | |
94 | 96 | } catch (Exception e) { |
95 | 97 | log.error("[{}] onResponse", e.toString()); |
96 | 98 | ... | ... |
... | ... | @@ -22,6 +22,7 @@ import com.google.gson.JsonSyntaxException; |
22 | 22 | import lombok.extern.slf4j.Slf4j; |
23 | 23 | import org.apache.commons.lang3.StringUtils; |
24 | 24 | import org.eclipse.californium.core.network.config.NetworkConfig; |
25 | +import org.eclipse.leshan.core.model.ObjectModel; | |
25 | 26 | import org.eclipse.leshan.core.model.ResourceModel; |
26 | 27 | import org.eclipse.leshan.core.node.LwM2mMultipleResource; |
27 | 28 | import org.eclipse.leshan.core.node.LwM2mNode; |
... | ... | @@ -32,6 +33,7 @@ import org.eclipse.leshan.core.node.LwM2mSingleResource; |
32 | 33 | import org.eclipse.leshan.core.node.codec.CodecException; |
33 | 34 | import org.eclipse.leshan.core.util.Hex; |
34 | 35 | import org.eclipse.leshan.server.californium.LeshanServerBuilder; |
36 | +import org.eclipse.leshan.server.registration.Registration; | |
35 | 37 | import org.nustaq.serialization.FSTConfiguration; |
36 | 38 | import org.thingsboard.server.common.data.DeviceProfile; |
37 | 39 | import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; |
... | ... | @@ -47,14 +49,12 @@ import java.util.Date; |
47 | 49 | import java.util.LinkedList; |
48 | 50 | import java.util.Optional; |
49 | 51 | |
52 | +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; | |
53 | +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; | |
54 | + | |
50 | 55 | @Slf4j |
51 | -//@Component("LwM2MTransportHandler") | |
52 | -//@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' )|| ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | |
53 | 56 | public class LwM2mTransportHandler { |
54 | 57 | |
55 | - // We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to | |
56 | - // send a Confirmable message to the time when an acknowledgement is no longer expected. | |
57 | - | |
58 | 58 | public static final String BASE_DEVICE_API_TOPIC = "v1/devices/me"; |
59 | 59 | public static final String ATTRIBUTE = "attribute"; |
60 | 60 | public static final String TELEMETRY = "telemetry"; |
... | ... | @@ -84,6 +84,8 @@ public class LwM2mTransportHandler { |
84 | 84 | public static final String LOG_LW2M_ERROR = "error"; |
85 | 85 | public static final String LOG_LW2M_WARN = "warn"; |
86 | 86 | |
87 | + public static final int LWM2M_STRATEGY_1 = 1; | |
88 | + public static final int LWM2M_STRATEGY_2 = 2; | |
87 | 89 | |
88 | 90 | public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; |
89 | 91 | |
... | ... | @@ -110,39 +112,6 @@ public class LwM2mTransportHandler { |
110 | 112 | public static final String SERVICE_CHANNEL = "SERVICE"; |
111 | 113 | public static final String RESPONSE_CHANNEL = "RESP"; |
112 | 114 | |
113 | -// @Autowired | |
114 | -// @Qualifier("LeshanServerCert") | |
115 | -// private LeshanServer lhServerCert; | |
116 | -// | |
117 | -// @Autowired | |
118 | -// @Qualifier("LeshanServerNoSecPskRpk") | |
119 | -// private LeshanServer lhServerNoSecPskRpk; | |
120 | - | |
121 | -// @Autowired | |
122 | -// @Qualifier("ServerListenerCert") | |
123 | -// private LwM2mServerListener serverListenerCert; | |
124 | -// | |
125 | -// @Autowired | |
126 | -// @Qualifier("ServerListenerNoSecPskRpk") | |
127 | -// private LwM2mServerListener serverListenerNoSecPskRpk; | |
128 | - | |
129 | - | |
130 | -// @PostConstruct | |
131 | -// public void init() { | |
132 | -// try { | |
133 | -// serverListenerCert.init(lhServerCert); | |
134 | -// this.lhServerCert.getRegistrationService().addListener(serverListenerCert.registrationListener); | |
135 | -// this.lhServerCert.getPresenceService().addListener(serverListenerCert.presenceListener); | |
136 | -// this.lhServerCert.getObservationService().addListener(serverListenerCert.observationListener); | |
137 | -// serverListenerNoSecPskRpk.init(lhServerNoSecPskRpk); | |
138 | -// this.lhServerNoSecPskRpk.getRegistrationService().addListener(serverListenerNoSecPskRpk.registrationListener); | |
139 | -// this.lhServerNoSecPskRpk.getPresenceService().addListener(serverListenerNoSecPskRpk.presenceListener); | |
140 | -// this.lhServerNoSecPskRpk.getObservationService().addListener(serverListenerNoSecPskRpk.observationListener); | |
141 | -// } catch (Exception e) { | |
142 | -// log.error("init [{}]", e.toString()); | |
143 | -// } | |
144 | -// } | |
145 | - | |
146 | 115 | public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) { |
147 | 116 | NetworkConfig coapConfig; |
148 | 117 | File configFile = new File(NetworkConfig.DEFAULT_FILE_NAME); |
... | ... | @@ -202,10 +171,10 @@ public class LwM2mTransportHandler { |
202 | 171 | |
203 | 172 | /** |
204 | 173 | * @return deviceProfileBody with Observe&Attribute&Telemetry From Thingsboard |
205 | - * Example: | |
174 | + * Example: | |
206 | 175 | * property: {"clientLwM2mSettings": { |
207 | - * clientUpdateValueAfterConnect: false; | |
208 | - * } | |
176 | + * clientUpdateValueAfterConnect: false; | |
177 | + * } | |
209 | 178 | * property: "observeAttr" |
210 | 179 | * {"keyName": { |
211 | 180 | * "/3/0/1": "modelNumber", |
... | ... | @@ -222,7 +191,7 @@ public class LwM2mTransportHandler { |
222 | 191 | try { |
223 | 192 | ObjectMapper mapper = new ObjectMapper(); |
224 | 193 | String profileStr = mapper.writeValueAsString(profile); |
225 | - JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; | |
194 | + JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; | |
226 | 195 | return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId()) : null; |
227 | 196 | } catch (IOException e) { |
228 | 197 | log.error("", e); |
... | ... | @@ -246,9 +215,9 @@ public class LwM2mTransportHandler { |
246 | 215 | return null; |
247 | 216 | } |
248 | 217 | |
249 | - public static boolean getClientOnlyObserveAfterConnect (LwM2mClientProfile profile) { | |
250 | - return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") && | |
251 | - profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsBoolean(); | |
218 | + public static int getClientOnlyObserveAfterConnect(LwM2mClientProfile profile) { | |
219 | + return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") ? | |
220 | + profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsInt() : 1; | |
252 | 221 | } |
253 | 222 | |
254 | 223 | private static boolean getValidateCredentialsBodyFromThingsboard(JsonObject objectMsg) { |
... | ... | @@ -346,4 +315,49 @@ public class LwM2mTransportHandler { |
346 | 315 | } |
347 | 316 | }; |
348 | 317 | } |
318 | + | |
319 | + public static String convertToObjectIdFromIdVer(String key) { | |
320 | + try { | |
321 | + String[] keyArray = key.split(LWM2M_SEPARATOR_PATH); | |
322 | + if (keyArray.length > 1 && keyArray[1].split(LWM2M_SEPARATOR_KEY).length == 2) { | |
323 | + keyArray[1] = keyArray[1].split(LWM2M_SEPARATOR_KEY)[0]; | |
324 | + return StringUtils.join(keyArray, LWM2M_SEPARATOR_PATH); | |
325 | + } else { | |
326 | + return key; | |
327 | + } | |
328 | + } catch (Exception e) { | |
329 | + return null; | |
330 | + } | |
331 | + } | |
332 | + | |
333 | + public static String convertToIdVerFromObjectId(String path, Registration registration) { | |
334 | + String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId()); | |
335 | + try { | |
336 | + String[] keyArray = path.split(LWM2M_SEPARATOR_PATH); | |
337 | + if (keyArray.length > 1) { | |
338 | + keyArray[1] = keyArray[1] + LWM2M_SEPARATOR_KEY + ver; | |
339 | + return StringUtils.join(keyArray, LWM2M_SEPARATOR_PATH); | |
340 | + } else { | |
341 | + return path; | |
342 | + } | |
343 | + } catch (Exception e) { | |
344 | + return null; | |
345 | + } | |
346 | + } | |
347 | + | |
348 | + public static Integer validateObjectIdFromKey(String key) { | |
349 | + try { | |
350 | + return Integer.parseInt(key.split(LWM2M_SEPARATOR_PATH)[1].split(LWM2M_SEPARATOR_KEY)[0]); | |
351 | + } catch (Exception e) { | |
352 | + return null; | |
353 | + } | |
354 | + } | |
355 | + | |
356 | + public static String validateObjectVerFromKey(String key) { | |
357 | + try { | |
358 | + return (key.split(LWM2M_SEPARATOR_PATH)[1].split(LWM2M_SEPARATOR_KEY)[1]); | |
359 | + } catch (Exception e) { | |
360 | + return ObjectModel.DEFAULT_VERSION; | |
361 | + } | |
362 | + } | |
349 | 363 | } | ... | ... |
... | ... | @@ -72,6 +72,8 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandle |
72 | 72 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES; |
73 | 73 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE; |
74 | 74 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.RESPONSE_CHANNEL; |
75 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId; | |
76 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer; | |
75 | 77 | |
76 | 78 | @Slf4j |
77 | 79 | @Service |
... | ... | @@ -114,7 +116,7 @@ public class LwM2mTransportRequest { |
114 | 116 | */ |
115 | 117 | public void sendAllRequest(Registration registration, String target, String typeOper, |
116 | 118 | String contentFormatParam, Observation observation, Object params, long timeoutInMs) { |
117 | - LwM2mPath resultIds = new LwM2mPath(target); | |
119 | + LwM2mPath resultIds = new LwM2mPath(convertToObjectIdFromIdVer(target)); | |
118 | 120 | if (registration != null && resultIds.getObjectId() >= 0) { |
119 | 121 | DownlinkRequest request = null; |
120 | 122 | ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null; |
... | ... | @@ -229,9 +231,8 @@ public class LwM2mTransportRequest { |
229 | 231 | private void sendRequest(Registration registration, DownlinkRequest request, long timeoutInMs) { |
230 | 232 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); |
231 | 233 | leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { |
232 | - | |
233 | 234 | if (!lwM2MClient.isInit()) { |
234 | - lwM2MClient.initValue(this.serviceImpl, request.getPath().toString()); | |
235 | + lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration)); | |
235 | 236 | } |
236 | 237 | if (isSuccess(((Response) response.getCoapResponse()).getCode())) { |
237 | 238 | this.handleResponse(registration, request.getPath().toString(), response, request); |
... | ... | @@ -251,7 +252,7 @@ public class LwM2mTransportRequest { |
251 | 252 | } |
252 | 253 | }, e -> { |
253 | 254 | if (!lwM2MClient.isInit()) { |
254 | - lwM2MClient.initValue(this.serviceImpl, request.getPath().toString()); | |
255 | + lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration)); | |
255 | 256 | } |
256 | 257 | String msg = String.format("%s: sendRequest: Resource path - %s msg error - %s SendRequest to Client", |
257 | 258 | LOG_LW2M_ERROR, request.getPath().toString(), e.toString()); |
... | ... | @@ -310,21 +311,22 @@ public class LwM2mTransportRequest { |
310 | 311 | * @param response - |
311 | 312 | */ |
312 | 313 | private void sendResponse(Registration registration, String path, LwM2mResponse response, DownlinkRequest request) { |
314 | + String pathIdVer = convertToIdVerFromObjectId(path, registration); | |
313 | 315 | if (response instanceof ReadResponse) { |
314 | - serviceImpl.onObservationResponse(registration, path, (ReadResponse) response); | |
316 | + serviceImpl.onObservationResponse(registration, pathIdVer, (ReadResponse) response); | |
315 | 317 | } else if (response instanceof CancelObservationResponse) { |
316 | - log.info("[{}] Path [{}] CancelObservationResponse 3_Send", path, response); | |
318 | + log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response); | |
317 | 319 | } else if (response instanceof DeleteResponse) { |
318 | - log.info("[{}] Path [{}] DeleteResponse 5_Send", path, response); | |
320 | + log.info("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response); | |
319 | 321 | } else if (response instanceof DiscoverResponse) { |
320 | - log.info("[{}] Path [{}] DiscoverResponse 6_Send", path, response); | |
322 | + log.info("[{}] Path [{}] DiscoverResponse 6_Send", pathIdVer, response); | |
321 | 323 | } else if (response instanceof ExecuteResponse) { |
322 | - log.info("[{}] Path [{}] ExecuteResponse 7_Send", path, response); | |
324 | + log.info("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response); | |
323 | 325 | } else if (response instanceof WriteAttributesResponse) { |
324 | - log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", path, response); | |
326 | + log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); | |
325 | 327 | } else if (response instanceof WriteResponse) { |
326 | - log.info("[{}] Path [{}] WriteAttributesResponse 9_Send", path, response); | |
327 | - serviceImpl.onWriteResponseOk(registration, path, (WriteRequest) request); | |
328 | + log.info("[{}] Path [{}] WriteAttributesResponse 9_Send", pathIdVer, response); | |
329 | + serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request); | |
328 | 330 | } |
329 | 331 | } |
330 | 332 | } | ... | ... |
... | ... | @@ -88,10 +88,15 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandle |
88 | 88 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; |
89 | 89 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; |
90 | 90 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; |
91 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LWM2M_STRATEGY_2; | |
91 | 92 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_EXECUTE; |
92 | 93 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_WRITE_REPLACE; |
93 | 94 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVICE_CHANNEL; |
95 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId; | |
96 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer; | |
94 | 97 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getAckCallback; |
98 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.validateObjectIdFromKey; | |
99 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.validateObjectVerFromKey; | |
95 | 100 | |
96 | 101 | @Slf4j |
97 | 102 | @Service |
... | ... | @@ -290,19 +295,19 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
290 | 295 | if (msg.getSharedUpdatedCount() > 0) { |
291 | 296 | JsonElement el = JsonConverter.toJson(msg); |
292 | 297 | el.getAsJsonObject().entrySet().forEach(de -> { |
293 | - String path = this.getPathAttributeUpdate(sessionInfo, de.getKey()); | |
298 | + String pathIdVer = this.getPathAttributeUpdate(sessionInfo, de.getKey()); | |
294 | 299 | String value = de.getValue().getAsString(); |
295 | 300 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); |
296 | 301 | LwM2mClientProfile clientProfile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); |
297 | - if (path != null && !path.isEmpty() && (this.validatePathInAttrProfile(clientProfile, path) || this.validatePathInTelemetryProfile(clientProfile, path))) { | |
298 | - ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(path)); | |
302 | + if (pathIdVer != null && !pathIdVer.isEmpty() && (this.validatePathInAttrProfile(clientProfile, pathIdVer) || this.validatePathInTelemetryProfile(clientProfile, pathIdVer))) { | |
303 | + ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(convertToObjectIdFromIdVer(pathIdVer))); | |
299 | 304 | if (resourceModel != null && resourceModel.operations.isWritable()) { |
300 | - lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, | |
305 | + lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), pathIdVer, POST_TYPE_OPER_WRITE_REPLACE, | |
301 | 306 | ContentFormat.TLV.getName(), null, value, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout()); |
302 | 307 | } else { |
303 | - log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value); | |
308 | + log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, value); | |
304 | 309 | String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", |
305 | - LOG_LW2M_ERROR, path, value); | |
310 | + LOG_LW2M_ERROR, pathIdVer, value); | |
306 | 311 | this.sentLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); |
307 | 312 | } |
308 | 313 | } else { |
... | ... | @@ -348,7 +353,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
348 | 353 | |
349 | 354 | /** |
350 | 355 | * Trigger Server path = "/1/0/8" |
351 | - * | |
356 | + * <p> | |
352 | 357 | * Trigger bootStrap path = "/1/0/9" - have to implemented on client |
353 | 358 | */ |
354 | 359 | @Override |
... | ... | @@ -458,7 +463,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
458 | 463 | private void initLwM2mFromClientValue(Registration registration, LwM2mClient lwM2MClient) { |
459 | 464 | LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); |
460 | 465 | Set<String> clientObjects = this.getAllOjectsInClient(registration); |
461 | - if (clientObjects != null && !LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { | |
466 | + if (clientObjects != null && LWM2M_STRATEGY_2 == LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { | |
462 | 467 | // #2 |
463 | 468 | lwM2MClient.getPendingRequests().addAll(clientObjects); |
464 | 469 | clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, GET_TYPE_OPER_READ, ContentFormat.TLV.getName(), |
... | ... | @@ -499,9 +504,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
499 | 504 | * #1 Return old Value Resource from LwM2MClient |
500 | 505 | * #2 Update new Resources (replace old Resource Value on new Resource Value) |
501 | 506 | * |
502 | - * @param registration - Registration LwM2M Client | |
507 | + * @param registration - Registration LwM2M Client | |
503 | 508 | * @param lwM2mResource - LwM2mSingleResource response.getContent() |
504 | - * @param path - resource | |
509 | + * @param path - resource | |
505 | 510 | */ |
506 | 511 | private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { |
507 | 512 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); |
... | ... | @@ -539,7 +544,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
539 | 544 | |
540 | 545 | /** |
541 | 546 | * @param clientProfile - |
542 | - * @param path - | |
547 | + * @param path - | |
543 | 548 | * @return true if path isPresent in postAttributeProfile |
544 | 549 | */ |
545 | 550 | private boolean validatePathInAttrProfile(LwM2mClientProfile clientProfile, String path) { |
... | ... | @@ -555,7 +560,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
555 | 560 | |
556 | 561 | /** |
557 | 562 | * @param clientProfile - |
558 | - * @param path - | |
563 | + * @param path - | |
559 | 564 | * @return true if path isPresent in postAttributeProfile |
560 | 565 | */ |
561 | 566 | private boolean validatePathInTelemetryProfile(LwM2mClientProfile clientProfile, String path) { |
... | ... | @@ -581,10 +586,13 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
581 | 586 | Set<String> clientInstances = this.getAllInstancesInClient(registration); |
582 | 587 | Set<String> result; |
583 | 588 | if (GET_TYPE_OPER_READ.equals(typeOper)) { |
584 | - result = JacksonUtil.fromString(lwM2MClientProfile.getPostAttributeProfile().toString(), new TypeReference<>() {}); | |
585 | - result.addAll(JacksonUtil.fromString(lwM2MClientProfile.getPostTelemetryProfile().toString(), new TypeReference<>() {})); | |
589 | + result = JacksonUtil.fromString(lwM2MClientProfile.getPostAttributeProfile().toString(), new TypeReference<>() { | |
590 | + }); | |
591 | + result.addAll(JacksonUtil.fromString(lwM2MClientProfile.getPostTelemetryProfile().toString(), new TypeReference<>() { | |
592 | + })); | |
586 | 593 | } else { |
587 | - result = JacksonUtil.fromString(lwM2MClientProfile.getPostObserveProfile().toString(), new TypeReference<>() {}); | |
594 | + result = JacksonUtil.fromString(lwM2MClientProfile.getPostObserveProfile().toString(), new TypeReference<>() { | |
595 | + }); | |
588 | 596 | } |
589 | 597 | Set<String> pathSent = ConcurrentHashMap.newKeySet(); |
590 | 598 | result.forEach(target -> { |
... | ... | @@ -646,7 +654,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
646 | 654 | Arrays.stream(registration.getObjectLinks()).forEach(url -> { |
647 | 655 | LwM2mPath pathIds = new LwM2mPath(url.getUrl()); |
648 | 656 | if (pathIds.isObjectInstance()) { |
649 | - clientInstances.add(url.getUrl()); | |
657 | + clientInstances.add(convertToIdVerFromObjectId(url.getUrl(), registration)); | |
650 | 658 | } |
651 | 659 | }); |
652 | 660 | return (clientInstances.size() > 0) ? clientInstances : null; |
... | ... | @@ -656,26 +664,22 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
656 | 664 | * @param attributes - new JsonObject |
657 | 665 | * @param telemetry - new JsonObject |
658 | 666 | * @param registration - Registration LwM2M Client |
659 | - * @param path - | |
667 | + * @param path - | |
660 | 668 | */ |
661 | 669 | private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) { |
662 | - LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); | |
663 | - lwM2MClientProfile.getPostAttributeProfile().forEach(p -> { | |
664 | - LwM2mPath pathIds = new LwM2mPath(p.getAsString()); | |
665 | - if (pathIds.isResource()) { | |
666 | - if (path == null || path.contains(p.getAsString())) { | |
667 | - this.addParameters(p.getAsString(), attributes, registration); | |
670 | + if (path != null && path.size() > 0) { | |
671 | + LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); | |
672 | + lwM2MClientProfile.getPostAttributeProfile().forEach(idVer -> { | |
673 | + if (path.contains(idVer.getAsString())) { | |
674 | + this.addParameters(idVer.getAsString(), attributes, registration); | |
668 | 675 | } |
669 | - } | |
670 | - }); | |
671 | - lwM2MClientProfile.getPostTelemetryProfile().forEach(p -> { | |
672 | - LwM2mPath pathIds = new LwM2mPath(p.getAsString()); | |
673 | - if (pathIds.isResource()) { | |
674 | - if (path == null || path.contains(p.getAsString())) { | |
675 | - this.addParameters(p.getAsString(), telemetry, registration); | |
676 | + }); | |
677 | + lwM2MClientProfile.getPostTelemetryProfile().forEach(idVer -> { | |
678 | + if (path.contains(idVer.getAsString())) { | |
679 | + this.addParameters(idVer.getAsString(), telemetry, registration); | |
676 | 680 | } |
677 | - } | |
678 | - }); | |
681 | + }); | |
682 | + } | |
679 | 683 | } |
680 | 684 | |
681 | 685 | /** |
... | ... | @@ -703,22 +707,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
703 | 707 | * @return - value of Resource or null |
704 | 708 | */ |
705 | 709 | private String getResourceValueToString(LwM2mClient lwM2MClient, String path) { |
706 | - LwM2mPath pathIds = new LwM2mPath(path); | |
707 | - ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, pathIds); | |
710 | + LwM2mPath pathIds =new LwM2mPath(convertToObjectIdFromIdVer(path)); | |
711 | + ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path); | |
708 | 712 | return resourceValue == null ? null : |
709 | 713 | this.converter.convertValue(resourceValue.getResourceValue(), this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds).toString(); |
710 | 714 | } |
711 | 715 | |
712 | 716 | /** |
713 | - * | |
714 | 717 | * @param lwM2MClient - |
715 | - * @param pathIds - | |
718 | + * @param path - | |
716 | 719 | * @return - return value of Resource by idPath |
717 | 720 | */ |
718 | - private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, LwM2mPath pathIds) { | |
721 | + private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) { | |
719 | 722 | ResourceValue resourceValue = null; |
720 | - if (pathIds.isResource()) { | |
721 | - resourceValue = lwM2MClient.getResources().get(pathIds.toString()); | |
723 | + if (new LwM2mPath(convertToObjectIdFromIdVer(path)).isResource()) { | |
724 | + resourceValue = lwM2MClient.getResources().get(path); | |
722 | 725 | } |
723 | 726 | return resourceValue; |
724 | 727 | } |
... | ... | @@ -818,8 +821,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
818 | 821 | |
819 | 822 | // #5.1 |
820 | 823 | if (!observeOld.equals(observeNew)) { |
821 | - Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<>() {}.getType()); | |
822 | - Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<>() {}.getType()); | |
824 | + Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<>() { | |
825 | + }.getType()); | |
826 | + Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<>() { | |
827 | + }.getType()); | |
823 | 828 | //#5.2 add |
824 | 829 | // path Attr/Telemetry includes newObserve |
825 | 830 | attributeSetOld.addAll(telemetrySetOld); |
... | ... | @@ -840,7 +845,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
840 | 845 | } |
841 | 846 | } |
842 | 847 | |
843 | - private Set <String> convertJsonArrayToSet (JsonArray jsonArray) { | |
848 | + private Set<String> convertJsonArrayToSet(JsonArray jsonArray) { | |
844 | 849 | List<String> attributeListOld = new Gson().fromJson(jsonArray, new TypeToken<>() { |
845 | 850 | }.getType()); |
846 | 851 | return Sets.newConcurrentHashSet(attributeListOld); |
... | ... | @@ -907,7 +912,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
907 | 912 | private void cancelObserveIsValue(Registration registration, Set<String> paramAnallyzer) { |
908 | 913 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); |
909 | 914 | paramAnallyzer.forEach(p -> { |
910 | - if (this.returnResourceValueFromLwM2MClient(lwM2MClient, new LwM2mPath(p)) != null) { | |
915 | + if (this.returnResourceValueFromLwM2MClient(lwM2MClient, p) != null) { | |
911 | 916 | this.setCancelObservationRecourse(registration, p); |
912 | 917 | } |
913 | 918 | } |
... | ... | @@ -953,8 +958,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
953 | 958 | */ |
954 | 959 | private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { |
955 | 960 | LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); |
961 | + Registration registration = lwM2mClientContext.getLwM2MClient(sessionInfo).getRegistration(); | |
956 | 962 | return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() |
957 | - .filter(e -> e.getValue().getAsString().equals(name)).findFirst().map(Map.Entry::getKey) | |
963 | + .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModelByVer(registration, e.getKey())).findFirst().map(Map.Entry::getKey) | |
958 | 964 | .orElse(""); |
959 | 965 | } |
960 | 966 | |
... | ... | @@ -974,12 +980,14 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
974 | 980 | try { |
975 | 981 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2MClient(sessionInfo); |
976 | 982 | attributesResponse.getSharedAttributeListList().forEach(attr -> { |
977 | - String path = this.getPathAttributeUpdate(sessionInfo, attr.getKv().getKey()); | |
978 | - // #1.1 | |
979 | - if (lwM2MClient.getDelayedRequests().containsKey(path) && attr.getTs() > lwM2MClient.getDelayedRequests().get(path).getTs()) { | |
980 | - lwM2MClient.getDelayedRequests().put(path, attr); | |
981 | - } else { | |
982 | - lwM2MClient.getDelayedRequests().put(path, attr); | |
983 | + String path =this.getPathAttributeUpdate(sessionInfo, attr.getKv().getKey()); | |
984 | + if (path != null) { | |
985 | + // #1.1 | |
986 | + if (lwM2MClient.getDelayedRequests().containsKey(path) && attr.getTs() > lwM2MClient.getDelayedRequests().get(path).getTs()) { | |
987 | + lwM2MClient.getDelayedRequests().put(path, attr); | |
988 | + } else { | |
989 | + lwM2MClient.getDelayedRequests().put(path, attr); | |
990 | + } | |
983 | 991 | } |
984 | 992 | }); |
985 | 993 | // #2.1 |
... | ... | @@ -1057,6 +1065,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1057 | 1065 | } |
1058 | 1066 | |
1059 | 1067 | /** |
1068 | + * !!! sharedAttr === profileAttr !!! | |
1060 | 1069 | * If there is a difference in values between the current resource values and the shared attribute values |
1061 | 1070 | * when the client connects to the server |
1062 | 1071 | * #1 get attributes name from profile include name resources in ModelObject if resource isWritable |
... | ... | @@ -1083,24 +1092,42 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1083 | 1092 | |
1084 | 1093 | |
1085 | 1094 | /** |
1086 | - * Get names and keyNames from profile shared!!!! attr resources IsWritable | |
1095 | + * !!! sharedAttr === profileAttr !!! | |
1096 | + * Get names or keyNames from profile: resources IsWritable | |
1087 | 1097 | * |
1088 | 1098 | * @param lwM2MClient - |
1089 | - * @return ArrayList keyNames from profile attr resources shared!!!! && IsWritable | |
1099 | + * @return ArrayList keyNames from profile profileAttr && IsWritable | |
1090 | 1100 | */ |
1091 | 1101 | private List<String> getNamesAttrFromProfileIsWritable(LwM2mClient lwM2MClient) { |
1092 | 1102 | LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId()); |
1093 | - Set<String> attrSet = new Gson().fromJson(profile.getPostAttributeProfile(), new TypeToken<>() {}.getType()); | |
1094 | - ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), new TypeToken<ConcurrentHashMap<String, String>>() {}.getType()); | |
1103 | + Set<String> attrSet = new Gson().fromJson(profile.getPostAttributeProfile(), | |
1104 | + new TypeToken<HashSet<String>>() { | |
1105 | + }.getType()); | |
1106 | + ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), | |
1107 | + new TypeToken<ConcurrentHashMap<String, String>>() { | |
1108 | + }.getType()); | |
1095 | 1109 | |
1096 | 1110 | ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet() |
1097 | 1111 | .stream() |
1098 | - .filter(e -> (attrSet.contains(e.getKey()) && lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())) != null && | |
1099 | - lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())).operations.isWritable())) | |
1112 | + .filter(e -> (attrSet.contains(e.getKey()) && resourceIsWritable(lwM2MClient.getRegistration(), e.getKey()))) | |
1100 | 1113 | .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue)); |
1101 | 1114 | |
1102 | 1115 | Set<String> namesIsWritable = ConcurrentHashMap.newKeySet(); |
1103 | 1116 | namesIsWritable.addAll(new HashSet<>(keyNamesIsWritable.values())); |
1104 | 1117 | return new ArrayList<>(namesIsWritable); |
1105 | 1118 | } |
1119 | + | |
1120 | + private boolean resourceIsWritable(Registration registration, String pathKey) { | |
1121 | + return validateResourceInModelByVer(registration, pathKey) && | |
1122 | + lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration, | |
1123 | + new LwM2mPath(convertToObjectIdFromIdVer(pathKey))).operations.isWritable(); | |
1124 | + } | |
1125 | + | |
1126 | + private boolean validateResourceInModelByVer(Registration registration, String pathKey) { | |
1127 | + Integer objectId = validateObjectIdFromKey(pathKey); | |
1128 | + String objectVer = validateObjectVerFromKey(pathKey); | |
1129 | + LwM2mPath lwM2mPath = new LwM2mPath(convertToObjectIdFromIdVer(pathKey)); | |
1130 | + return objectId != null && objectVer != null && objectVer.equals(registration.getSupportedVersion(objectId)) && | |
1131 | + lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration, lwM2mPath) != null; | |
1132 | + } | |
1106 | 1133 | } | ... | ... |
... | ... | @@ -32,6 +32,7 @@ import java.util.Iterator; |
32 | 32 | import java.util.Map; |
33 | 33 | |
34 | 34 | import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL; |
35 | +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; | |
35 | 36 | |
36 | 37 | @Slf4j |
37 | 38 | public class LwM2mVersionedModelProvider implements LwM2mModelProvider { |
... | ... | @@ -49,12 +50,9 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { |
49 | 50 | this.lwM2mClientContext = lwM2mClientContext; |
50 | 51 | this.lwM2mTransportContextServer = lwM2mTransportContextServer; |
51 | 52 | } |
52 | - private String getIdVer(ObjectModel objectModel) { | |
53 | - return objectModel.id + "##" + ((objectModel.getVersion() == null || objectModel.getVersion().isEmpty()) ? ObjectModel.DEFAULT_VERSION : objectModel.getVersion()); | |
54 | - } | |
55 | 53 | |
56 | - private String getIdVer(Integer objectId, String version) { | |
57 | - return objectId != null ? objectId + "##" + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null; | |
54 | + private String getKeyIdVer(Integer objectId, String version) { | |
55 | + return objectId != null ? objectId + LWM2M_SEPARATOR_KEY + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null; | |
58 | 56 | } |
59 | 57 | |
60 | 58 | /** |
... | ... | @@ -65,8 +63,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { |
65 | 63 | */ |
66 | 64 | @Override |
67 | 65 | public LwM2mModel getObjectModel(Registration registration) { |
68 | - return new DynamicModel(registration | |
69 | - ); | |
66 | + return new DynamicModel(registration); | |
70 | 67 | } |
71 | 68 | |
72 | 69 | private class DynamicModel implements LwM2mModel { |
... | ... | @@ -107,7 +104,6 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { |
107 | 104 | Map<Integer, String> supportedObjects = this.registration.getSupportedObject(); |
108 | 105 | Collection<ObjectModel> result = new ArrayList<>(supportedObjects.size()); |
109 | 106 | Iterator<Map.Entry<Integer, String>> i$ = supportedObjects.entrySet().iterator(); |
110 | - | |
111 | 107 | while (i$.hasNext()) { |
112 | 108 | Map.Entry<Integer, String> supportedObject = i$.next(); |
113 | 109 | ObjectModel objectModel = this.getObjectModelDynamic(supportedObject.getKey(), supportedObject.getValue()); |
... | ... | @@ -119,7 +115,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { |
119 | 115 | } |
120 | 116 | |
121 | 117 | private ObjectModel getObjectModelDynamic(Integer objectId, String version) { |
122 | - String key = getIdVer(objectId, version); | |
118 | + String key = getKeyIdVer(objectId, version); | |
123 | 119 | String xmlB64 = lwM2mTransportContextServer.getTransportResourceCache().get( |
124 | 120 | this.tenantId, |
125 | 121 | LWM2M_MODEL, | ... | ... |
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/LwM2mInMemorySecurityStore.java
deleted
100644 → 0
1 | -/** | |
2 | - * Copyright © 2016-2021 The Thingsboard Authors | |
3 | - * | |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | - * you may not use this file except in compliance with the License. | |
6 | - * You may obtain a copy of the License at | |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
10 | - * Unless required by applicable law or agreed to in writing, software | |
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | - * See the License for the specific language governing permissions and | |
14 | - * limitations under the License. | |
15 | - */ | |
16 | -package org.thingsboard.server.transport.lwm2m.server.store; | |
17 | - | |
18 | -import lombok.extern.slf4j.Slf4j; | |
19 | -import org.eclipse.leshan.core.util.Hex; | |
20 | -import org.eclipse.leshan.server.registration.Registration; | |
21 | -import org.eclipse.leshan.server.security.InMemorySecurityStore; | |
22 | -import org.eclipse.leshan.server.security.SecurityInfo; | |
23 | -import org.eclipse.leshan.server.security.SecurityStoreListener; | |
24 | -import org.springframework.beans.factory.annotation.Autowired; | |
25 | -import org.thingsboard.server.common.data.DeviceProfile; | |
26 | -import org.thingsboard.server.gen.transport.TransportProtos; | |
27 | -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | |
28 | -import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; | |
29 | -import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; | |
30 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | |
31 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | |
32 | -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; | |
33 | -import org.thingsboard.server.transport.lwm2m.utils.TypeServer; | |
34 | - | |
35 | -import java.util.Collection; | |
36 | -import java.util.List; | |
37 | -import java.util.Map; | |
38 | -import java.util.UUID; | |
39 | -import java.util.concurrent.ConcurrentHashMap; | |
40 | -import java.util.concurrent.locks.Lock; | |
41 | -import java.util.concurrent.locks.ReadWriteLock; | |
42 | -import java.util.concurrent.locks.ReentrantReadWriteLock; | |
43 | -import java.util.stream.Collectors; | |
44 | - | |
45 | -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; | |
46 | - | |
47 | -@Slf4j | |
48 | -//@Service("LwM2mInMemorySecurityStore") | |
49 | -//@TbLwM2mTransportComponent | |
50 | -@Deprecated | |
51 | -public class LwM2mInMemorySecurityStore extends InMemorySecurityStore { | |
52 | - private static final boolean INFOS_ARE_COMPROMISED = false; | |
53 | - | |
54 | - // lock for the two maps | |
55 | - private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); | |
56 | - private final Lock readLock = readWriteLock.readLock(); | |
57 | - private final Lock writeLock = readWriteLock.writeLock(); | |
58 | - private final Map<String /** registrationId */, LwM2mClient> sessions = new ConcurrentHashMap<>(); | |
59 | - private Map<UUID /** profileUUid */, LwM2mClientProfile> profiles = new ConcurrentHashMap<>(); | |
60 | - private SecurityStoreListener listener; | |
61 | - | |
62 | - @Autowired | |
63 | - LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator; | |
64 | - | |
65 | - /** | |
66 | - * Start after DefaultAuthorizer or LwM2mPskStore | |
67 | - * @param endPoint - | |
68 | - * @return SecurityInfo | |
69 | - */ | |
70 | - @Override | |
71 | - public SecurityInfo getByEndpoint(String endPoint) { | |
72 | - readLock.lock(); | |
73 | - try { | |
74 | - String registrationId = this.getRegistrationId(endPoint, null); | |
75 | - return (registrationId != null && sessions.size() > 0 && sessions.get(registrationId) != null) ? | |
76 | - sessions.get(registrationId).getSecurityInfo() : this.addLwM2MClientToSession(endPoint); | |
77 | - } finally { | |
78 | - readLock.unlock(); | |
79 | - } | |
80 | - } | |
81 | - | |
82 | - /** | |
83 | - * Start after LwM2mPskStore | |
84 | - * @param identity - | |
85 | - * @return SecurityInfo | |
86 | - */ | |
87 | - @Override | |
88 | - public SecurityInfo getByIdentity(String identity) { | |
89 | - readLock.lock(); | |
90 | - try { | |
91 | - String integrationId = this.getRegistrationId(null, identity); | |
92 | - return (integrationId != null) ? sessions.get(integrationId).getSecurityInfo() : this.addLwM2MClientToSession(identity); | |
93 | - } finally { | |
94 | - readLock.unlock(); | |
95 | - } | |
96 | - } | |
97 | - | |
98 | - @Override | |
99 | - public Collection<SecurityInfo> getAll() { | |
100 | - readLock.lock(); | |
101 | - try { | |
102 | - return this.sessions.values().stream().map(LwM2mClient::getSecurityInfo).collect(Collectors.toUnmodifiableList()); | |
103 | - } finally { | |
104 | - readLock.unlock(); | |
105 | - } | |
106 | - } | |
107 | - | |
108 | - /** | |
109 | - * Removed registration Client from sessions and listener | |
110 | - * @param registrationId if Client | |
111 | - */ | |
112 | - public void delRemoveSessionAndListener(String registrationId) { | |
113 | - writeLock.lock(); | |
114 | - try { | |
115 | - LwM2mClient lwM2MClient = (sessions.get(registrationId) != null) ? sessions.get(registrationId) : null; | |
116 | - if (lwM2MClient != null) { | |
117 | - if (listener != null) { | |
118 | - listener.securityInfoRemoved(INFOS_ARE_COMPROMISED, lwM2MClient.getSecurityInfo()); | |
119 | - } | |
120 | - sessions.remove(registrationId); | |
121 | - } | |
122 | - } finally { | |
123 | - writeLock.unlock(); | |
124 | - } | |
125 | - } | |
126 | - | |
127 | - @Override | |
128 | - public void setListener(SecurityStoreListener listener) { | |
129 | - this.listener = listener; | |
130 | - } | |
131 | - | |
132 | - public LwM2mClient getLwM2MClient(String endPoint, String identity) { | |
133 | - Map.Entry<String, LwM2mClient> modelClients = endPoint != null ? | |
134 | - this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).findAny().orElse(null) : | |
135 | - this.sessions.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).findAny().orElse(null); | |
136 | - return modelClients != null ? modelClients.getValue() : null; | |
137 | - } | |
138 | - | |
139 | - public LwM2mClient getLwM2MClientWithReg(Registration registration, String registrationId) { | |
140 | - return registrationId != null ? | |
141 | - this.sessions.get(registrationId) : | |
142 | - this.sessions.containsKey(registration.getId()) ? | |
143 | - this.sessions.get(registration.getId()) : | |
144 | - this.sessions.get(registration.getEndpoint()); | |
145 | - } | |
146 | - | |
147 | - public LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) { | |
148 | - return this.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue(); | |
149 | - } | |
150 | - | |
151 | - /** | |
152 | - * Update in sessions (LwM2MClient for key registration_Id) after starting registration LwM2MClient in LwM2MTransportServiceImpl | |
153 | - * Remove from sessions LwM2MClient with key registration_Endpoint | |
154 | - * @param registration - | |
155 | - * @return LwM2MClient after adding it to session | |
156 | - */ | |
157 | - public LwM2mClient updateInSessionsLwM2MClient(Registration registration) { | |
158 | - writeLock.lock(); | |
159 | - try { | |
160 | - if (this.sessions.get(registration.getEndpoint()) == null) { | |
161 | - this.addLwM2MClientToSession(registration.getEndpoint()); | |
162 | - } | |
163 | - LwM2mClient lwM2MClient = this.sessions.get(registration.getEndpoint()); | |
164 | - lwM2MClient.setRegistration(registration); | |
165 | -// lwM2MClient.getAttributes().putAll(registration.getAdditionalRegistrationAttributes()); | |
166 | - this.sessions.remove(registration.getEndpoint()); | |
167 | - this.sessions.put(registration.getId(), lwM2MClient); | |
168 | - return lwM2MClient; | |
169 | - } finally { | |
170 | - writeLock.unlock(); | |
171 | - } | |
172 | - } | |
173 | - | |
174 | - private String getRegistrationId(String endPoint, String identity) { | |
175 | - List<String> registrationIds = (endPoint != null) ? | |
176 | - this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).map(Map.Entry::getKey).collect(Collectors.toList()) : | |
177 | - this.sessions.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).map(Map.Entry::getKey).collect(Collectors.toList()); | |
178 | - return (registrationIds != null && registrationIds.size() > 0) ? registrationIds.get(0) : null; | |
179 | - } | |
180 | - | |
181 | - public Registration getByRegistration(String registrationId) { | |
182 | - return this.sessions.get(registrationId).getRegistration(); | |
183 | - } | |
184 | - | |
185 | - /** | |
186 | - * Add new LwM2MClient to session | |
187 | - * @param identity- | |
188 | - * @return SecurityInfo. If error - SecurityInfoError | |
189 | - * and log: | |
190 | - * - FORBIDDEN - if there is no authorization | |
191 | - * - profileUuid - if the device does not have a profile | |
192 | - * - device - if the thingsboard does not have a device with a name equal to the identity | |
193 | - */ | |
194 | - private SecurityInfo addLwM2MClientToSession(String identity) { | |
195 | - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, TypeServer.CLIENT); | |
196 | - if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { | |
197 | - UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null; | |
198 | - if (store.getSecurityInfo() != null && profileUuid != null) { | |
199 | - String endpoint = store.getSecurityInfo().getEndpoint(); | |
200 | - sessions.put(endpoint, new LwM2mClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID())); | |
201 | - } else if (store.getSecurityMode() == NO_SEC.code && profileUuid != null) { | |
202 | - sessions.put(identity, new LwM2mClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID())); | |
203 | - } else { | |
204 | - log.error("Registration failed: FORBIDDEN/profileUuid/device [{}] , endpointId: [{}]", profileUuid, identity); | |
205 | - /** | |
206 | - * Return Error securityInfo | |
207 | - */ | |
208 | - byte[] preSharedKey = Hex.decodeHex("0A0B".toCharArray()); | |
209 | - SecurityInfo infoError = SecurityInfo.newPreSharedKeyInfo("error", "error_identity", preSharedKey); | |
210 | - return infoError; | |
211 | - } | |
212 | - } | |
213 | - return store.getSecurityInfo(); | |
214 | - } | |
215 | - | |
216 | - public Map<String, LwM2mClient> getSession(UUID sessionUuId) { | |
217 | - return this.sessions.entrySet().stream() | |
218 | - .filter(e -> e.getValue().getSessionId().equals(sessionUuId)) | |
219 | - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | |
220 | - } | |
221 | - | |
222 | - public Map<String, LwM2mClient> getSessions() { | |
223 | - return this.sessions; | |
224 | - } | |
225 | - | |
226 | - public Map<UUID, LwM2mClientProfile> getProfiles() { | |
227 | - return this.profiles; | |
228 | - } | |
229 | - | |
230 | - public LwM2mClientProfile getProfile(UUID profileUuId) { | |
231 | - return this.profiles.get(profileUuId); | |
232 | - } | |
233 | - | |
234 | - public LwM2mClientProfile getProfile(String registrationId) { | |
235 | - UUID profileUUid = this.getSessions().get(registrationId).getProfileId(); | |
236 | - return this.getProfiles().get(profileUUid); | |
237 | - } | |
238 | - | |
239 | - public Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles) { | |
240 | - return this.profiles = profiles; | |
241 | - } | |
242 | - | |
243 | - public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) { | |
244 | - LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile); | |
245 | - if (lwM2MClientProfile != null) { | |
246 | - profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); | |
247 | - return true; | |
248 | - } | |
249 | - return false; | |
250 | - } | |
251 | -} |
... | ... | @@ -29,6 +29,7 @@ import org.springframework.context.annotation.Lazy; |
29 | 29 | import org.springframework.stereotype.Service; |
30 | 30 | import org.thingsboard.server.cache.TBRedisCacheConfiguration; |
31 | 31 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
32 | +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; | |
32 | 33 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
33 | 34 | |
34 | 35 | import java.util.Collection; |
... | ... | @@ -89,10 +90,14 @@ public class TbLwM2mStoreConfiguration { |
89 | 90 | } |
90 | 91 | |
91 | 92 | @Override |
92 | - public SecurityInfo getByEndpoint(String endpoint) { | |
93 | - SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint); | |
93 | + public SecurityInfo getByEndpoint(String endPoint) { | |
94 | + SecurityInfo securityInfo = securityStore.getByEndpoint(endPoint); | |
94 | 95 | if (securityInfo == null) { |
95 | - securityInfo = clientContext.addLwM2mClientToSession(endpoint).getSecurityInfo(); | |
96 | + LwM2mClient lwM2mClient = clientContext.getLwM2MClient(endPoint, null); | |
97 | + if (lwM2mClient != null && !lwM2mClient.getRegistration().getIdentity().isSecure()){ | |
98 | + return null; | |
99 | + } | |
100 | + securityInfo = clientContext.addLwM2mClientToSession(endPoint).getSecurityInfo(); | |
96 | 101 | try { |
97 | 102 | if (securityInfo != null) { |
98 | 103 | add(securityInfo); | ... | ... |
... | ... | @@ -466,7 +466,6 @@ public class ModelConstants { |
466 | 466 | public static final String RESOURCE_TITLE_COLUMN = TITLE_PROPERTY; |
467 | 467 | public static final String RESOURCE_DATA_COLUMN = "data"; |
468 | 468 | |
469 | - | |
470 | 469 | /** |
471 | 470 | * Cassandra attributes and timeseries constants. |
472 | 471 | */ | ... | ... |
... | ... | @@ -65,7 +65,8 @@ public class TbResourceEntity extends BaseSqlEntity<TbResource> implements Searc |
65 | 65 | } |
66 | 66 | |
67 | 67 | public TbResourceEntity(TbResource resource) { |
68 | - this.setUuid(resource.getId().getId()); | |
68 | + this.id = resource.getUuidId(); | |
69 | + this.createdTime = resource.getCreatedTime(); | |
69 | 70 | this.tenantId = resource.getTenantId().getId(); |
70 | 71 | this.title = resource.getTitle(); |
71 | 72 | this.resourceType = resource.getResourceType().name(); | ... | ... |
... | ... | @@ -43,6 +43,8 @@ import java.util.Comparator; |
43 | 43 | import java.util.List; |
44 | 44 | import java.util.stream.Collectors; |
45 | 45 | |
46 | +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; | |
47 | +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_SEARCH_TEXT; | |
46 | 48 | import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID; |
47 | 49 | import static org.thingsboard.server.dao.service.Validator.validateId; |
48 | 50 | |
... | ... | @@ -62,26 +64,24 @@ public class BaseTbResourceService implements TbResourceService { |
62 | 64 | } |
63 | 65 | |
64 | 66 | @Override |
65 | - public TbResource saveResource(TbResource resource) throws InvalidDDFFileException, IOException { | |
66 | - log.trace("Executing saveResource [{}]", resource); | |
67 | - | |
68 | - if (resource.getId() == null && ResourceType.LWM2M_MODEL.equals(resource.getResourceType())) { | |
67 | + public TbResource saveResource(TbResource tbResource) throws InvalidDDFFileException, IOException { | |
68 | + log.trace("Executing saveResource [{}]", tbResource); | |
69 | + if (ResourceType.LWM2M_MODEL.equals(tbResource.getResourceType())) { | |
69 | 70 | List<ObjectModel> objectModels = |
70 | - ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getData())), resource.getSearchText()); | |
71 | + ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(tbResource.getData())), tbResource.getSearchText()); | |
71 | 72 | if (!objectModels.isEmpty()) { |
72 | 73 | ObjectModel objectModel = objectModels.get(0); |
73 | - | |
74 | - String resourceKey = objectModel.id + "_" + objectModel.getVersion(); | |
74 | + String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion(); | |
75 | 75 | String name = objectModel.name; |
76 | - resource.setResourceKey(resourceKey); | |
77 | - resource.setTitle(name); | |
78 | - resource.setSearchText(resourceKey + ":" + name); | |
76 | + tbResource.setResourceKey(resourceKey); | |
77 | + tbResource.setTitle(name); | |
78 | + tbResource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name); | |
79 | + } else { | |
80 | + throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", tbResource.getSearchText())); | |
79 | 81 | } |
80 | 82 | } |
81 | - | |
82 | - validate(resource); | |
83 | - | |
84 | - return resourceDao.saveResource(resource); | |
83 | + validate(tbResource); | |
84 | + return resourceDao.save(tbResource.getTenantId(), tbResource); | |
85 | 85 | } |
86 | 86 | |
87 | 87 | @Override |
... | ... | @@ -162,9 +162,6 @@ public class BaseTbResourceService implements TbResourceService { |
162 | 162 | throw new DataValidationException("Resource value should be specified!"); |
163 | 163 | } |
164 | 164 | validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceKey()); |
165 | - if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && this.toLwM2mObject(resource) == null) { | |
166 | - throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText())); | |
167 | - } | |
168 | 165 | } |
169 | 166 | |
170 | 167 | protected void validate(TenantId tenantId, ResourceType resourceType, String resourceId) { | ... | ... |
... | ... | @@ -26,8 +26,6 @@ import java.util.List; |
26 | 26 | |
27 | 27 | public interface TbResourceDao extends Dao<TbResource> { |
28 | 28 | |
29 | - TbResource saveResource(TbResource resource); | |
30 | - | |
31 | 29 | TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); |
32 | 30 | |
33 | 31 | PageData<TbResource> findAllByTenantId(TenantId tenantId, PageLink pageLink); | ... | ... |
... | ... | @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.resource; |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.springframework.data.repository.CrudRepository; |
20 | 20 | import org.springframework.stereotype.Component; |
21 | -import org.springframework.transaction.annotation.Transactional; | |
22 | 21 | import org.thingsboard.server.common.data.ResourceType; |
23 | 22 | import org.thingsboard.server.common.data.TbResource; |
24 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -54,12 +53,6 @@ public class JpaTbResourceDao extends JpaAbstractSearchTextDao<TbResourceEntity, |
54 | 53 | } |
55 | 54 | |
56 | 55 | @Override |
57 | - @Transactional | |
58 | - public TbResource saveResource(TbResource resource) { | |
59 | - return DaoUtil.getData(resourceRepository.save(new TbResourceEntity(resource))); | |
60 | - } | |
61 | - | |
62 | - @Override | |
63 | 56 | public TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceKey) { |
64 | 57 | |
65 | 58 | return DaoUtil.getData(resourceRepository.findByTenantIdAndResourceTypeAndResourceKey(tenantId.getId(), resourceType.name(), resourceKey)); | ... | ... |