Commit e96452cdcf527f6f4b624a8fa78b3086943d9191

Authored by Volodymyr Babak
2 parents aedebc32 3716e283

Merge remote-tracking branch 'upstream/develop/3.3' into develop/3.3-edge

Showing 82 changed files with 1999 additions and 495 deletions
... ... @@ -30,7 +30,8 @@ import java.util.Arrays;
30 30 "org.thingsboard.server.service.component",
31 31 "org.thingsboard.server.service.install",
32 32 "org.thingsboard.server.dao",
33   - "org.thingsboard.server.common.stats"})
  33 + "org.thingsboard.server.common.stats",
  34 + "org.thingsboard.server.cache"})
34 35 public class ThingsboardInstallApplication {
35 36
36 37 private static final String SPRING_CONFIG_NAME_KEY = "--spring.config.name";
... ...
... ... @@ -47,8 +47,7 @@ import org.thingsboard.server.common.data.id.EdgeId;
47 47 import org.thingsboard.server.common.data.id.TenantId;
48 48 import org.thingsboard.server.common.data.page.PageData;
49 49 import org.thingsboard.server.common.data.page.PageLink;
50   -import org.thingsboard.server.common.data.page.TimePageLink;
51   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  50 +import org.thingsboard.common.util.JacksonUtil;
52 51 import org.thingsboard.server.queue.util.TbCoreComponent;
53 52 import org.thingsboard.server.service.security.model.SecurityUser;
54 53 import org.thingsboard.server.service.security.permission.Operation;
... ...
... ... @@ -50,7 +50,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
50 50 import org.thingsboard.server.dao.device.provision.ProvisionRequest;
51 51 import org.thingsboard.server.dao.device.provision.ProvisionResponse;
52 52 import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus;
53   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  53 +import org.thingsboard.common.util.JacksonUtil;
54 54 import org.thingsboard.server.gen.transport.TransportProtos;
55 55 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
56 56 import org.thingsboard.server.queue.TbQueueCallback;
... ...
... ... @@ -41,7 +41,7 @@ import org.thingsboard.server.dao.entityview.EntityViewService;
41 41 import org.thingsboard.server.dao.rule.RuleChainService;
42 42 import org.thingsboard.server.dao.tenant.TenantService;
43 43 import org.thingsboard.server.dao.timeseries.TimeseriesService;
44   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  44 +import org.thingsboard.common.util.JacksonUtil;
45 45 import org.thingsboard.server.service.install.InstallScripts;
46 46
47 47 import java.util.ArrayList;
... ... @@ -51,7 +51,6 @@ import java.util.concurrent.ExecutionException;
51 51 import java.util.stream.Collectors;
52 52
53 53 import static org.apache.commons.lang3.StringUtils.isBlank;
54   -import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper;
55 54
56 55 @Service
57 56 @Profile("install")
... ...
... ... @@ -47,7 +47,7 @@ import org.thingsboard.server.dao.attributes.AttributesService;
47 47 import org.thingsboard.server.dao.entity.EntityService;
48 48 import org.thingsboard.server.dao.model.ModelConstants;
49 49 import org.thingsboard.server.dao.timeseries.TimeseriesService;
50   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  50 +import org.thingsboard.common.util.JacksonUtil;
51 51 import org.thingsboard.server.queue.util.TbCoreComponent;
52 52 import org.thingsboard.server.service.executors.DbCallbackExecutorService;
53 53 import org.thingsboard.server.service.security.AccessValidator;
... ...
... ... @@ -35,7 +35,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
35 35 import org.thingsboard.server.common.msg.queue.TbCallback;
36 36 import org.thingsboard.server.common.stats.StatsFactory;
37 37 import org.thingsboard.server.common.transport.util.DataDecodingEncodingService;
38   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  38 +import org.thingsboard.common.util.JacksonUtil;
39 39 import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto;
40 40 import org.thingsboard.server.gen.transport.TransportProtos.EdgeNotificationMsgProto;
41 41 import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto;
... ...
... ... @@ -49,7 +49,7 @@ import org.thingsboard.server.dao.exception.DataValidationException;
49 49 import org.thingsboard.server.dao.settings.AdminSettingsService;
50 50 import org.thingsboard.server.dao.user.UserService;
51 51 import org.thingsboard.server.dao.user.UserServiceImpl;
52   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  52 +import org.thingsboard.common.util.JacksonUtil;
53 53 import org.thingsboard.server.service.security.exception.UserPasswordExpiredException;
54 54 import org.thingsboard.server.utils.MiscUtils;
55 55
... ...
... ... @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException;
31 31 import org.thingsboard.server.common.data.id.EntityId;
32 32 import org.thingsboard.server.common.data.id.TenantId;
33 33 import org.thingsboard.server.dao.settings.AdminSettingsService;
34   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  34 +import org.thingsboard.common.util.JacksonUtil;
35 35 import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
36 36 import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
37 37
... ...
... ... @@ -52,7 +52,7 @@ import org.thingsboard.server.dao.attributes.AttributesService;
52 52 import org.thingsboard.server.dao.device.DeviceService;
53 53 import org.thingsboard.server.dao.tenant.TenantService;
54 54 import org.thingsboard.server.dao.timeseries.TimeseriesService;
55   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  55 +import org.thingsboard.common.util.JacksonUtil;
56 56 import org.thingsboard.server.gen.transport.TransportProtos;
57 57 import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
58 58 import org.thingsboard.server.queue.discovery.PartitionService;
... ...
... ... @@ -39,7 +39,7 @@ import org.thingsboard.server.common.msg.queue.TbCallback;
39 39 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
40 40 import org.thingsboard.server.dao.attributes.AttributesService;
41 41 import org.thingsboard.server.dao.timeseries.TimeseriesService;
42   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  42 +import org.thingsboard.common.util.JacksonUtil;
43 43 import org.thingsboard.server.gen.transport.TransportProtos.*;
44 44 import org.thingsboard.server.gen.transport.TransportProtos.LocalSubscriptionServiceMsgProto;
45 45 import org.thingsboard.server.gen.transport.TransportProtos.TbSubscriptionUpdateProto;
... ...
... ... @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.kv.KvEntry;
30 30 import org.thingsboard.server.common.data.kv.LongDataEntry;
31 31 import org.thingsboard.server.common.data.kv.StringDataEntry;
32 32 import org.thingsboard.server.common.data.kv.TsKvEntry;
33   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  33 +import org.thingsboard.common.util.JacksonUtil;
34 34 import org.thingsboard.server.gen.transport.TransportProtos;
35 35 import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto;
36 36 import org.thingsboard.server.gen.transport.TransportProtos.KeyValueType;
... ...
... ... @@ -54,7 +54,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionRequest;
54 54 import org.thingsboard.server.dao.device.provision.ProvisionResponse;
55 55 import org.thingsboard.server.dao.relation.RelationService;
56 56 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
57   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  57 +import org.thingsboard.common.util.JacksonUtil;
58 58 import org.thingsboard.server.gen.transport.TransportProtos;
59 59 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
60 60 import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg;
... ...
... ... @@ -643,8 +643,8 @@ transport:
643 643 public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
644 644 private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" # Only Certificate_x509:
645 645 alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}"
646   - # Redis
647   - redis_url: "${LWM2M_REDIS_URL:''}"
  646 + # Use redis for Security and Registration stores
  647 + redis.enabled: "${LWM2M_REDIS_ENABLED:false}"
648 648
649 649 # Edges parameters
650 650 edges:
... ...
... ... @@ -26,7 +26,7 @@ import org.junit.Before;
26 26 import org.junit.Test;
27 27 import org.thingsboard.server.common.data.Device;
28 28 import org.thingsboard.server.common.data.device.profile.MqttTopics;
29   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  29 +import org.thingsboard.common.util.JacksonUtil;
30 30 import org.thingsboard.server.mqtt.attributes.AbstractMqttAttributesIntegrationTest;
31 31
32 32 import java.nio.charset.StandardCharsets;
... ...
... ... @@ -25,7 +25,7 @@ import org.junit.Test;
25 25 import org.thingsboard.server.common.data.Device;
26 26 import org.thingsboard.server.common.data.TransportPayloadType;
27 27 import org.thingsboard.server.common.data.device.profile.MqttTopics;
28   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  28 +import org.thingsboard.common.util.JacksonUtil;
29 29 import org.thingsboard.server.mqtt.attributes.AbstractMqttAttributesIntegrationTest;
30 30
31 31 import java.nio.charset.StandardCharsets;
... ...
... ... @@ -37,7 +37,7 @@ import org.thingsboard.server.common.transport.util.JsonUtils;
37 37 import org.thingsboard.server.dao.device.DeviceCredentialsService;
38 38 import org.thingsboard.server.dao.device.DeviceService;
39 39 import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus;
40   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  40 +import org.thingsboard.common.util.JacksonUtil;
41 41 import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest;
42 42
43 43 import java.util.concurrent.CountDownLatch;
... ...
... ... @@ -36,7 +36,7 @@ import org.thingsboard.server.common.msg.EncryptionUtil;
36 36 import org.thingsboard.server.dao.device.DeviceCredentialsService;
37 37 import org.thingsboard.server.dao.device.DeviceService;
38 38 import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus;
39   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  39 +import org.thingsboard.common.util.JacksonUtil;
40 40 import org.thingsboard.server.gen.transport.TransportProtos.CredentialsDataProto;
41 41 import org.thingsboard.server.gen.transport.TransportProtos.CredentialsType;
42 42 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceCredentialsMsg;
... ... @@ -47,7 +47,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenR
47 47 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
48 48 import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest;
49 49
50   -import java.util.UUID;
51 50 import java.util.concurrent.CountDownLatch;
52 51 import java.util.concurrent.TimeUnit;
53 52
... ...
... ... @@ -30,7 +30,7 @@ import org.junit.Assert;
30 30 import org.thingsboard.server.common.data.Device;
31 31 import org.thingsboard.server.common.data.TransportPayloadType;
32 32 import org.thingsboard.server.common.data.device.profile.MqttTopics;
33   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  33 +import org.thingsboard.common.util.JacksonUtil;
34 34 import org.thingsboard.server.mqtt.AbstractMqttIntegrationTest;
35 35
36 36 import java.util.Arrays;
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2021 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  20 + <modelVersion>4.0.0</modelVersion>
  21 + <parent>
  22 + <groupId>org.thingsboard</groupId>
  23 + <version>3.3.0-SNAPSHOT</version>
  24 + <artifactId>common</artifactId>
  25 + </parent>
  26 + <groupId>org.thingsboard.common</groupId>
  27 + <artifactId>cache</artifactId>
  28 + <packaging>jar</packaging>
  29 +
  30 + <name>Thingsboard Server Common Cache</name>
  31 + <url>https://thingsboard.io</url>
  32 +
  33 + <properties>
  34 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  35 + <main.dir>${basedir}/../..</main.dir>
  36 + </properties>
  37 +
  38 + <dependencies>
  39 + <dependency>
  40 + <groupId>org.thingsboard.common</groupId>
  41 + <artifactId>data</artifactId>
  42 + </dependency>
  43 + <dependency>
  44 + <groupId>org.springframework.boot</groupId>
  45 + <artifactId>spring-boot-autoconfigure</artifactId>
  46 + </dependency>
  47 + <dependency>
  48 + <groupId>org.springframework.data</groupId>
  49 + <artifactId>spring-data-redis</artifactId>
  50 + </dependency>
  51 + <dependency>
  52 + <groupId>redis.clients</groupId>
  53 + <artifactId>jedis</artifactId>
  54 + </dependency>
  55 + <dependency>
  56 + <groupId>com.github.ben-manes.caffeine</groupId>
  57 + <artifactId>caffeine</artifactId>
  58 + </dependency>
  59 + <dependency>
  60 + <groupId>org.apache.commons</groupId>
  61 + <artifactId>commons-lang3</artifactId>
  62 + </dependency>
  63 + <dependency>
  64 + <groupId>org.slf4j</groupId>
  65 + <artifactId>slf4j-api</artifactId>
  66 + </dependency>
  67 + <dependency>
  68 + <groupId>org.slf4j</groupId>
  69 + <artifactId>log4j-over-slf4j</artifactId>
  70 + </dependency>
  71 + <dependency>
  72 + <groupId>ch.qos.logback</groupId>
  73 + <artifactId>logback-core</artifactId>
  74 + </dependency>
  75 + <dependency>
  76 + <groupId>ch.qos.logback</groupId>
  77 + <artifactId>logback-classic</artifactId>
  78 + </dependency>
  79 + <dependency>
  80 + <groupId>junit</groupId>
  81 + <artifactId>junit</artifactId>
  82 + <scope>test</scope>
  83 + </dependency>
  84 + <dependency>
  85 + <groupId>org.mockito</groupId>
  86 + <artifactId>mockito-core</artifactId>
  87 + <scope>test</scope>
  88 + </dependency>
  89 + </dependencies>
  90 +
  91 + <build>
  92 + <plugins>
  93 +<!-- <plugin>-->
  94 +<!-- <groupId>org.apache.maven.plugins</groupId>-->
  95 +<!-- <artifactId>maven-source-plugin</artifactId>-->
  96 +<!-- <executions>-->
  97 +<!-- <execution>-->
  98 +<!-- <id>attach-sources</id>-->
  99 +<!-- <goals>-->
  100 +<!-- <goal>jar</goal>-->
  101 +<!-- </goals>-->
  102 +<!-- </execution>-->
  103 +<!-- </executions>-->
  104 +<!-- </plugin>-->
  105 +<!-- <plugin>-->
  106 +<!-- <groupId>org.apache.maven.plugins</groupId>-->
  107 +<!-- <artifactId>maven-deploy-plugin</artifactId>-->
  108 +<!-- <configuration>-->
  109 +<!-- <skip>false</skip>-->
  110 +<!-- </configuration>-->
  111 +<!-- </plugin>-->
  112 + </plugins>
  113 + </build>
  114 +
  115 +</project>
... ...
common/cache/src/main/java/org/thingsboard/server/cache/CacheSpecs.java renamed from dao/src/main/java/org/thingsboard/server/dao/cache/CacheSpecs.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.dao.cache;
  16 +package org.thingsboard.server.cache;
17 17
18 18 import lombok.Data;
19 19
... ...
common/cache/src/main/java/org/thingsboard/server/cache/CaffeineCacheConfiguration.java renamed from dao/src/main/java/org/thingsboard/server/dao/cache/CaffeineCacheConfiguration.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.dao.cache;
  16 +package org.thingsboard.server.cache;
17 17
18 18 import com.github.benmanes.caffeine.cache.Caffeine;
19 19 import com.github.benmanes.caffeine.cache.RemovalCause;
... ... @@ -26,7 +26,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
26 26 import org.springframework.cache.CacheManager;
27 27 import org.springframework.cache.annotation.EnableCaching;
28 28 import org.springframework.cache.caffeine.CaffeineCache;
29   -import org.springframework.cache.interceptor.KeyGenerator;
30 29 import org.springframework.cache.support.SimpleCacheManager;
31 30 import org.springframework.context.annotation.Bean;
32 31 import org.springframework.context.annotation.Configuration;
... ... @@ -78,14 +77,9 @@ public class CaffeineCacheConfiguration {
78 77 return Ticker.systemTicker();
79 78 }
80 79
81   - @Bean
82   - public KeyGenerator previousDeviceCredentialsId() {
83   - return new PreviousDeviceCredentialsIdKeyGenerator();
84   - }
85   -
86 80 private Weigher<? super Object, ? super Object> collectionSafeWeigher() {
87 81 return (Weigher<Object, Object>) (key, value) -> {
88   - if(value instanceof Collection) {
  82 + if (value instanceof Collection) {
89 83 return ((Collection) value).size();
90 84 }
91 85 return 1;
... ...
common/cache/src/main/java/org/thingsboard/server/cache/TBRedisCacheConfiguration.java renamed from dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisCacheConfiguration.java
... ... @@ -13,14 +13,13 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.dao.cache;
  16 +package org.thingsboard.server.cache;
17 17
18 18 import lombok.Data;
19 19 import org.springframework.beans.factory.annotation.Value;
20 20 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
21 21 import org.springframework.cache.CacheManager;
22 22 import org.springframework.cache.annotation.EnableCaching;
23   -import org.springframework.cache.interceptor.KeyGenerator;
24 23 import org.springframework.context.annotation.Bean;
25 24 import org.springframework.context.annotation.Configuration;
26 25 import org.springframework.core.convert.converter.ConverterRegistry;
... ... @@ -90,11 +89,6 @@ public abstract class TBRedisCacheConfiguration {
90 89 }
91 90
92 91 @Bean
93   - public KeyGenerator previousDeviceCredentialsId() {
94   - return new PreviousDeviceCredentialsIdKeyGenerator();
95   - }
96   -
97   - @Bean
98 92 public RedisTemplate<String, Object> redisTemplate() {
99 93 RedisTemplate<String, Object> template = new RedisTemplate<>();
100 94 template.setConnectionFactory(redisConnectionFactory());
... ...
common/cache/src/main/java/org/thingsboard/server/cache/TBRedisClusterConfiguration.java renamed from dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisClusterConfiguration.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.dao.cache;
  16 +package org.thingsboard.server.cache;
17 17
18 18 import org.apache.commons.lang3.StringUtils;
19 19 import org.springframework.beans.factory.annotation.Value;
... ...
common/cache/src/main/java/org/thingsboard/server/cache/TBRedisStandaloneConfiguration.java renamed from dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisStandaloneConfiguration.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.dao.cache;
  16 +package org.thingsboard.server.cache;
17 17
18 18 import org.springframework.beans.factory.annotation.Value;
19 19 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
... ...
... ... @@ -42,6 +42,7 @@
42 42 <module>transport</module>
43 43 <module>dao-api</module>
44 44 <module>stats</module>
  45 + <module>cache</module>
45 46 <module>edge-api</module>
46 47 </modules>
47 48
... ...
  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.queue.util;
  17 +
  18 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  19 +
  20 +import java.lang.annotation.Retention;
  21 +import java.lang.annotation.RetentionPolicy;
  22 +
  23 +@Retention(RetentionPolicy.RUNTIME)
  24 +@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
  25 +public @interface TbLwM2mTransportComponent {
  26 +}
... ...
... ... @@ -90,7 +90,6 @@
90 90 <groupId>org.eclipse.leshan</groupId>
91 91 <artifactId>leshan-client-cf</artifactId>
92 92 </dependency>
93   -
94 93 <dependency>
95 94 <groupId>org.eclipse.leshan</groupId>
96 95 <artifactId>leshan-server-redis</artifactId>
... ...
... ... @@ -29,7 +29,7 @@ import org.springframework.stereotype.Component;
29 29 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore;
30 30 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore;
31 31 import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2mDefaultBootstrapSessionManager;
32   -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer;
  32 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer;
33 33
34 34 import java.math.BigInteger;
35 35 import java.security.AlgorithmParameters;
... ... @@ -56,7 +56,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE
56 56 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
57 57 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
58 58 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
59   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getCoapConfig;
  59 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig;
60 60
61 61 @Slf4j
62 62 @Component
... ... @@ -70,7 +70,7 @@ public class LwM2MTransportBootstrapServerConfiguration {
70 70 private LwM2MTransportContextBootstrap contextBs;
71 71
72 72 @Autowired
73   - private LwM2MTransportContextServer contextS;
  73 + private LwM2mTransportContextServer contextS;
74 74
75 75 @Autowired
76 76 private LwM2MBootstrapSecurityStore lwM2MBootstrapSecurityStore;
... ... @@ -94,7 +94,7 @@ public class LwM2MTransportBootstrapServerConfiguration {
94 94 builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort));
95 95
96 96 /** Define model provider (Create Models )*/
97   - builder.setModel(new StaticModel(contextS.getCtxServer().getModelsValue()));
  97 + builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValue()));
98 98
99 99 /** Create credentials */
100 100 this.setServerWithCredentials(builder);
... ... @@ -108,8 +108,8 @@ public class LwM2MTransportBootstrapServerConfiguration {
108 108
109 109 /** Create and Set DTLS Config */
110 110 DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();
111   - dtlsConfig.setRecommendedSupportedGroupsOnly(this.contextS.getCtxServer().isRecommendedSupportedGroups());
112   - dtlsConfig.setRecommendedCipherSuitesOnly(this.contextS.getCtxServer().isRecommendedCiphers());
  111 + dtlsConfig.setRecommendedSupportedGroupsOnly(this.contextS.getLwM2MTransportConfigServer().isRecommendedSupportedGroups());
  112 + dtlsConfig.setRecommendedCipherSuitesOnly(this.contextS.getLwM2MTransportConfigServer().isRecommendedCiphers());
113 113 if (this.pskMode) {
114 114 dtlsConfig.setSupportedCipherSuites(
115 115 TLS_PSK_WITH_AES_128_CCM_8,
... ... @@ -135,10 +135,10 @@ public class LwM2MTransportBootstrapServerConfiguration {
135 135
136 136 private void setServerWithCredentials(LeshanBootstrapServerBuilder builder) {
137 137 try {
138   - if (this.contextS.getCtxServer().getKeyStoreValue() != null) {
139   - KeyStore keyStoreServer = this.contextS.getCtxServer().getKeyStoreValue();
  138 + if (this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue() != null) {
  139 + KeyStore keyStoreServer = this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue();
140 140 if (this.setBuilderX509(builder)) {
141   - X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getCtxServer().getRootAlias());
  141 + X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getLwM2MTransportConfigServer().getRootAlias());
142 142 if (rootCAX509Cert != null) {
143 143 X509Certificate[] trustedCertificates = new X509Certificate[1];
144 144 trustedCertificates[0] = rootCAX509Cert;
... ... @@ -169,8 +169,8 @@ public class LwM2MTransportBootstrapServerConfiguration {
169 169 * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks
170 170 */
171 171 try {
172   - X509Certificate serverCertificate = (X509Certificate) this.contextS.getCtxServer().getKeyStoreValue().getCertificate(this.contextBs.getCtxBootStrap().getBootstrapAlias());
173   - PrivateKey privateKey = (PrivateKey) this.contextS.getCtxServer().getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getBootstrapAlias(), this.contextS.getCtxServer().getKeyStorePasswordServer() == null ? null : this.contextS.getCtxServer().getKeyStorePasswordServer().toCharArray());
  172 + X509Certificate serverCertificate = (X509Certificate) this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.contextBs.getCtxBootStrap().getBootstrapAlias());
  173 + PrivateKey privateKey = (PrivateKey) this.contextS.getLwM2MTransportConfigServer().getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getBootstrapAlias(), this.contextS.getLwM2MTransportConfigServer().getKeyStorePasswordServer() == null ? null : this.contextS.getLwM2MTransportConfigServer().getKeyStorePasswordServer().toCharArray());
174 174 PublicKey publicKey = serverCertificate.getPublicKey();
175 175 if (serverCertificate != null &&
176 176 privateKey != null && privateKey.getEncoded().length > 0 &&
... ...
... ... @@ -31,30 +31,24 @@ package org.thingsboard.server.transport.lwm2m.bootstrap;
31 31 */
32 32
33 33 import lombok.extern.slf4j.Slf4j;
34   -import org.springframework.beans.factory.annotation.Autowired;
35 34 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
36 35 import org.springframework.stereotype.Component;
37 36 import org.thingsboard.server.common.transport.TransportContext;
38 37 import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap;
39 38
40   -import javax.annotation.PostConstruct;
41   -
42 39
43 40 @Slf4j
44 41 @Component
45 42 @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || '${service.type:null}'=='monolith'")
46 43 public class LwM2MTransportContextBootstrap extends TransportContext {
47 44
48   - private LwM2MTransportConfigBootstrap ctxBootStrap;
49   - @Autowired
50   - LwM2MTransportConfigBootstrap lwM2MTransportConfigBootstarp;
  45 + private final LwM2MTransportConfigBootstrap lwM2MTransportConfigBootstrap;
51 46
52   - @PostConstruct
53   - public void init() {
54   - this.ctxBootStrap = lwM2MTransportConfigBootstarp;
  47 + public LwM2MTransportContextBootstrap(LwM2MTransportConfigBootstrap ctxBootStrap) {
  48 + this.lwM2MTransportConfigBootstrap = ctxBootStrap;
55 49 }
56 50
57 51 public LwM2MTransportConfigBootstrap getCtxBootStrap() {
58   - return this.ctxBootStrap;
  52 + return this.lwM2MTransportConfigBootstrap;
59 53 }
60 54 }
... ...
... ... @@ -27,16 +27,15 @@ import org.eclipse.leshan.server.bootstrap.EditableBootstrapConfigStore;
27 27 import org.eclipse.leshan.server.bootstrap.InvalidConfigurationException;
28 28 import org.eclipse.leshan.server.security.BootstrapSecurityStore;
29 29 import org.eclipse.leshan.server.security.SecurityInfo;
30   -import org.springframework.beans.factory.annotation.Autowired;
31 30 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
32 31 import org.springframework.stereotype.Service;
33 32 import org.thingsboard.server.gen.transport.TransportProtos;
34 33 import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;
35 34 import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
36 35 import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore;
37   -import org.thingsboard.server.transport.lwm2m.server.LwM2MSessionMsgListener;
38   -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer;
39   -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler;
  36 +import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener;
  37 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer;
  38 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler;
40 39 import org.thingsboard.server.transport.lwm2m.utils.TypeServer;
41 40
42 41 import java.io.IOException;
... ... @@ -45,12 +44,12 @@ import java.util.Arrays;
45 44 import java.util.List;
46 45 import java.util.UUID;
47 46
48   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.BOOTSTRAP_SERVER;
49   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_ERROR;
50   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_INFO;
51   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LWM2M_SERVER;
52   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.SERVERS;
53   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getBootstrapParametersFromThingsboard;
  47 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.BOOTSTRAP_SERVER;
  48 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR;
  49 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
  50 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LWM2M_SERVER;
  51 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVERS;
  52 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getBootstrapParametersFromThingsboard;
54 53
55 54 @Slf4j
56 55 @Service("LwM2MBootstrapSecurityStore")
... ... @@ -59,14 +58,14 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
59 58
60 59 private final EditableBootstrapConfigStore bootstrapConfigStore;
61 60
62   - @Autowired
63   - LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator;
  61 + private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator;
64 62
65   - @Autowired
66   - public LwM2MTransportContextServer context;
  63 + private final LwM2mTransportContextServer context;
67 64
68   - public LwM2MBootstrapSecurityStore(EditableBootstrapConfigStore bootstrapConfigStore) {
  65 + public LwM2MBootstrapSecurityStore(EditableBootstrapConfigStore bootstrapConfigStore, LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator, LwM2mTransportContextServer context) {
69 66 this.bootstrapConfigStore = bootstrapConfigStore;
  67 + this.lwM2MCredentialsSecurityInfoValidator = lwM2MCredentialsSecurityInfoValidator;
  68 + this.context = context;
70 69 }
71 70
72 71 @Override
... ... @@ -162,18 +161,18 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
162 161 LwM2MServerBootstrap profileLwm2mServer = mapper.readValue(bootstrapObject.get(LWM2M_SERVER).toString(), LwM2MServerBootstrap.class);
163 162 UUID sessionUUiD = UUID.randomUUID();
164 163 TransportProtos.SessionInfoProto sessionInfo = context.getValidateSessionInfo(store.getMsg(), sessionUUiD.getMostSignificantBits(), sessionUUiD.getLeastSignificantBits());
165   - context.getTransportService().registerAsyncSession(sessionInfo, new LwM2MSessionMsgListener(null, sessionInfo));
  164 + context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, sessionInfo));
166 165 if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) {
167 166 lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap);
168 167 lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer);
169 168 String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint());
170   - context.sentParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo);
  169 + context.sentParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo);
171 170 return lwM2MBootstrapConfig;
172 171 } else {
173 172 log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint());
174 173 log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint());
175 174 String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint());
176   - context.sentParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo);
  175 + context.sentParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo);
177 176 return null;
178 177 }
179 178 }
... ...
... ... @@ -20,16 +20,14 @@ import lombok.extern.slf4j.Slf4j;
20 20 import org.eclipse.leshan.core.util.Hex;
21 21 import org.eclipse.leshan.core.util.SecurityUtil;
22 22 import org.eclipse.leshan.server.security.SecurityInfo;
23   -import org.springframework.beans.factory.annotation.Autowired;
24   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
25 23 import org.springframework.stereotype.Component;
26 24 import org.thingsboard.server.common.data.DeviceProfile;
27 25 import org.thingsboard.server.common.transport.TransportServiceCallback;
28   -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
29 26 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
30   -import org.thingsboard.server.transport.lwm2m.bootstrap.LwM2MTransportContextBootstrap;
31   -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer;
32   -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler;
  27 +import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
  28 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  29 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer;
  30 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler;
33 31 import org.thingsboard.server.transport.lwm2m.utils.TypeServer;
34 32
35 33 import java.io.IOException;
... ... @@ -45,47 +43,46 @@ import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.RP
45 43 import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X509;
46 44
47 45 @Slf4j
48   -@Component("LwM2MGetSecurityInfo")
49   -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
  46 +@Component
  47 +@TbLwM2mTransportComponent
50 48 public class LwM2mCredentialsSecurityInfoValidator {
51 49
52   - @Autowired
53   - public LwM2MTransportContextServer contextS;
54   -
55   - @Autowired
56   - public LwM2MTransportContextBootstrap contextBS;
  50 + private final LwM2mTransportContextServer contextS;
57 51
  52 + public LwM2mCredentialsSecurityInfoValidator(LwM2mTransportContextServer contextS) {
  53 + this.contextS = contextS;
  54 + }
58 55
59 56 /**
60 57 * Request to thingsboard Response from thingsboard ValidateDeviceLwM2MCredentials
61   - * @param endPoint -
  58 + * @param endpoint -
62 59 * @param keyValue -
63 60 * @return ValidateDeviceCredentialsResponseMsg and SecurityInfo
64 61 */
65   - public ReadResultSecurityStore createAndValidateCredentialsSecurityInfo(String endPoint, TypeServer keyValue) {
  62 + public ReadResultSecurityStore createAndValidateCredentialsSecurityInfo(String endpoint, TypeServer keyValue) {
66 63 CountDownLatch latch = new CountDownLatch(1);
67 64 final ReadResultSecurityStore[] resultSecurityStore = new ReadResultSecurityStore[1];
68   - contextS.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endPoint).build(),
69   - new TransportServiceCallback<ValidateDeviceCredentialsResponseMsg>() {
  65 + contextS.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endpoint).build(),
  66 + new TransportServiceCallback<>() {
70 67 @Override
71 68 public void onSuccess(ValidateDeviceCredentialsResponseMsg msg) {
72 69 String credentialsBody = msg.getCredentialsBody();
73   - resultSecurityStore[0] = createSecurityInfo(endPoint, credentialsBody, keyValue);
  70 + resultSecurityStore[0] = createSecurityInfo(endpoint, credentialsBody, keyValue);
74 71 resultSecurityStore[0].setMsg(msg);
75   - Optional<DeviceProfile> deviceProfileOpt = LwM2MTransportHandler.decode(msg.getProfileBody().toByteArray());
  72 + Optional<DeviceProfile> deviceProfileOpt = LwM2mTransportHandler.decode(msg.getProfileBody().toByteArray());
76 73 deviceProfileOpt.ifPresent(profile -> resultSecurityStore[0].setDeviceProfile(profile));
77 74 latch.countDown();
78 75 }
79 76
80 77 @Override
81 78 public void onError(Throwable e) {
82   - log.trace("[{}] [{}] Failed to process credentials ", endPoint, e);
83   - resultSecurityStore[0] = createSecurityInfo(endPoint, null, null);
  79 + log.trace("[{}] [{}] Failed to process credentials ", endpoint, e);
  80 + resultSecurityStore[0] = createSecurityInfo(endpoint, null, null);
84 81 latch.countDown();
85 82 }
86 83 });
87 84 try {
88   - latch.await(contextS.getCtxServer().getTimeout(), TimeUnit.MILLISECONDS);
  85 + latch.await(contextS.getLwM2MTransportConfigServer().getTimeout(), TimeUnit.MILLISECONDS);
89 86 } catch (InterruptedException e) {
90 87 log.error("Failed to await credentials!", e);
91 88 }
... ... @@ -101,7 +98,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
101 98 */
102 99 private ReadResultSecurityStore createSecurityInfo(String endPoint, String jsonStr, TypeServer keyValue) {
103 100 ReadResultSecurityStore result = new ReadResultSecurityStore();
104   - JsonObject objectMsg = LwM2MTransportHandler.validateJson(jsonStr);
  101 + JsonObject objectMsg = LwM2mTransportHandler.validateJson(jsonStr);
105 102 if (objectMsg != null && !objectMsg.isJsonNull()) {
106 103 JsonObject object = (objectMsg.has(keyValue.type) && !objectMsg.get(keyValue.type).isJsonNull()) ? objectMsg.get(keyValue.type).getAsJsonObject() : null;
107 104 /**
... ...
... ... @@ -31,9 +31,9 @@ import java.util.Collection;
31 31 public class LwM2mServerListener {
32 32
33 33 private final LeshanServer lhServer;
34   - private final LwM2MTransportServiceImpl service;
  34 + private final LwM2mTransportServiceImpl service;
35 35
36   - public LwM2mServerListener(LeshanServer lhServer, LwM2MTransportServiceImpl service) {
  36 + public LwM2mServerListener(LeshanServer lhServer, LwM2mTransportServiceImpl service) {
37 37 this.lhServer = lhServer;
38 38 this.service = service;
39 39 }
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mSessionMsgListener.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MSessionMsgListener.java
... ... @@ -32,11 +32,11 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCre
32 32 import java.util.Optional;
33 33
34 34 @Slf4j
35   -public class LwM2MSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener {
36   - private LwM2MTransportServiceImpl service;
  35 +public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener {
  36 + private LwM2mTransportServiceImpl service;
37 37 private TransportProtos.SessionInfoProto sessionInfo;
38 38
39   - public LwM2MSessionMsgListener(LwM2MTransportServiceImpl service, TransportProtos.SessionInfoProto sessionInfo) {
  39 + public LwM2mSessionMsgListener(LwM2mTransportServiceImpl service, TransportProtos.SessionInfoProto sessionInfo) {
40 40 this.service = service;
41 41 this.sessionInfo = sessionInfo;
42 42 }
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportContextServer.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportContextServer.java
... ... @@ -34,8 +34,6 @@ import com.google.gson.JsonElement;
34 34 import com.google.gson.JsonObject;
35 35 import lombok.Getter;
36 36 import lombok.extern.slf4j.Slf4j;
37   -import org.springframework.beans.factory.annotation.Autowired;
38   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
39 37 import org.springframework.stereotype.Component;
40 38 import org.thingsboard.server.common.transport.TransportContext;
41 39 import org.thingsboard.server.common.transport.TransportService;
... ... @@ -43,40 +41,32 @@ import org.thingsboard.server.common.transport.TransportServiceCallback;
43 41 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
44 42 import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer;
45 43 import org.thingsboard.server.gen.transport.TransportProtos;
  44 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
46 45 import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor;
47   -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore;
48 46
49   -import javax.annotation.PostConstruct;
50   -
51   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_TELEMETRY;
  47 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY;
52 48
53 49 @Slf4j
54 50 @Component
55   -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
56   -public class LwM2MTransportContextServer extends TransportContext {
  51 +@TbLwM2mTransportComponent
  52 +public class LwM2mTransportContextServer extends TransportContext {
57 53
58   - private LwM2MTransportConfigServer ctxServer;
59 54
60   - @Autowired
61   - protected LwM2MTransportConfigServer lwM2MTransportConfigServer;
  55 + private final LwM2MTransportConfigServer lwM2MTransportConfigServer;
62 56
63   - @Autowired
64   - private TransportService transportService;
  57 + private final TransportService transportService;
65 58
66 59 @Getter
67   - @Autowired
68   - private LwM2MJsonAdaptor adaptor;
69   -
70   - @Autowired
71   - LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore;
  60 + private final LwM2MJsonAdaptor adaptor;
72 61
73   - @PostConstruct
74   - public void init() {
75   - this.ctxServer = lwM2MTransportConfigServer;
  62 + public LwM2mTransportContextServer(LwM2MTransportConfigServer lwM2MTransportConfigServer, TransportService transportService, LwM2MJsonAdaptor adaptor) {
  63 + this.lwM2MTransportConfigServer = lwM2MTransportConfigServer;
  64 + this.transportService = transportService;
  65 + this.adaptor = adaptor;
76 66 }
77 67
78   - public LwM2MTransportConfigServer getCtxServer() {
79   - return this.ctxServer;
  68 + public LwM2MTransportConfigServer getLwM2MTransportConfigServer() {
  69 + return this.lwM2MTransportConfigServer;
80 70 }
81 71
82 72 /**
... ... @@ -86,7 +76,7 @@ public class LwM2MTransportContextServer extends TransportContext {
86 76 * @return - dummy
87 77 */
88 78 private <T> TransportServiceCallback<Void> getPubAckCallbackSentAttrTelemetry(final T msg) {
89   - return new TransportServiceCallback<Void>() {
  79 + return new TransportServiceCallback<>() {
90 80 @Override
91 81 public void onSuccess(Void dummy) {
92 82 log.trace("Success to publish msg: {}, dummy: {}", msg, dummy);
... ... @@ -101,11 +91,11 @@ public class LwM2MTransportContextServer extends TransportContext {
101 91
102 92 public void sentParametersOnThingsboard(JsonElement msg, String topicName, TransportProtos.SessionInfoProto sessionInfo) {
103 93 try {
104   - if (topicName.equals(LwM2MTransportHandler.DEVICE_ATTRIBUTES_TOPIC)) {
  94 + if (topicName.equals(LwM2mTransportHandler.DEVICE_ATTRIBUTES_TOPIC)) {
105 95 TransportProtos.PostAttributeMsg postAttributeMsg = adaptor.convertToPostAttributes(msg);
106 96 TransportServiceCallback call = this.getPubAckCallbackSentAttrTelemetry(postAttributeMsg);
107 97 transportService.process(sessionInfo, postAttributeMsg, this.getPubAckCallbackSentAttrTelemetry(call));
108   - } else if (topicName.equals(LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC)) {
  98 + } else if (topicName.equals(LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC)) {
109 99 TransportProtos.PostTelemetryMsg postTelemetryMsg = adaptor.convertToPostTelemetry(msg);
110 100 TransportServiceCallback call = this.getPubAckCallbackSentAttrTelemetry(postTelemetryMsg);
111 101 transportService.process(sessionInfo, postTelemetryMsg, this.getPubAckCallbackSentAttrTelemetry(call));
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportHandler.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java
... ... @@ -36,8 +36,8 @@ import org.nustaq.serialization.FSTConfiguration;
36 36 import org.thingsboard.server.common.data.DeviceProfile;
37 37 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
38 38 import org.thingsboard.server.common.transport.TransportServiceCallback;
39   -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientProfile;
40   -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient;
  39 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
  40 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
41 41
42 42 import java.io.File;
43 43 import java.io.IOException;
... ... @@ -49,7 +49,7 @@ import java.util.Optional;
49 49 @Slf4j
50 50 //@Component("LwM2MTransportHandler")
51 51 //@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' )|| ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
52   -public class LwM2MTransportHandler {
  52 +public class LwM2mTransportHandler {
53 53
54 54 // We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to
55 55 // send a Confirmable message to the time when an acknowledgement is no longer expected.
... ... @@ -188,8 +188,8 @@ public class LwM2MTransportHandler {
188 188 return null;
189 189 }
190 190
191   - public static LwM2MClientProfile getNewProfileParameters(JsonObject profilesConfigData) {
192   - LwM2MClientProfile lwM2MClientProfile = new LwM2MClientProfile();
  191 + public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData) {
  192 + LwM2mClientProfile lwM2MClientProfile = new LwM2mClientProfile();
193 193 lwM2MClientProfile.setPostClientLwM2mSettings(profilesConfigData.get(CLIENT_LWM2M_SETTINGS).getAsJsonObject());
194 194 lwM2MClientProfile.setPostKeyNameProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEY_NAME).getAsJsonObject());
195 195 lwM2MClientProfile.setPostAttributeProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).getAsJsonArray());
... ... @@ -214,14 +214,14 @@ public class LwM2MTransportHandler {
214 214 * "telemetry":["/1/0/1","/2/0/1","/6/0/1"],
215 215 * "observe":["/2/0","/2/0/0","/4/0/2"]}
216 216 */
217   - public static LwM2MClientProfile getLwM2MClientProfileFromThingsboard(DeviceProfile deviceProfile) {
  217 + public static LwM2mClientProfile getLwM2MClientProfileFromThingsboard(DeviceProfile deviceProfile) {
218 218 if (deviceProfile != null && ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) {
219 219 Object profile = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties();
220 220 try {
221 221 ObjectMapper mapper = new ObjectMapper();
222 222 String profileStr = mapper.writeValueAsString(profile);
223 223 JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null;
224   - return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2MTransportHandler.getNewProfileParameters(profileJson) : null;
  224 + return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson) : null;
225 225 } catch (IOException e) {
226 226 log.error("", e);
227 227 }
... ... @@ -244,12 +244,12 @@ public class LwM2MTransportHandler {
244 244 return null;
245 245 }
246 246
247   - public static boolean getClientUpdateValueAfterConnect (LwM2MClientProfile profile) {
  247 + public static boolean getClientUpdateValueAfterConnect (LwM2mClientProfile profile) {
248 248 return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientUpdateValueAfterConnect") &&
249 249 profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientUpdateValueAfterConnect").getAsBoolean();
250 250 }
251 251
252   - public static boolean getClientOnlyObserveAfterConnect (LwM2MClientProfile profile) {
  252 + public static boolean getClientOnlyObserveAfterConnect (LwM2mClientProfile profile) {
253 253 return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") &&
254 254 profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsBoolean();
255 255 }
... ... @@ -336,11 +336,11 @@ public class LwM2MTransportHandler {
336 336 return StringUtils.join(linkedListOut, "");
337 337 }
338 338
339   - public static <T> TransportServiceCallback<Void> getAckCallback(LwM2MClient lwM2MClient, int requestId, String typeTopic) {
  339 + public static <T> TransportServiceCallback<Void> getAckCallback(LwM2mClient lwM2MClient, int requestId, String typeTopic) {
340 340 return new TransportServiceCallback<Void>() {
341 341 @Override
342 342 public void onSuccess(Void dummy) {
343   - log.trace("[{}] [{}] - requestId [{}] - EndPoint , Access AckCallback", typeTopic, requestId, lwM2MClient.getEndPoint());
  343 + log.trace("[{}] [{}] - requestId [{}] - EndPoint , Access AckCallback", typeTopic, requestId, lwM2MClient.getEndpoint());
344 344 }
345 345
346 346 @Override
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java
... ... @@ -48,9 +48,10 @@ import org.eclipse.leshan.core.util.NamedThreadFactory;
48 48 import org.eclipse.leshan.server.californium.LeshanServer;
49 49 import org.eclipse.leshan.server.registration.Registration;
50 50 import org.springframework.beans.factory.annotation.Autowired;
51   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
52 51 import org.springframework.stereotype.Service;
53   -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient;
  52 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  53 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  54 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
54 55 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
55 56
56 57 import javax.annotation.PostConstruct;
... ... @@ -63,40 +64,41 @@ import java.util.concurrent.Executors;
63 64
64 65 import static org.eclipse.californium.core.coap.CoAP.ResponseCode.isSuccess;
65 66 import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_PERIOD;
66   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEFAULT_TIMEOUT;
67   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_DISCOVER;
68   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_OBSERVE;
69   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_READ;
70   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_ERROR;
71   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_INFO;
72   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_EXECUTE;
73   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_OBSERVE_CANCEL;
74   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_WRITE_REPLACE;
75   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES;
76   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE;
77   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.RESPONSE_CHANNEL;
  67 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEFAULT_TIMEOUT;
  68 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_DISCOVER;
  69 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_OBSERVE;
  70 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_READ;
  71 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR;
  72 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
  73 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_EXECUTE;
  74 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_OBSERVE_CANCEL;
  75 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_WRITE_REPLACE;
  76 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES;
  77 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE;
  78 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.RESPONSE_CHANNEL;
78 79
79 80 @Slf4j
80   -@Service("LwM2MTransportRequest")
81   -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
82   -public class LwM2MTransportRequest {
  81 +@Service("LwM2mTransportRequest")
  82 +@TbLwM2mTransportComponent
  83 +public class LwM2mTransportRequest {
83 84 private ExecutorService executorResponse;
84   - private ExecutorService executorResponseError;
  85 +
85 86 private LwM2mValueConverterImpl converter;
86 87
87 88 @Autowired
88   - LwM2MTransportServiceImpl service;
  89 + private LwM2mTransportServiceImpl service;
  90 +
  91 + @Autowired
  92 + private LwM2mTransportContextServer context;
89 93
90 94 @Autowired
91   - public LwM2MTransportContextServer context;
  95 + private LwM2mClientContext lwM2mClientContext;
92 96
93 97 @PostConstruct
94 98 public void init() {
95 99 this.converter = LwM2mValueConverterImpl.getInstance();
96   - executorResponse = Executors.newFixedThreadPool(this.context.getCtxServer().getRequestPoolSize(),
  100 + executorResponse = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getRequestPoolSize(),
97 101 new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL)));
98   - executorResponseError = Executors.newFixedThreadPool(this.context.getCtxServer().getRequestErrorPoolSize(),
99   - new NamedThreadFactory(String.format("LwM2M %s channel response Error", RESPONSE_CHANNEL)));
100 102 }
101 103
102 104 public Collection<Registration> doGetRegistrations(LeshanServer lwServer) {
... ... @@ -124,7 +126,7 @@ public class LwM2MTransportRequest {
124 126 if (registration != null && resultIds.getObjectId() >= 0) {
125 127 DownlinkRequest request = null;
126 128 ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null;
127   - ResourceModel resource = service.context.getCtxServer().getResourceModel(registration, resultIds);
  129 + ResourceModel resource = service.context.getLwM2MTransportConfigServer().getResourceModel(registration, resultIds);
128 130 timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
129 131 switch (typeOper) {
130 132 case GET_TYPE_OPER_READ:
... ... @@ -234,7 +236,7 @@ public class LwM2MTransportRequest {
234 236
235 237 @SuppressWarnings("unchecked")
236 238 private void sendRequest(LeshanServer lwServer, Registration registration, DownlinkRequest request, long timeoutInMs) {
237   - LwM2MClient lwM2MClient = this.service.lwM2mInMemorySecurityStore.getLwM2MClientWithReg(registration, null);
  239 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
238 240 lwServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
239 241 if (!lwM2MClient.isInit()) {
240 242 lwM2MClient.initValue(this.service, request.getPath().toString());
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerConfiguration.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerConfiguration.java
... ... @@ -22,15 +22,16 @@ import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder;
22 22 import org.eclipse.leshan.core.util.Hex;
23 23 import org.eclipse.leshan.server.californium.LeshanServer;
24 24 import org.eclipse.leshan.server.californium.LeshanServerBuilder;
  25 +import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
25 26 import org.eclipse.leshan.server.model.LwM2mModelProvider;
26 27 import org.eclipse.leshan.server.model.VersionedModelProvider;
27 28 import org.eclipse.leshan.server.security.DefaultAuthorizer;
  29 +import org.eclipse.leshan.server.security.EditableSecurityStore;
28 30 import org.eclipse.leshan.server.security.SecurityChecker;
29 31 import org.springframework.beans.factory.annotation.Autowired;
30   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
31 32 import org.springframework.context.annotation.Bean;
32 33 import org.springframework.stereotype.Component;
33   -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore;
  34 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
34 35 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
35 36
36 37 import java.math.BigInteger;
... ... @@ -57,32 +58,35 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE
57 58 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
58 59 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
59 60 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
60   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getCoapConfig;
  61 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig;
61 62
62 63 @Slf4j
63 64 @Component("LwM2MTransportServerConfiguration")
64   -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
65   -public class LwM2MTransportServerConfiguration {
  65 +@TbLwM2mTransportComponent
  66 +public class LwM2mTransportServerConfiguration {
66 67 private PublicKey publicKey;
67 68 private PrivateKey privateKey;
68 69 private boolean pskMode = false;
69 70
70 71 @Autowired
71   - private LwM2MTransportContextServer context;
  72 + private LwM2mTransportContextServer context;
72 73
73 74 @Autowired
74   - private LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore;
  75 + private CaliforniumRegistrationStore registrationStore;
  76 +
  77 + @Autowired
  78 + private EditableSecurityStore securityStore;
75 79
76 80 @Bean
77 81 public LeshanServer getLeshanServer() {
78 82 log.info("Starting LwM2M transport Server... PostConstruct");
79   - return this.getLhServer(this.context.getCtxServer().getServerPortNoSec(), this.context.getCtxServer().getServerPortSecurity());
  83 + return this.getLhServer(this.context.getLwM2MTransportConfigServer().getServerPortNoSec(), this.context.getLwM2MTransportConfigServer().getServerPortSecurity());
80 84 }
81 85
82 86 private LeshanServer getLhServer(Integer serverPortNoSec, Integer serverSecurePort) {
83 87 LeshanServerBuilder builder = new LeshanServerBuilder();
84   - builder.setLocalAddress(this.context.getCtxServer().getServerHost(), serverPortNoSec);
85   - builder.setLocalSecureAddress(this.context.getCtxServer().getServerHostSecurity(), serverSecurePort);
  88 + builder.setLocalAddress(this.context.getLwM2MTransportConfigServer().getServerHost(), serverPortNoSec);
  89 + builder.setLocalSecureAddress(this.context.getLwM2MTransportConfigServer().getServerHostSecurity(), serverSecurePort);
86 90 builder.setDecoder(new DefaultLwM2mNodeDecoder());
87 91 /** Use a magic converter to support bad type send by the UI. */
88 92 builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance()));
... ... @@ -91,26 +95,26 @@ public class LwM2MTransportServerConfiguration {
91 95 builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort));
92 96
93 97 /** Define model provider (Create Models )*/
94   - LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getCtxServer().getModelsValue());
  98 + LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getLwM2MTransportConfigServer().getModelsValue());
95 99 builder.setObjectModelProvider(modelProvider);
96 100
97 101 /** Create credentials */
98 102 this.setServerWithCredentials(builder);
99 103
100 104 /** Set securityStore with new registrationStore */
101   - builder.setSecurityStore(lwM2mInMemorySecurityStore);
  105 + builder.setSecurityStore(securityStore);
  106 + builder.setRegistrationStore(registrationStore);
102 107
103 108
104 109 /** Create DTLS Config */
105 110 DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();
106   - dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getCtxServer().isRecommendedSupportedGroups());
107   - dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getCtxServer().isRecommendedCiphers());
  111 + dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getLwM2MTransportConfigServer().isRecommendedSupportedGroups());
  112 + dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getLwM2MTransportConfigServer().isRecommendedCiphers());
108 113 if (this.pskMode) {
109 114 dtlsConfig.setSupportedCipherSuites(
110 115 TLS_PSK_WITH_AES_128_CCM_8,
111 116 TLS_PSK_WITH_AES_128_CBC_SHA256);
112   - }
113   - else {
  117 + } else {
114 118 dtlsConfig.setSupportedCipherSuites(
115 119 TLS_PSK_WITH_AES_128_CCM_8,
116 120 TLS_PSK_WITH_AES_128_CBC_SHA256,
... ... @@ -118,7 +122,6 @@ public class LwM2MTransportServerConfiguration {
118 122 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);
119 123 }
120 124
121   -
122 125 /** Set DTLS Config */
123 126 builder.setDtlsConfig(dtlsConfig);
124 127
... ... @@ -128,9 +131,9 @@ public class LwM2MTransportServerConfiguration {
128 131
129 132 private void setServerWithCredentials(LeshanServerBuilder builder) {
130 133 try {
131   - if (this.context.getCtxServer().getKeyStoreValue() != null) {
  134 + if (this.context.getLwM2MTransportConfigServer().getKeyStoreValue() != null) {
132 135 if (this.setBuilderX509(builder)) {
133   - X509Certificate rootCAX509Cert = (X509Certificate) this.context.getCtxServer().getKeyStoreValue().getCertificate(this.context.getCtxServer().getRootAlias());
  136 + X509Certificate rootCAX509Cert = (X509Certificate) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.context.getLwM2MTransportConfigServer().getRootAlias());
134 137 if (rootCAX509Cert != null) {
135 138 X509Certificate[] trustedCertificates = new X509Certificate[1];
136 139 trustedCertificates[0] = rootCAX509Cert;
... ... @@ -140,7 +143,7 @@ public class LwM2MTransportServerConfiguration {
140 143 builder.setTrustedCertificates(new X509Certificate[0]);
141 144 }
142 145 /** Set securityStore with registrationStore*/
143   - builder.setAuthorizer(new DefaultAuthorizer(lwM2mInMemorySecurityStore, new SecurityChecker() {
  146 + builder.setAuthorizer(new DefaultAuthorizer(securityStore, new SecurityChecker() {
144 147 @Override
145 148 protected boolean matchX509Identity(String endpoint, String receivedX509CommonName,
146 149 String expectedX509CommonName) {
... ... @@ -169,8 +172,8 @@ public class LwM2MTransportServerConfiguration {
169 172 * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks
170 173 */
171 174 try {
172   - X509Certificate serverCertificate = (X509Certificate) this.context.getCtxServer().getKeyStoreValue().getCertificate(this.context.getCtxServer().getServerAlias());
173   - PrivateKey privateKey = (PrivateKey) this.context.getCtxServer().getKeyStoreValue().getKey(this.context.getCtxServer().getServerAlias(), this.context.getCtxServer().getKeyStorePasswordServer() == null ? null : this.context.getCtxServer().getKeyStorePasswordServer().toCharArray());
  175 + X509Certificate serverCertificate = (X509Certificate) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getCertificate(this.context.getLwM2MTransportConfigServer().getServerAlias());
  176 + PrivateKey privateKey = (PrivateKey) this.context.getLwM2MTransportConfigServer().getKeyStoreValue().getKey(this.context.getLwM2MTransportConfigServer().getServerAlias(), this.context.getLwM2MTransportConfigServer().getKeyStorePasswordServer() == null ? null : this.context.getLwM2MTransportConfigServer().getKeyStorePasswordServer().toCharArray());
174 177 PublicKey publicKey = serverCertificate.getPublicKey();
175 178 if (serverCertificate != null &&
176 179 privateKey != null && privateKey.getEncoded().length > 0 &&
... ... @@ -203,8 +206,8 @@ public class LwM2MTransportServerConfiguration {
203 206 private void infoPramsUri(String mode) {
204 207 log.info("Server uses [{}]: serverNoSecureURI : [{}], serverSecureURI : [{}]",
205 208 mode,
206   - this.context.getCtxServer().getServerHost() + ":" + this.context.getCtxServer().getServerPortNoSec(),
207   - this.context.getCtxServer().getServerHostSecurity() + ":" + this.context.getCtxServer().getServerPortSecurity());
  209 + this.context.getLwM2MTransportConfigServer().getServerHost() + ":" + this.context.getLwM2MTransportConfigServer().getServerPortNoSec(),
  210 + this.context.getLwM2MTransportConfigServer().getServerHostSecurity() + ":" + this.context.getLwM2MTransportConfigServer().getServerPortSecurity());
208 211 }
209 212
210 213 private boolean setServerRPK(LeshanServerBuilder builder) {
... ... @@ -234,27 +237,27 @@ public class LwM2MTransportServerConfiguration {
234 237 AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC");
235 238 algoParameters.init(new ECGenParameterSpec("secp256r1"));
236 239 ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class);
237   - if (this.context.getCtxServer().getServerPublicX() != null &&
238   - !this.context.getCtxServer().getServerPublicX().isEmpty() &&
239   - this.context.getCtxServer().getServerPublicY() != null &&
240   - !this.context.getCtxServer().getServerPublicY().isEmpty()) {
  240 + if (this.context.getLwM2MTransportConfigServer().getServerPublicX() != null &&
  241 + !this.context.getLwM2MTransportConfigServer().getServerPublicX().isEmpty() &&
  242 + this.context.getLwM2MTransportConfigServer().getServerPublicY() != null &&
  243 + !this.context.getLwM2MTransportConfigServer().getServerPublicY().isEmpty()) {
241 244 /** Get point values */
242   - byte[] publicX = Hex.decodeHex(this.context.getCtxServer().getServerPublicX().toCharArray());
243   - byte[] publicY = Hex.decodeHex(this.context.getCtxServer().getServerPublicY().toCharArray());
  245 + byte[] publicX = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPublicX().toCharArray());
  246 + byte[] publicY = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPublicY().toCharArray());
244 247 /** Create key specs */
245 248 KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)),
246 249 parameterSpec);
247 250 /** Get keys */
248 251 this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec);
249 252 }
250   - if (this.context.getCtxServer().getServerPrivateEncoded() != null &&
251   - !this.context.getCtxServer().getServerPrivateEncoded().isEmpty()) {
  253 + if (this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded() != null &&
  254 + !this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded().isEmpty()) {
252 255 /** Get private key */
253   - byte[] privateS = Hex.decodeHex(this.context.getCtxServer().getServerPrivateEncoded().toCharArray());
  256 + byte[] privateS = Hex.decodeHex(this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded().toCharArray());
254 257 try {
255 258 this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS));
256 259 } catch (InvalidKeySpecException ignore2) {
257   - log.error("Invalid Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", this.context.getCtxServer().getServerPrivateEncoded());
  260 + log.error("Invalid Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", this.context.getLwM2MTransportConfigServer().getServerPrivateEncoded());
258 261 }
259 262 }
260 263 }
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerInitializer.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerInitializer.java
... ... @@ -18,8 +18,8 @@ package org.thingsboard.server.transport.lwm2m.server;
18 18 import lombok.extern.slf4j.Slf4j;
19 19 import org.eclipse.leshan.server.californium.LeshanServer;
20 20 import org.springframework.beans.factory.annotation.Autowired;
21   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
22 21 import org.springframework.stereotype.Component;
  22 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
23 23 import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC;
24 24
25 25 import javax.annotation.PostConstruct;
... ... @@ -27,21 +27,21 @@ import javax.annotation.PreDestroy;
27 27
28 28 @Slf4j
29 29 @Component("LwM2MTransportServerInitializer")
30   -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
31   -public class LwM2MTransportServerInitializer {
  30 +@TbLwM2mTransportComponent
  31 +public class LwM2mTransportServerInitializer {
32 32
33 33 @Autowired
34   - private LwM2MTransportServiceImpl service;
  34 + private LwM2mTransportServiceImpl service;
35 35
36 36 @Autowired(required = false)
37 37 private LeshanServer leshanServer;
38 38
39 39 @Autowired
40   - private LwM2MTransportContextServer context;
  40 + private LwM2mTransportContextServer context;
41 41
42 42 @PostConstruct
43 43 public void init() {
44   - if (this.context.getCtxServer().getEnableGenNewKeyPskRpk()) {
  44 + if (this.context.getLwM2MTransportConfigServer().getEnableGenNewKeyPskRpk()) {
45 45 new LWM2MGenerationPSkRPkECC();
46 46 }
47 47 this.startLhServer();
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java
... ... @@ -26,7 +26,7 @@ import org.thingsboard.server.gen.transport.TransportProtos;
26 26 import java.util.Collection;
27 27 import java.util.Optional;
28 28
29   -public interface LwM2MTransportService {
  29 +public interface LwM2mTransportService {
30 30
31 31 void onRegistered(LeshanServer lwServer, Registration registration, Collection<Observation> previousObsersations);
32 32
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServiceImpl.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServiceImpl.java
... ... @@ -36,7 +36,6 @@ import org.eclipse.leshan.core.util.NamedThreadFactory;
36 36 import org.eclipse.leshan.server.californium.LeshanServer;
37 37 import org.eclipse.leshan.server.registration.Registration;
38 38 import org.springframework.beans.factory.annotation.Autowired;
39   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
40 39 import org.springframework.stereotype.Service;
41 40 import org.thingsboard.server.common.data.Device;
42 41 import org.thingsboard.server.common.data.DeviceProfile;
... ... @@ -48,11 +47,12 @@ import org.thingsboard.server.gen.transport.TransportProtos;
48 47 import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
49 48 import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent;
50 49 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
51   -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient;
52   -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientProfile;
  50 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  51 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  52 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
  53 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
53 54 import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue;
54 55 import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters;
55   -import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore;
56 56 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
57 57
58 58 import javax.annotation.PostConstruct;
... ... @@ -79,24 +79,24 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
79 79 import java.util.stream.Collectors;
80 80
81 81 import static org.thingsboard.server.common.transport.util.JsonUtils.getJsonObject;
82   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.CLIENT_NOT_AUTHORIZED;
83   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEVICE_ATTRIBUTES_REQUEST;
84   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEVICE_ATTRIBUTES_TOPIC;
85   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.DEVICE_TELEMETRY_TOPIC;
86   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_OBSERVE;
87   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.GET_TYPE_OPER_READ;
88   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_ERROR;
89   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_INFO;
90   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.LOG_LW2M_TELEMETRY;
91   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_EXECUTE;
92   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.POST_TYPE_OPER_WRITE_REPLACE;
93   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.SERVICE_CHANNEL;
94   -import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getAckCallback;
  82 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.CLIENT_NOT_AUTHORIZED;
  83 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_REQUEST;
  84 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_TOPIC;
  85 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC;
  86 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_OBSERVE;
  87 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_READ;
  88 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR;
  89 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
  90 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY;
  91 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_EXECUTE;
  92 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_WRITE_REPLACE;
  93 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVICE_CHANNEL;
  94 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getAckCallback;
95 95
96 96 @Slf4j
97   -@Service("LwM2MTransportService")
98   -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
99   -public class LwM2MTransportServiceImpl implements LwM2MTransportService {
  97 +@Service
  98 +@TbLwM2mTransportComponent
  99 +public class LwM2mTransportServiceImpl implements LwM2mTransportService {
100 100
101 101 private ExecutorService executorRegistered;
102 102 private ExecutorService executorUpdateRegistered;
... ... @@ -105,27 +105,29 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
105 105 protected final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
106 106 protected final Lock writeLock = readWriteLock.writeLock();
107 107
108   -
109 108 @Autowired
110 109 private TransportService transportService;
111 110
112 111 @Autowired
113   - public LwM2MTransportContextServer context;
  112 + public LwM2mTransportContextServer context;
114 113
115 114 @Autowired
116   - private LwM2MTransportRequest lwM2MTransportRequest;
  115 + private LwM2mTransportRequest lwM2mTransportRequest;
117 116
118 117 @Autowired
119   - LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore;
  118 + private LwM2mClientContext lwM2mClientContext;
  119 +
  120 + @Autowired(required = false)
  121 + private LeshanServer leshanServer;
120 122
121 123 @PostConstruct
122 124 public void init() {
123   - this.context.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) context.getCtxServer().getSessionReportTimeout()), context.getCtxServer().getSessionReportTimeout(), TimeUnit.MILLISECONDS);
124   - this.executorRegistered = Executors.newFixedThreadPool(this.context.getCtxServer().getRegisteredPoolSize(),
  125 + this.context.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) context.getLwM2MTransportConfigServer().getSessionReportTimeout()), context.getLwM2MTransportConfigServer().getSessionReportTimeout(), TimeUnit.MILLISECONDS);
  126 + this.executorRegistered = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getRegisteredPoolSize(),
125 127 new NamedThreadFactory(String.format("LwM2M %s channel registered", SERVICE_CHANNEL)));
126   - this.executorUpdateRegistered = Executors.newFixedThreadPool(this.context.getCtxServer().getUpdateRegisteredPoolSize(),
  128 + this.executorUpdateRegistered = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getUpdateRegisteredPoolSize(),
127 129 new NamedThreadFactory(String.format("LwM2M %s channel update registered", SERVICE_CHANNEL)));
128   - this.executorUnRegistered = Executors.newFixedThreadPool(this.context.getCtxServer().getUnRegisteredPoolSize(),
  130 + this.executorUnRegistered = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getUnRegisteredPoolSize(),
129 131 new NamedThreadFactory(String.format("LwM2M %s channel un registered", SERVICE_CHANNEL)));
130 132 this.converter = LwM2mValueConverterImpl.getInstance();
131 133 }
... ... @@ -149,17 +151,16 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
149 151 executorRegistered.submit(() -> {
150 152 try {
151 153 log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId());
152   - LwM2MClient lwM2MClient = this.lwM2mInMemorySecurityStore.updateInSessionsLwM2MClient(lwServer, registration);
  154 + LwM2mClient lwM2MClient = this.lwM2mClientContext.updateInSessionsLwM2MClient(registration);
153 155 if (lwM2MClient != null) {
154   - lwM2MClient.setLwM2MTransportServiceImpl(this);
155 156 this.sentLogsToThingsboard(LOG_LW2M_INFO + ": Client Registered", registration);
156 157 SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration);
157 158 if (sessionInfo != null) {
158   - lwM2MClient.setDeviceUuid(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
159   - lwM2MClient.setProfileUuid(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
  159 + lwM2MClient.setDeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
  160 + lwM2MClient.setProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
160 161 lwM2MClient.setDeviceName(sessionInfo.getDeviceName());
161 162 lwM2MClient.setDeviceProfileName(sessionInfo.getDeviceType());
162   - transportService.registerAsyncSession(sessionInfo, new LwM2MSessionMsgListener(this, sessionInfo));
  163 + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
163 164 transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null);
164 165 transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
165 166 this.sentLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration);
... ... @@ -221,8 +222,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
221 222 if (sessionInfo != null) {
222 223 transportService.deregisterSession(sessionInfo);
223 224 this.doCloseSession(sessionInfo);
224   - lwM2mInMemorySecurityStore.delRemoveSessionAndListener(registration.getId());
225   - if (lwM2mInMemorySecurityStore.getProfiles().size() > 0) {
  225 + lwM2mClientContext.delRemoveSessionAndListener(registration.getId());
  226 + if (lwM2mClientContext.getProfiles().size() > 0) {
226 227 this.syncSessionsAndProfiles();
227 228 }
228 229 log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());
... ... @@ -292,13 +293,13 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
292 293 el.getAsJsonObject().entrySet().forEach(de -> {
293 294 String path = this.getPathAttributeUpdate(sessionInfo, de.getKey());
294 295 String value = de.getValue().getAsString();
295   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue();
296   - LwM2MClientProfile profile = lwM2mInMemorySecurityStore.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
297   - ResourceModel resourceModel = context.getCtxServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(path));
  296 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
  297 + LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
  298 + ResourceModel resourceModel = context.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(path));
298 299 if (!path.isEmpty() && (this.validatePathInAttrProfile(profile, path) || this.validatePathInTelemetryProfile(profile, path))) {
299 300 if (resourceModel != null && resourceModel.operations.isWritable()) {
300   - lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE,
301   - ContentFormat.TLV.getName(), null, value, this.context.getCtxServer().getTimeout());
  301 + lwM2mTransportRequest.sendAllRequest(leshanServer, lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE,
  302 + ContentFormat.TLV.getName(), null, value, this.context.getLwM2MTransportConfigServer().getTimeout());
302 303 } else {
303 304 log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value);
304 305 String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated",
... ... @@ -323,9 +324,9 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
323 324 */
324 325 @Override
325 326 public void onDeviceProfileUpdate(SessionInfoProto sessionInfo, DeviceProfile deviceProfile) {
326   - Set<String> registrationIds = lwM2mInMemorySecurityStore.getSessions().entrySet()
  327 + Set<String> registrationIds = lwM2mClientContext.getLwM2mClients().entrySet()
327 328 .stream()
328   - .filter(e -> e.getValue().getProfileUuid().equals(deviceProfile.getUuidId()))
  329 + .filter(e -> e.getValue().getProfileId().equals(deviceProfile.getUuidId()))
329 330 .map(Map.Entry::getKey).sorted().collect(Collectors.toCollection(LinkedHashSet::new));
330 331 if (registrationIds.size() > 0) {
331 332 this.onDeviceUpdateChangeProfile(registrationIds, deviceProfile);
... ... @@ -339,8 +340,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
339 340 */
340 341 @Override
341 342 public void onDeviceUpdate(SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) {
342   - Optional<String> registrationIdOpt = lwM2mInMemorySecurityStore.getSessions().entrySet().stream()
343   - .filter(e -> device.getUuidId().equals(e.getValue().getDeviceUuid()))
  343 + Optional<String> registrationIdOpt = lwM2mClientContext.getLwM2mClients().entrySet().stream()
  344 + .filter(e -> device.getUuidId().equals(e.getValue().getDeviceId()))
344 345 .map(Map.Entry::getKey)
345 346 .findFirst();
346 347 registrationIdOpt.ifPresent(registrationId -> this.onDeviceUpdateLwM2MClient(registrationId, device, deviceProfileOpt));
... ... @@ -353,8 +354,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
353 354 */
354 355 @Override
355 356 public void doTrigger(LeshanServer lwServer, Registration registration, String path) {
356   - lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_EXECUTE,
357   - ContentFormat.TLV.getName(), null, null, this.context.getCtxServer().getTimeout());
  357 + lwM2mTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_EXECUTE,
  358 + ContentFormat.TLV.getName(), null, null, this.context.getLwM2MTransportConfigServer().getTimeout());
358 359 }
359 360
360 361 /**
... ... @@ -397,18 +398,18 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
397 398 * Removes a profile if not used in sessions
398 399 */
399 400 private void syncSessionsAndProfiles() {
400   - Map<UUID, LwM2MClientProfile> profilesClone = lwM2mInMemorySecurityStore.getProfiles().entrySet()
  401 + Map<UUID, LwM2mClientProfile> profilesClone = lwM2mClientContext.getProfiles().entrySet()
401 402 .stream()
402 403 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
403 404 profilesClone.forEach((k, v) -> {
404   - String registrationId = lwM2mInMemorySecurityStore.getSessions().entrySet()
  405 + String registrationId = lwM2mClientContext.getLwM2mClients().entrySet()
405 406 .stream()
406   - .filter(e -> e.getValue().getProfileUuid().equals(k))
  407 + .filter(e -> e.getValue().getProfileId().equals(k))
407 408 .findFirst()
408 409 .map(Map.Entry::getKey) // return the key of the matching entry if found
409 410 .orElse("");
410 411 if (registrationId.isEmpty()) {
411   - lwM2mInMemorySecurityStore.getProfiles().remove(k);
  412 + lwM2mClientContext.getProfiles().remove(k);
412 413 }
413 414 });
414 415 }
... ... @@ -458,12 +459,12 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
458 459 * @param registration - Registration LwM2M Client
459 460 * @param lwM2MClient - object with All parameters off client
460 461 */
461   - private void initLwM2mFromClientValue(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient) {
462   - LwM2MClientProfile lwM2MClientProfile = lwM2mInMemorySecurityStore.getProfile(registration.getId());
  462 + private void initLwM2mFromClientValue(LeshanServer lwServer, Registration registration, LwM2mClient lwM2MClient) {
  463 + LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);
463 464 Set<String> clientObjects = this.getAllOjectsInClient(registration);
464   - if (clientObjects != null && !LwM2MTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
  465 + if (clientObjects != null && !LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
465 466 // #2
466   - if (!LwM2MTransportHandler.getClientUpdateValueAfterConnect(lwM2MClientProfile)) {
  467 + if (!LwM2mTransportHandler.getClientUpdateValueAfterConnect(lwM2MClientProfile)) {
467 468 this.initReadAttrTelemetryObserveToClient(lwServer, registration, lwM2MClient, GET_TYPE_OPER_READ);
468 469
469 470 }
... ... @@ -471,8 +472,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
471 472 else {
472 473 lwM2MClient.getPendingRequests().addAll(clientObjects);
473 474 clientObjects.forEach(path -> {
474   - lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, GET_TYPE_OPER_READ, ContentFormat.TLV.getName(),
475   - null, null, this.context.getCtxServer().getTimeout());
  475 + lwM2mTransportRequest.sendAllRequest(lwServer, registration, path, GET_TYPE_OPER_READ, ContentFormat.TLV.getName(),
  476 + null, null, this.context.getLwM2MTransportConfigServer().getTimeout());
476 477 });
477 478 }
478 479 }
... ... @@ -517,7 +518,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
517 518 * @param path - resource
518 519 */
519 520 private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) {
520   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(registration, null);
  521 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
521 522 lwM2MClient.updateResourceValue(path, lwM2mResource);
522 523 Set<String> paths = new HashSet<>();
523 524 paths.add(path);
... ... @@ -565,8 +566,9 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
565 566 * @param path -
566 567 * @return true if path isPresent in postAttributeProfile
567 568 */
568   - private boolean validatePathInAttrProfile(LwM2MClientProfile profile, String path) {
569   - Set<String> attributesSet = new Gson().fromJson(profile.getPostAttributeProfile(), new TypeToken<>(){}.getType());
  569 + private boolean validatePathInAttrProfile(LwM2mClientProfile profile, String path) {
  570 + Set<String> attributesSet = new Gson().fromJson(profile.getPostAttributeProfile(), new TypeToken<>() {
  571 + }.getType());
570 572 return attributesSet.stream().filter(p -> p.equals(path)).findFirst().isPresent();
571 573 }
572 574
... ... @@ -575,8 +577,9 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
575 577 * @param path -
576 578 * @return true if path isPresent in postAttributeProfile
577 579 */
578   - private boolean validatePathInTelemetryProfile(LwM2MClientProfile profile, String path) {
579   - Set<String> telemetriesSet = new Gson().fromJson(profile.getPostTelemetryProfile(), new TypeToken<>(){}.getType());
  580 + private boolean validatePathInTelemetryProfile(LwM2mClientProfile profile, String path) {
  581 + Set<String> telemetriesSet = new Gson().fromJson(profile.getPostTelemetryProfile(), new TypeToken<>() {
  582 + }.getType());
580 583 return telemetriesSet.stream().filter(p -> p.equals(path)).findFirst().isPresent();
581 584 }
582 585
... ... @@ -588,16 +591,19 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
588 591 * @param lwServer -
589 592 * @param registration -
590 593 */
591   - private void initReadAttrTelemetryObserveToClient(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient, String typeOper) {
  594 + private void initReadAttrTelemetryObserveToClient(LeshanServer lwServer, Registration registration, LwM2mClient lwM2MClient, String typeOper) {
592 595 try {
593   - LwM2MClientProfile lwM2MClientProfile = lwM2mInMemorySecurityStore.getProfile(registration.getId());
  596 + LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);
594 597 Set<String> clientInstances = this.getAllInstancesInClient(registration);
595 598 Set<String> result;
596 599 if (GET_TYPE_OPER_READ.equals(typeOper)) {
597   - result = new ObjectMapper().readValue(lwM2MClientProfile.getPostAttributeProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {});
598   - result.addAll(new ObjectMapper().readValue(lwM2MClientProfile.getPostTelemetryProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {}));
  600 + result = new ObjectMapper().readValue(lwM2MClientProfile.getPostAttributeProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {
  601 + });
  602 + result.addAll(new ObjectMapper().readValue(lwM2MClientProfile.getPostTelemetryProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {
  603 + }));
599 604 } else {
600   - result = new ObjectMapper().readValue(lwM2MClientProfile.getPostObserveProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {});
  605 + result = new ObjectMapper().readValue(lwM2MClientProfile.getPostObserveProfile().getAsJsonArray().toString().getBytes(), new TypeReference<>() {
  606 + });
601 607 }
602 608 Set<String> pathSent = ConcurrentHashMap.newKeySet();
603 609 result.forEach(p -> {
... ... @@ -611,8 +617,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
611 617 });
612 618 lwM2MClient.getPendingRequests().addAll(pathSent);
613 619 pathSent.forEach(target -> {
614   - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, ContentFormat.TLV.getName(),
615   - null, null, this.context.getCtxServer().getTimeout());
  620 + lwM2mTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, ContentFormat.TLV.getName(),
  621 + null, null, this.context.getLwM2MTransportConfigServer().getTimeout());
616 622 });
617 623 if (GET_TYPE_OPER_OBSERVE.equals(typeOper)) {
618 624 lwM2MClient.initValue(this, null);
... ... @@ -630,15 +636,15 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
630 636 * @param device -
631 637 */
632 638 private void onDeviceUpdateLwM2MClient(String registrationId, Device device, Optional<DeviceProfile> deviceProfileOpt) {
633   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSessions().get(registrationId);
  639 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClients().get(registrationId);
634 640 lwM2MClient.setDeviceName(device.getName());
635   - if (!lwM2MClient.getProfileUuid().equals(device.getDeviceProfileId().getId())) {
  641 + if (!lwM2MClient.getProfileId().equals(device.getDeviceProfileId().getId())) {
636 642 Set<String> registrationIds = new HashSet<>();
637 643 registrationIds.add(registrationId);
638 644 deviceProfileOpt.ifPresent(deviceProfile -> this.onDeviceUpdateChangeProfile(registrationIds, deviceProfile));
639 645 }
640 646
641   - lwM2MClient.setProfileUuid(device.getDeviceProfileId().getId());
  647 + lwM2MClient.setProfileId(device.getDeviceProfileId().getId());
642 648 }
643 649
644 650 /**
... ... @@ -693,20 +699,20 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
693 699 * @param path
694 700 */
695 701 private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) {
696   - LwM2MClientProfile lwM2MClientProfile = lwM2mInMemorySecurityStore.getProfile(registration.getId());
  702 + LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);
697 703 lwM2MClientProfile.getPostAttributeProfile().forEach(p -> {
698   - LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString());
  704 + LwM2mPath pathIds = new LwM2mPath(p.getAsString());
699 705 if (pathIds.isResource()) {
700 706 if (path == null || path.contains(p.getAsString())) {
701   - this.addParameters(p.getAsString().toString(), attributes, registration);
  707 + this.addParameters(p.getAsString(), attributes, registration);
702 708 }
703 709 }
704 710 });
705 711 lwM2MClientProfile.getPostTelemetryProfile().forEach(p -> {
706   - LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString());
  712 + LwM2mPath pathIds = new LwM2mPath(p.getAsString());
707 713 if (pathIds.isResource()) {
708 714 if (path == null || path.contains(p.getAsString())) {
709   - this.addParameters(p.getAsString().toString(), telemetry, registration);
  715 + this.addParameters(p.getAsString(), telemetry, registration);
710 716 }
711 717 }
712 718 });
... ... @@ -717,8 +723,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
717 723 * @param registration - Registration LwM2M Client
718 724 */
719 725 private void addParameters(String path, JsonObject parameters, Registration registration) {
720   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getSessions().get(registration.getId());
721   - JsonObject names = lwM2mInMemorySecurityStore.getProfiles().get(lwM2MClient.getProfileUuid()).getPostKeyNameProfile();
  726 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
  727 + JsonObject names = lwM2mClientContext.getProfiles().get(lwM2MClient.getProfileId()).getPostKeyNameProfile();
722 728 String resName = String.valueOf(names.get(path));
723 729 if (resName != null && !resName.isEmpty()) {
724 730 try {
... ... @@ -727,7 +733,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
727 733 parameters.addProperty(resName, resValue);
728 734 }
729 735 } catch (Exception e) {
730   - log.error(e.getStackTrace().toString());
  736 + log.error("Failed to add parameters.", e);
731 737 }
732 738 }
733 739 }
... ... @@ -736,11 +742,11 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
736 742 * @param path - path resource
737 743 * @return - value of Resource or null
738 744 */
739   - private String getResourceValueToString(LwM2MClient lwM2MClient, String path) {
  745 + private String getResourceValueToString(LwM2mClient lwM2MClient, String path) {
740 746 LwM2mPath pathIds = new LwM2mPath(path);
741 747 ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, pathIds);
742   - return (resourceValue == null) ? null :
743   - (String) this.converter.convertValue(resourceValue.getResourceValue(), this.context.getCtxServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds);
  748 + return resourceValue == null ? null :
  749 + this.converter.convertValue(resourceValue.getResourceValue(), this.context.getLwM2MTransportConfigServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds).toString();
744 750 }
745 751
746 752 /**
... ... @@ -749,7 +755,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
749 755 * @param pathIds -
750 756 * @return - return value of Resource by idPath
751 757 */
752   - private ResourceValue returnResourceValueFromLwM2MClient(LwM2MClient lwM2MClient, LwM2mPath pathIds) {
  758 + private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, LwM2mPath pathIds) {
753 759 ResourceValue resourceValue = null;
754 760 if (pathIds.isResource()) {
755 761 resourceValue = lwM2MClient.getResources().get(pathIds.toString());
... ... @@ -790,23 +796,25 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
790 796 * @param deviceProfile -
791 797 */
792 798 private void onDeviceUpdateChangeProfile(Set<String> registrationIds, DeviceProfile deviceProfile) {
793   -
794   - LwM2MClientProfile lwM2MClientProfileOld = lwM2mInMemorySecurityStore.getProfiles().get(deviceProfile.getUuidId());
795   - if (lwM2mInMemorySecurityStore.addUpdateProfileParameters(deviceProfile)) {
796   -
  799 + LwM2mClientProfile lwM2MClientProfileOld = lwM2mClientContext.getProfiles().get(deviceProfile.getUuidId());
  800 + if (lwM2mClientContext.addUpdateProfileParameters(deviceProfile)) {
797 801 // #1
798 802 JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile();
799   - Set<String> attributeSetOld = new Gson().fromJson(attributeOld, new TypeToken<>(){}.getType());
  803 + Set<String> attributeSetOld = new Gson().fromJson(attributeOld, new TypeToken<>() {
  804 + }.getType());
800 805 JsonArray telemetryOld = lwM2MClientProfileOld.getPostTelemetryProfile();
801   - Set<String> telemetrySetOld = new Gson().fromJson(telemetryOld, new TypeToken<>(){}.getType());
  806 + Set<String> telemetrySetOld = new Gson().fromJson(telemetryOld, new TypeToken<>() {
  807 + }.getType());
802 808 JsonArray observeOld = lwM2MClientProfileOld.getPostObserveProfile();
803 809 JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile();
804 810
805   - LwM2MClientProfile lwM2MClientProfileNew = lwM2mInMemorySecurityStore.getProfiles().get(deviceProfile.getUuidId());
  811 + LwM2mClientProfile lwM2MClientProfileNew = lwM2mClientContext.getProfiles().get(deviceProfile.getUuidId());
806 812 JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile();
807   - Set<String> attributeSetNew = new Gson().fromJson(attributeNew, new TypeToken<>(){}.getType());
  813 + Set<String> attributeSetNew = new Gson().fromJson(attributeNew, new TypeToken<>() {
  814 + }.getType());
808 815 JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile();
809   - Set<String> telemetrySetNew = new Gson().fromJson(telemetryNew, new TypeToken<>(){}.getType());
  816 + Set<String> telemetrySetNew = new Gson().fromJson(telemetryNew, new TypeToken<>() {
  817 + }.getType());
810 818 JsonArray observeNew = lwM2MClientProfileNew.getPostObserveProfile();
811 819 JsonObject keyNameNew = lwM2MClientProfileNew.getPostKeyNameProfile();
812 820
... ... @@ -814,20 +822,24 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
814 822 ResultsAnalyzerParameters sentAttrToThingsboard = new ResultsAnalyzerParameters();
815 823 // #3.1
816 824 if (!attributeOld.equals(attributeNew)) {
817   - ResultsAnalyzerParameters postAttributeAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(attributeOld, new TypeToken<Set<String>>(){}.getType()), attributeSetNew);
  825 + ResultsAnalyzerParameters postAttributeAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(attributeOld, new TypeToken<Set<String>>() {
  826 + }.getType()), attributeSetNew);
818 827 sentAttrToThingsboard.getPathPostParametersAdd().addAll(postAttributeAnalyzer.getPathPostParametersAdd());
819 828 sentAttrToThingsboard.getPathPostParametersDel().addAll(postAttributeAnalyzer.getPathPostParametersDel());
820 829 }
821 830 // #3.2
822   - if (!attributeOld.equals(attributeNew)) {
823   - ResultsAnalyzerParameters postTelemetryAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(telemetryOld, new TypeToken<Set<String>>(){}.getType()), telemetrySetNew);
  831 + if (!telemetryOld.equals(telemetryNew)) {
  832 + ResultsAnalyzerParameters postTelemetryAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(telemetryOld, new TypeToken<Set<String>>() {
  833 + }.getType()), telemetrySetNew);
824 834 sentAttrToThingsboard.getPathPostParametersAdd().addAll(postTelemetryAnalyzer.getPathPostParametersAdd());
825 835 sentAttrToThingsboard.getPathPostParametersDel().addAll(postTelemetryAnalyzer.getPathPostParametersDel());
826 836 }
827 837 // #3.3
828 838 if (!keyNameOld.equals(keyNameNew)) {
829   - ResultsAnalyzerParameters keyNameChange = this.getAnalyzerKeyName(new Gson().fromJson(keyNameOld.toString(), new TypeToken<ConcurrentHashMap<String, String>>(){}.getType()),
830   - new Gson().fromJson(keyNameNew.toString(), new TypeToken<ConcurrentHashMap<String, String>>(){}.getType()));
  839 + ResultsAnalyzerParameters keyNameChange = this.getAnalyzerKeyName(new Gson().fromJson(keyNameOld.toString(), new TypeToken<ConcurrentHashMap<String, String>>() {
  840 + }.getType()),
  841 + new Gson().fromJson(keyNameNew.toString(), new TypeToken<ConcurrentHashMap<String, String>>() {
  842 + }.getType()));
831 843 sentAttrToThingsboard.getPathPostParametersAdd().addAll(keyNameChange.getPathPostParametersAdd());
832 844 }
833 845
... ... @@ -835,9 +847,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
835 847 if (sentAttrToThingsboard.getPathPostParametersAdd().size() > 0) {
836 848 // update value in Resources
837 849 registrationIds.forEach(registrationId -> {
838   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(null, registrationId);
839   - LeshanServer lwServer = lwM2MClient.getLwServer();
840   - Registration registration = lwM2mInMemorySecurityStore.getByRegistration(registrationId);
  850 + LeshanServer lwServer = leshanServer;
  851 + Registration registration = lwM2mClientContext.getRegistration(registrationId);
841 852 this.readResourceValueObserve(lwServer, registration, sentAttrToThingsboard.getPathPostParametersAdd(), GET_TYPE_OPER_READ);
842 853 // sent attr/telemetry to tingsboard for new path
843 854 this.updateAttrTelemetry(registration, false, sentAttrToThingsboard.getPathPostParametersAdd());
... ... @@ -851,8 +862,10 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
851 862
852 863 // #5.1
853 864 if (!observeOld.equals(observeNew)) {
854   - Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<>(){}.getType());
855   - Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<>(){}.getType());
  865 + Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<>() {
  866 + }.getType());
  867 + Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<>() {
  868 + }.getType());
856 869 //#5.2 add
857 870 // path Attr/Telemetry includes newObserve
858 871 attributeSetOld.addAll(telemetrySetOld);
... ... @@ -863,9 +876,8 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
863 876 ResultsAnalyzerParameters postObserveAnalyzer = this.getAnalyzerParameters(sentObserveToClientOld.getPathPostParametersAdd(), sentObserveToClientNew.getPathPostParametersAdd());
864 877 // sent Request observe to Client
865 878 registrationIds.forEach(registrationId -> {
866   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(null, registrationId);
867   - LeshanServer lwServer = lwM2MClient.getLwServer();
868   - Registration registration = lwM2mInMemorySecurityStore.getByRegistration(registrationId);
  879 + LeshanServer lwServer = leshanServer;
  880 + Registration registration = lwM2mClientContext.getRegistration(registrationId);
869 881 this.readResourceValueObserve(lwServer, registration, postObserveAnalyzer.getPathPostParametersAdd(), GET_TYPE_OPER_OBSERVE);
870 882 // 5.3 del
871 883 // sent Request cancel observe to Client
... ... @@ -914,11 +926,11 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
914 926 LwM2mPath pathIds = new LwM2mPath(target);
915 927 if (pathIds.isResource()) {
916 928 if (GET_TYPE_OPER_READ.equals(typeOper)) {
917   - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper,
918   - ContentFormat.TLV.getName(), null, null, this.context.getCtxServer().getTimeout());
  929 + lwM2mTransportRequest.sendAllRequest(lwServer, registration, target, typeOper,
  930 + ContentFormat.TLV.getName(), null, null, this.context.getLwM2MTransportConfigServer().getTimeout());
919 931 } else if (GET_TYPE_OPER_OBSERVE.equals(typeOper)) {
920   - lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper,
921   - null, null, null, this.context.getCtxServer().getTimeout());
  932 + lwM2mTransportRequest.sendAllRequest(lwServer, registration, target, typeOper,
  933 + null, null, null, this.context.getLwM2MTransportConfigServer().getTimeout());
922 934 }
923 935 }
924 936 });
... ... @@ -935,7 +947,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
935 947 }
936 948
937 949 private void cancelObserveIsValue(LeshanServer lwServer, Registration registration, Set<String> paramAnallyzer) {
938   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(registration, null);
  950 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
939 951 paramAnallyzer.forEach(p -> {
940 952 if (this.returnResourceValueFromLwM2MClient(lwM2MClient, new LwM2mPath(p)) != null) {
941 953 this.setCancelObservationRecourse(lwServer, registration, p);
... ... @@ -944,10 +956,10 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
944 956 );
945 957 }
946 958
947   - private void putDelayedUpdateResourcesClient(LwM2MClient lwM2MClient, Object valueOld, Object valueNew, String path) {
  959 + private void putDelayedUpdateResourcesClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) {
948 960 if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) {
949   - lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE,
950   - ContentFormat.TLV.getName(), null, valueNew, this.context.getCtxServer().getTimeout());
  961 + lwM2mTransportRequest.sendAllRequest(leshanServer, lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE,
  962 + ContentFormat.TLV.getName(), null, valueNew, this.context.getLwM2MTransportConfigServer().getTimeout());
951 963 } else {
952 964 log.error("05 delayError");
953 965 }
... ... @@ -982,7 +994,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
982 994 * @return -
983 995 */
984 996 private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
985   - LwM2MClientProfile profile = lwM2mInMemorySecurityStore.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
  997 + LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
986 998 return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
987 999 .filter(e -> e.getValue().getAsString().equals(name)).findFirst().map(Map.Entry::getKey)
988 1000 .orElse("");
... ... @@ -1002,7 +1014,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
1002 1014 */
1003 1015 public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) {
1004 1016 try {
1005   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(sessionInfo);
  1017 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2MClient(sessionInfo);
1006 1018 attributesResponse.getSharedAttributeListList().forEach(attr -> {
1007 1019 String path = this.getPathAttributeUpdate(sessionInfo, attr.getKv().getKey());
1008 1020 // #1.1
... ... @@ -1027,18 +1039,18 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
1027 1039 * @param lwM2MClient -
1028 1040 * @return
1029 1041 */
1030   - private SessionInfoProto getNewSessionInfoProto(LwM2MClient lwM2MClient) {
  1042 + private SessionInfoProto getNewSessionInfoProto(LwM2mClient lwM2MClient) {
1031 1043 if (lwM2MClient != null) {
1032 1044 TransportProtos.ValidateDeviceCredentialsResponseMsg msg = lwM2MClient.getCredentialsResponse();
1033 1045 if (msg == null || msg.getDeviceInfo() == null) {
1034   - log.error("[{}] [{}]", lwM2MClient.getEndPoint(), CLIENT_NOT_AUTHORIZED);
  1046 + log.error("[{}] [{}]", lwM2MClient.getEndpoint(), CLIENT_NOT_AUTHORIZED);
1035 1047 this.closeClientSession(lwM2MClient.getRegistration());
1036 1048 return null;
1037 1049 } else {
1038 1050 return SessionInfoProto.newBuilder()
1039 1051 .setNodeId(this.context.getNodeId())
1040   - .setSessionIdMSB(lwM2MClient.getSessionUuid().getMostSignificantBits())
1041   - .setSessionIdLSB(lwM2MClient.getSessionUuid().getLeastSignificantBits())
  1052 + .setSessionIdMSB(lwM2MClient.getSessionId().getMostSignificantBits())
  1053 + .setSessionIdLSB(lwM2MClient.getSessionId().getLeastSignificantBits())
1042 1054 .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB())
1043 1055 .setDeviceIdLSB(msg.getDeviceInfo().getDeviceIdLSB())
1044 1056 .setTenantIdMSB(msg.getDeviceInfo().getTenantIdMSB())
... ... @@ -1053,13 +1065,12 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
1053 1065 return null;
1054 1066 }
1055 1067
1056   -
1057 1068 /**
1058 1069 * @param registration - Registration LwM2M Client
1059 1070 * @return - sessionInfo after access connect client
1060 1071 */
1061 1072 private SessionInfoProto getValidateSessionInfo(Registration registration) {
1062   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(registration, null);
  1073 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
1063 1074 return getNewSessionInfoProto(lwM2MClient);
1064 1075 }
1065 1076
... ... @@ -1068,7 +1079,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
1068 1079 * @return -
1069 1080 */
1070 1081 private SessionInfoProto getValidateSessionInfo(String registrationId) {
1071   - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClientWithReg(null, registrationId);
  1082 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(null, registrationId);
1072 1083 return getNewSessionInfoProto(lwM2MClient);
1073 1084 }
1074 1085
... ... @@ -1079,12 +1090,12 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
1079 1090 */
1080 1091 private void checkInactivity(SessionInfoProto sessionInfo) {
1081 1092 if (transportService.reportActivity(sessionInfo) == null) {
1082   - transportService.registerAsyncSession(sessionInfo, new LwM2MSessionMsgListener(this, sessionInfo));
  1093 + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
1083 1094 }
1084 1095 }
1085 1096
1086 1097 private void checkInactivityAndReportActivity() {
1087   - lwM2mInMemorySecurityStore.getSessions().forEach((key, value) -> this.checkInactivity(this.getValidateSessionInfo(key)));
  1098 + lwM2mClientContext.getLwM2mClients().forEach((key, value) -> this.checkInactivity(this.getValidateSessionInfo(key)));
1088 1099 }
1089 1100
1090 1101 /**
... ... @@ -1095,7 +1106,7 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
1095 1106 *
1096 1107 * @param lwM2MClient - LwM2M Client
1097 1108 */
1098   - public void putDelayedUpdateResourcesThingsboard(LwM2MClient lwM2MClient) {
  1109 + public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) {
1099 1110 SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration());
1100 1111 if (sessionInfo != null) {
1101 1112 //#1.1 + #1.2
... ... @@ -1119,15 +1130,16 @@ public class LwM2MTransportServiceImpl implements LwM2MTransportService {
1119 1130 * @param lwM2MClient -
1120 1131 * @return ArrayList keyNames from profile attr resources shared!!!! && IsWritable
1121 1132 */
1122   - private List<String> getNamesAttrFromProfileIsWritable(LwM2MClient lwM2MClient) {
1123   - LwM2MClientProfile profile = lwM2mInMemorySecurityStore.getProfile(lwM2MClient.getProfileUuid());
  1133 + private List<String> getNamesAttrFromProfileIsWritable(LwM2mClient lwM2MClient) {
  1134 + LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId());
1124 1135 Set attrSet = new Gson().fromJson(profile.getPostAttributeProfile(), Set.class);
1125   - ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), new TypeToken<ConcurrentHashMap<String, String>>(){}.getType());
  1136 + ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), new TypeToken<ConcurrentHashMap<String, String>>() {
  1137 + }.getType());
1126 1138
1127 1139 ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet()
1128 1140 .stream()
1129   - .filter(e -> (attrSet.contains(e.getKey()) && context.getCtxServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())) != null &&
1130   - context.getCtxServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())).operations.isWritable()))
  1141 + .filter(e -> (attrSet.contains(e.getKey()) && context.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())) != null &&
  1142 + context.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())).operations.isWritable()))
1131 1143 .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue));
1132 1144
1133 1145 Set<String> namesIsWritable = ConcurrentHashMap.newKeySet();
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java
... ... @@ -20,13 +20,11 @@ import lombok.extern.slf4j.Slf4j;
20 20 import org.eclipse.leshan.core.node.LwM2mMultipleResource;
21 21 import org.eclipse.leshan.core.node.LwM2mResource;
22 22 import org.eclipse.leshan.core.node.LwM2mSingleResource;
23   -import org.eclipse.leshan.server.californium.LeshanServer;
24 23 import org.eclipse.leshan.server.registration.Registration;
25 24 import org.eclipse.leshan.server.security.SecurityInfo;
26 25 import org.thingsboard.server.gen.transport.TransportProtos;
27 26 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
28   -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportServiceImpl;
29   -import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
  27 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServiceImpl;
30 28
31 29 import java.util.List;
32 30 import java.util.Map;
... ... @@ -36,42 +34,36 @@ import java.util.concurrent.CopyOnWriteArrayList;
36 34
37 35 @Slf4j
38 36 @Data
39   -public class LwM2MClient implements Cloneable {
  37 +public class LwM2mClient implements Cloneable {
40 38 private String deviceName;
41 39 private String deviceProfileName;
42   - private String endPoint;
  40 + private String endpoint;
43 41 private String identity;
44 42 private SecurityInfo securityInfo;
45   - private UUID deviceUuid;
46   - private UUID sessionUuid;
47   - private UUID profileUuid;
48   - private LeshanServer lwServer;
49   - private LwM2MTransportServiceImpl lwM2MTransportServiceImpl;
  43 + private UUID deviceId;
  44 + private UUID sessionId;
  45 + private UUID profileId;
50 46 private Registration registration;
51 47 private ValidateDeviceCredentialsResponseMsg credentialsResponse;
52   - private final Map<String, String> attributes;
53 48 private final Map<String, ResourceValue> resources;
54 49 private final Map<String, TransportProtos.TsKvProto> delayedRequests;
55 50 private final List<String> pendingRequests;
56 51 private boolean init;
57   - private final LwM2mValueConverterImpl converter;
58 52
59 53 public Object clone() throws CloneNotSupportedException {
60 54 return super.clone();
61 55 }
62 56
63   - public LwM2MClient(String endPoint, String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponseMsg credentialsResponse, UUID profileUuid, UUID sessionUuid) {
64   - this.endPoint = endPoint;
  57 + public LwM2mClient(String endpoint, String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponseMsg credentialsResponse, UUID profileId, UUID sessionId) {
  58 + this.endpoint = endpoint;
65 59 this.identity = identity;
66 60 this.securityInfo = securityInfo;
67 61 this.credentialsResponse = credentialsResponse;
68   - this.attributes = new ConcurrentHashMap<>();
69 62 this.delayedRequests = new ConcurrentHashMap<>();
70 63 this.pendingRequests = new CopyOnWriteArrayList<>();
71 64 this.resources = new ConcurrentHashMap<>();
72   - this.profileUuid = profileUuid;
73   - this.sessionUuid = sessionUuid;
74   - this.converter = LwM2mValueConverterImpl.getInstance();
  65 + this.profileId = profileId;
  66 + this.sessionId = sessionId;
75 67 this.init = false;
76 68 }
77 69
... ... @@ -83,7 +75,7 @@ public class LwM2MClient implements Cloneable {
83 75 }
84 76 }
85 77
86   - public void initValue(LwM2MTransportServiceImpl lwM2MTransportService, String path) {
  78 + public void initValue(LwM2mTransportServiceImpl lwM2MTransportService, String path) {
87 79 if (path != null) {
88 80 this.pendingRequests.remove(path);
89 81 }
... ... @@ -93,8 +85,8 @@ public class LwM2MClient implements Cloneable {
93 85 }
94 86 }
95 87
96   - public LwM2MClient copy() {
97   - return new LwM2MClient(this.endPoint, this.identity, this.securityInfo, this.credentialsResponse, this.profileUuid, this.sessionUuid);
  88 + public LwM2mClient copy() {
  89 + return new LwM2mClient(this.endpoint, this.identity, this.securityInfo, this.credentialsResponse, this.profileId, this.sessionId);
98 90 }
99 91 }
100 92
... ...
  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.client;
  17 +
  18 +import org.eclipse.leshan.server.registration.Registration;
  19 +import org.thingsboard.server.common.data.DeviceProfile;
  20 +import org.thingsboard.server.gen.transport.TransportProtos;
  21 +
  22 +import java.util.Map;
  23 +import java.util.UUID;
  24 +
  25 +public interface LwM2mClientContext {
  26 +
  27 + void delRemoveSessionAndListener(String registrationId);
  28 +
  29 + LwM2mClient getLwM2MClient(String endPoint, String identity);
  30 +
  31 + LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo);
  32 +
  33 + LwM2mClient getLwM2mClient(UUID sessionId);
  34 +
  35 + LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId);
  36 +
  37 + LwM2mClient updateInSessionsLwM2MClient(Registration registration);
  38 +
  39 + LwM2mClient addLwM2mClientToSession(String identity);
  40 +
  41 + Registration getRegistration(String registrationId);
  42 +
  43 + Map<String, LwM2mClient> getLwM2mClients();
  44 +
  45 + Map<UUID, LwM2mClientProfile> getProfiles();
  46 +
  47 + LwM2mClientProfile getProfile(UUID profileUuId);
  48 +
  49 + LwM2mClientProfile getProfile(Registration registration);
  50 +
  51 + Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles);
  52 +
  53 + boolean addUpdateProfileParameters(DeviceProfile deviceProfile);
  54 +}
... ...
  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.client;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.eclipse.leshan.server.registration.Registration;
  20 +import org.eclipse.leshan.server.security.EditableSecurityStore;
  21 +import org.springframework.stereotype.Service;
  22 +import org.thingsboard.server.common.data.DeviceProfile;
  23 +import org.thingsboard.server.gen.transport.TransportProtos;
  24 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  25 +import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;
  26 +import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
  27 +import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore;
  28 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler;
  29 +import org.thingsboard.server.transport.lwm2m.utils.TypeServer;
  30 +
  31 +import java.util.Map;
  32 +import java.util.UUID;
  33 +import java.util.concurrent.ConcurrentHashMap;
  34 +
  35 +import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC;
  36 +
  37 +@Service
  38 +@TbLwM2mTransportComponent
  39 +public class LwM2mClientContextImpl implements LwM2mClientContext {
  40 + private static final boolean INFOS_ARE_COMPROMISED = false;
  41 +
  42 + private final Map<String /** registrationId */, LwM2mClient> lwM2mClients = new ConcurrentHashMap<>();
  43 + private Map<UUID /** profileUUid */, LwM2mClientProfile> profiles = new ConcurrentHashMap<>();
  44 +
  45 + private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator;
  46 +
  47 + private final EditableSecurityStore securityStore;
  48 +
  49 + public LwM2mClientContextImpl(LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator, EditableSecurityStore securityStore) {
  50 + this.lwM2MCredentialsSecurityInfoValidator = lwM2MCredentialsSecurityInfoValidator;
  51 + this.securityStore = securityStore;
  52 + }
  53 +
  54 + public void delRemoveSessionAndListener(String registrationId) {
  55 + LwM2mClient lwM2MClient = lwM2mClients.get(registrationId);
  56 + if (lwM2MClient != null) {
  57 + securityStore.remove(lwM2MClient.getEndpoint(), INFOS_ARE_COMPROMISED);
  58 + lwM2mClients.remove(registrationId);
  59 + }
  60 + }
  61 +
  62 + @Override
  63 + public LwM2mClient getLwM2MClient(String endPoint, String identity) {
  64 + Map.Entry<String, LwM2mClient> modelClients = endPoint != null ?
  65 + this.lwM2mClients.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).findAny().orElse(null) :
  66 + this.lwM2mClients.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).findAny().orElse(null);
  67 + return modelClients != null ? modelClients.getValue() : null;
  68 + }
  69 +
  70 + @Override
  71 + public LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) {
  72 + return getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
  73 + }
  74 +
  75 + @Override
  76 + public LwM2mClient getLwM2mClient(UUID sessionId) {
  77 + return lwM2mClients.values().stream().filter(c -> c.getSessionId().equals(sessionId)).findAny().get();
  78 + }
  79 +
  80 + @Override
  81 + public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) {
  82 + LwM2mClient client = registrationId != null ?
  83 + this.lwM2mClients.get(registrationId) :
  84 + this.lwM2mClients.containsKey(registration.getId()) ?
  85 + this.lwM2mClients.get(registration.getId()) :
  86 + this.lwM2mClients.get(registration.getEndpoint());
  87 + return client != null ? client : updateInSessionsLwM2MClient(registration);
  88 + }
  89 +
  90 + @Override
  91 + public LwM2mClient updateInSessionsLwM2MClient(Registration registration) {
  92 + if (this.lwM2mClients.get(registration.getEndpoint()) == null) {
  93 + addLwM2mClientToSession(registration.getEndpoint());
  94 + }
  95 + LwM2mClient lwM2MClient = lwM2mClients.get(registration.getEndpoint());
  96 + lwM2MClient.setRegistration(registration);
  97 + this.lwM2mClients.remove(registration.getEndpoint());
  98 + this.lwM2mClients.put(registration.getId(), lwM2MClient);
  99 + return lwM2MClient;
  100 + }
  101 +
  102 + public Registration getRegistration(String registrationId) {
  103 + return this.lwM2mClients.get(registrationId).getRegistration();
  104 + }
  105 +
  106 + /**
  107 + * Add new LwM2MClient to session
  108 + * @param identity-
  109 + * @return SecurityInfo. If error - SecurityInfoError
  110 + * and log:
  111 + * - FORBIDDEN - if there is no authorization
  112 + * - profileUuid - if the device does not have a profile
  113 + * - device - if the thingsboard does not have a device with a name equal to the identity
  114 + */
  115 + @Override
  116 + public LwM2mClient addLwM2mClientToSession(String identity) {
  117 + ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, TypeServer.CLIENT);
  118 + if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {
  119 + UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null;
  120 + LwM2mClient client;
  121 + if (store.getSecurityInfo() != null && profileUuid != null) {
  122 + String endpoint = store.getSecurityInfo().getEndpoint();
  123 + client = new LwM2mClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID());
  124 + lwM2mClients.put(endpoint, client);
  125 + } else if (store.getSecurityMode() == NO_SEC.code && profileUuid != null) {
  126 + client = new LwM2mClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID());
  127 + lwM2mClients.put(identity, client);
  128 + } else {
  129 + throw new RuntimeException(String.format("Registration failed: FORBIDDEN/profileUuid/device %s , endpointId: %s [PSK]", profileUuid, identity));
  130 + }
  131 + return client;
  132 + } else {
  133 + throw new RuntimeException(String.format("Registration failed: FORBIDDEN, endpointId: %s", identity));
  134 + }
  135 + }
  136 +
  137 + @Override
  138 + public Map<String, LwM2mClient> getLwM2mClients() {
  139 + return lwM2mClients;
  140 + }
  141 +
  142 + @Override
  143 + public Map<UUID, LwM2mClientProfile> getProfiles() {
  144 + return profiles;
  145 + }
  146 +
  147 + @Override
  148 + public LwM2mClientProfile getProfile(UUID profileId) {
  149 + return profiles.get(profileId);
  150 + }
  151 +
  152 + @Override
  153 + public LwM2mClientProfile getProfile(Registration registration) {
  154 + return this.getProfiles().get(getLwM2mClientWithReg(registration, null).getProfileId());
  155 + }
  156 +
  157 + @Override
  158 + public Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles) {
  159 + return this.profiles = profiles;
  160 + }
  161 +
  162 + @Override
  163 + public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) {
  164 + LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile);
  165 + if (lwM2MClientProfile != null) {
  166 + profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
  167 + return true;
  168 + }
  169 + return false;
  170 + }
  171 +}
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClientProfile.java
... ... @@ -20,7 +20,7 @@ import com.google.gson.JsonObject;
20 20 import lombok.Data;
21 21
22 22 @Data
23   -public class LwM2MClientProfile {
  23 +public class LwM2mClientProfile {
24 24 /**
25 25 * {"clientLwM2mSettings": {
26 26 * clientUpdateValueAfterConnect: false;
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/LwM2mInMemorySecurityStore.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/secure/LwM2mInMemorySecurityStore.java
... ... @@ -13,30 +13,26 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.transport.lwm2m.server.secure;
  16 +package org.thingsboard.server.transport.lwm2m.server.store;
17 17
18 18 import lombok.extern.slf4j.Slf4j;
19 19 import org.eclipse.leshan.core.util.Hex;
20   -import org.eclipse.leshan.server.californium.LeshanServer;
21 20 import org.eclipse.leshan.server.registration.Registration;
22 21 import org.eclipse.leshan.server.security.InMemorySecurityStore;
23 22 import org.eclipse.leshan.server.security.SecurityInfo;
24 23 import org.eclipse.leshan.server.security.SecurityStoreListener;
25 24 import org.springframework.beans.factory.annotation.Autowired;
26   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
27   -import org.springframework.stereotype.Service;
28 25 import org.thingsboard.server.common.data.DeviceProfile;
29 26 import org.thingsboard.server.gen.transport.TransportProtos;
30 27 import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;
31 28 import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
32 29 import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore;
33   -import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler;
34   -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient;
35   -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientProfile;
  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;
36 33 import org.thingsboard.server.transport.lwm2m.utils.TypeServer;
37 34
38 35 import java.util.Collection;
39   -import java.util.Collections;
40 36 import java.util.List;
41 37 import java.util.Map;
42 38 import java.util.UUID;
... ... @@ -49,8 +45,9 @@ import java.util.stream.Collectors;
49 45 import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC;
50 46
51 47 @Slf4j
52   -@Service("LwM2mInMemorySecurityStore")
53   -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' )|| ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
  48 +//@Service("LwM2mInMemorySecurityStore")
  49 +//@TbLwM2mTransportComponent
  50 +@Deprecated
54 51 public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {
55 52 private static final boolean INFOS_ARE_COMPROMISED = false;
56 53
... ... @@ -58,8 +55,8 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {
58 55 private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
59 56 private final Lock readLock = readWriteLock.readLock();
60 57 private final Lock writeLock = readWriteLock.writeLock();
61   - private final Map<String /** registrationId */, LwM2MClient> sessions = new ConcurrentHashMap<>();
62   - private Map<UUID /** profileUUid */, LwM2MClientProfile> profiles = new ConcurrentHashMap<>();
  58 + private final Map<String /** registrationId */, LwM2mClient> sessions = new ConcurrentHashMap<>();
  59 + private Map<UUID /** profileUUid */, LwM2mClientProfile> profiles = new ConcurrentHashMap<>();
63 60 private SecurityStoreListener listener;
64 61
65 62 @Autowired
... ... @@ -102,7 +99,7 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {
102 99 public Collection<SecurityInfo> getAll() {
103 100 readLock.lock();
104 101 try {
105   - return Collections.unmodifiableCollection(this.sessions.values().stream().map(LwM2MClient::getSecurityInfo).collect(Collectors.toList()));
  102 + return this.sessions.values().stream().map(LwM2mClient::getSecurityInfo).collect(Collectors.toUnmodifiableList());
106 103 } finally {
107 104 readLock.unlock();
108 105 }
... ... @@ -115,7 +112,7 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {
115 112 public void delRemoveSessionAndListener(String registrationId) {
116 113 writeLock.lock();
117 114 try {
118   - LwM2MClient lwM2MClient = (sessions.get(registrationId) != null) ? sessions.get(registrationId) : null;
  115 + LwM2mClient lwM2MClient = (sessions.get(registrationId) != null) ? sessions.get(registrationId) : null;
119 116 if (lwM2MClient != null) {
120 117 if (listener != null) {
121 118 listener.securityInfoRemoved(INFOS_ARE_COMPROMISED, lwM2MClient.getSecurityInfo());
... ... @@ -132,14 +129,14 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {
132 129 this.listener = listener;
133 130 }
134 131
135   - public LwM2MClient getLwM2MClient(String endPoint, String identity) {
136   - Map.Entry<String, LwM2MClient> modelClients = (endPoint != null) ?
137   - this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndPoint())).findAny().orElse(null) :
  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) :
138 135 this.sessions.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).findAny().orElse(null);
139   - return (modelClients != null) ? modelClients.getValue() : null;
  136 + return modelClients != null ? modelClients.getValue() : null;
140 137 }
141 138
142   - public LwM2MClient getLwM2MClientWithReg(Registration registration, String registrationId) {
  139 + public LwM2mClient getLwM2MClientWithReg(Registration registration, String registrationId) {
143 140 return registrationId != null ?
144 141 this.sessions.get(registrationId) :
145 142 this.sessions.containsKey(registration.getId()) ?
... ... @@ -147,28 +144,25 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {
147 144 this.sessions.get(registration.getEndpoint());
148 145 }
149 146
150   - public LwM2MClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) {
  147 + public LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) {
151 148 return this.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue();
152   -
153 149 }
154 150
155 151 /**
156 152 * Update in sessions (LwM2MClient for key registration_Id) after starting registration LwM2MClient in LwM2MTransportServiceImpl
157 153 * Remove from sessions LwM2MClient with key registration_Endpoint
158   - * @param lwServer -
159 154 * @param registration -
160 155 * @return LwM2MClient after adding it to session
161 156 */
162   - public LwM2MClient updateInSessionsLwM2MClient(LeshanServer lwServer, Registration registration) {
  157 + public LwM2mClient updateInSessionsLwM2MClient(Registration registration) {
163 158 writeLock.lock();
164 159 try {
165 160 if (this.sessions.get(registration.getEndpoint()) == null) {
166 161 this.addLwM2MClientToSession(registration.getEndpoint());
167 162 }
168   - LwM2MClient lwM2MClient = this.sessions.get(registration.getEndpoint());
169   - lwM2MClient.setLwServer(lwServer);
  163 + LwM2mClient lwM2MClient = this.sessions.get(registration.getEndpoint());
170 164 lwM2MClient.setRegistration(registration);
171   - lwM2MClient.getAttributes().putAll(registration.getAdditionalRegistrationAttributes());
  165 +// lwM2MClient.getAttributes().putAll(registration.getAdditionalRegistrationAttributes());
172 166 this.sessions.remove(registration.getEndpoint());
173 167 this.sessions.put(registration.getId(), lwM2MClient);
174 168 return lwM2MClient;
... ... @@ -179,7 +173,7 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {
179 173
180 174 private String getRegistrationId(String endPoint, String identity) {
181 175 List<String> registrationIds = (endPoint != null) ?
182   - this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndPoint())).map(Map.Entry::getKey).collect(Collectors.toList()) :
  176 + this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).map(Map.Entry::getKey).collect(Collectors.toList()) :
183 177 this.sessions.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).map(Map.Entry::getKey).collect(Collectors.toList());
184 178 return (registrationIds != null && registrationIds.size() > 0) ? registrationIds.get(0) : null;
185 179 }
... ... @@ -203,49 +197,51 @@ public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {
203 197 UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null;
204 198 if (store.getSecurityInfo() != null && profileUuid != null) {
205 199 String endpoint = store.getSecurityInfo().getEndpoint();
206   - sessions.put(endpoint, new LwM2MClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID()));
  200 + sessions.put(endpoint, new LwM2mClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID()));
207 201 } else if (store.getSecurityMode() == NO_SEC.code && profileUuid != null) {
208   - sessions.put(identity, new LwM2MClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID()));
  202 + sessions.put(identity, new LwM2mClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID()));
209 203 } else {
210   - log.error("Registration failed: FORBIDDEN/profileUuid/device [{}] , endpointId: [{}]", profileUuid, identity);
211   - /**
212   - * Return Error securityInfo
213   - */
214   - byte[] preSharedKey = Hex.decodeHex("0A0B".toCharArray());
215   - SecurityInfo infoError = SecurityInfo.newPreSharedKeyInfo("error", "error_identity", preSharedKey);
216   - return infoError;
217   - }
  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;
218 211 }
219   - return store.getSecurityInfo();
  212 + }
  213 + return store.getSecurityInfo();
220 214 }
221 215
222   - public Map<String, LwM2MClient> getSession(UUID sessionUuId) {
223   - return this.sessions.entrySet().stream().filter(e -> e.getValue().getSessionUuid().equals(sessionUuId)).collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
  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));
224 220 }
225 221
226   - public Map<String, LwM2MClient> getSessions() {
  222 + public Map<String, LwM2mClient> getSessions() {
227 223 return this.sessions;
228 224 }
229 225
230   - public Map<UUID, LwM2MClientProfile> getProfiles() {
  226 + public Map<UUID, LwM2mClientProfile> getProfiles() {
231 227 return this.profiles;
232 228 }
233 229
234   - public LwM2MClientProfile getProfile(UUID profileUuId) {
  230 + public LwM2mClientProfile getProfile(UUID profileUuId) {
235 231 return this.profiles.get(profileUuId);
236 232 }
237 233
238   - public LwM2MClientProfile getProfile(String registrationId) {
239   - UUID profileUUid = this.getSessions().get(registrationId).getProfileUuid();
  234 + public LwM2mClientProfile getProfile(String registrationId) {
  235 + UUID profileUUid = this.getSessions().get(registrationId).getProfileId();
240 236 return this.getProfiles().get(profileUUid);
241 237 }
242 238
243   - public Map<UUID, LwM2MClientProfile> setProfiles(Map<UUID, LwM2MClientProfile> profiles) {
  239 + public Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles) {
244 240 return this.profiles = profiles;
245 241 }
246 242
247 243 public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) {
248   - LwM2MClientProfile lwM2MClientProfile = LwM2MTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile);
  244 + LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile);
249 245 if (lwM2MClientProfile != null) {
250 246 profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
251 247 return true;
... ...
  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 org.eclipse.californium.core.coap.Token;
  19 +import org.eclipse.californium.core.observe.ObservationStoreException;
  20 +import org.eclipse.californium.elements.EndpointContext;
  21 +import org.eclipse.leshan.core.observation.Observation;
  22 +import org.eclipse.leshan.core.util.NamedThreadFactory;
  23 +import org.eclipse.leshan.core.util.Validate;
  24 +import org.eclipse.leshan.server.Destroyable;
  25 +import org.eclipse.leshan.server.Startable;
  26 +import org.eclipse.leshan.server.Stoppable;
  27 +import org.eclipse.leshan.server.californium.observation.ObserveUtil;
  28 +import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
  29 +import org.eclipse.leshan.server.redis.JedisLock;
  30 +import org.eclipse.leshan.server.redis.RedisRegistrationStore;
  31 +import org.eclipse.leshan.server.redis.SingleInstanceJedisLock;
  32 +import org.eclipse.leshan.server.redis.serialization.ObservationSerDes;
  33 +import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes;
  34 +import org.eclipse.leshan.server.registration.Deregistration;
  35 +import org.eclipse.leshan.server.registration.ExpirationListener;
  36 +import org.eclipse.leshan.server.registration.Registration;
  37 +import org.eclipse.leshan.server.registration.RegistrationUpdate;
  38 +import org.eclipse.leshan.server.registration.UpdatedRegistration;
  39 +import org.slf4j.Logger;
  40 +import org.slf4j.LoggerFactory;
  41 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  42 +import redis.clients.jedis.Jedis;
  43 +import redis.clients.jedis.ScanParams;
  44 +import redis.clients.jedis.ScanResult;
  45 +import redis.clients.jedis.Transaction;
  46 +
  47 +import java.net.InetSocketAddress;
  48 +import java.util.ArrayList;
  49 +import java.util.Arrays;
  50 +import java.util.Collection;
  51 +import java.util.Collections;
  52 +import java.util.Iterator;
  53 +import java.util.List;
  54 +import java.util.NoSuchElementException;
  55 +import java.util.Set;
  56 +import java.util.concurrent.Executors;
  57 +import java.util.concurrent.ScheduledExecutorService;
  58 +import java.util.concurrent.ScheduledFuture;
  59 +import java.util.concurrent.TimeUnit;
  60 +
  61 +import static java.nio.charset.StandardCharsets.UTF_8;
  62 +
  63 +public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationStore, Startable, Stoppable, Destroyable {
  64 + /** Default time in seconds between 2 cleaning tasks (used to remove expired registration). */
  65 + public static final long DEFAULT_CLEAN_PERIOD = 60;
  66 + public static final int DEFAULT_CLEAN_LIMIT = 500;
  67 + /** Defaut Extra time for registration lifetime in seconds */
  68 + public static final long DEFAULT_GRACE_PERIOD = 0;
  69 +
  70 + private static final Logger LOG = LoggerFactory.getLogger(RedisRegistrationStore.class);
  71 +
  72 + // Redis key prefixes
  73 + private static final String REG_EP = "REG:EP:"; // (Endpoint => Registration)
  74 + private static final String REG_EP_REGID_IDX = "EP:REGID:"; // secondary index key (Registration ID => Endpoint)
  75 + private static final String REG_EP_ADDR_IDX = "EP:ADDR:"; // secondary index key (Socket Address => Endpoint)
  76 + private static final String LOCK_EP = "LOCK:EP:";
  77 + private static final byte[] OBS_TKN = "OBS:TKN:".getBytes(UTF_8);
  78 + private static final String OBS_TKNS_REGID_IDX = "TKNS:REGID:"; // secondary index (token list by registration)
  79 + private static final byte[] EXP_EP = "EXP:EP".getBytes(UTF_8); // a sorted set used for registration expiration
  80 + // (expiration date, Endpoint)
  81 +
  82 + private final RedisConnectionFactory connectionFactory;
  83 +
  84 + // Listener use to notify when a registration expires
  85 + private ExpirationListener expirationListener;
  86 +
  87 + private final ScheduledExecutorService schedExecutor;
  88 + private ScheduledFuture<?> cleanerTask;
  89 + private boolean started = false;
  90 +
  91 + private final long cleanPeriod; // in seconds
  92 + private final int cleanLimit; // maximum number to clean in a clean period
  93 + private final long gracePeriod; // in seconds
  94 +
  95 + private final JedisLock lock;
  96 +
  97 + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory) {
  98 + this(connectionFactory, DEFAULT_CLEAN_PERIOD, DEFAULT_GRACE_PERIOD, DEFAULT_CLEAN_LIMIT); // default clean period 60s
  99 + }
  100 +
  101 + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, long cleanPeriodInSec, long lifetimeGracePeriodInSec, int cleanLimit) {
  102 + this(connectionFactory, Executors.newScheduledThreadPool(1,
  103 + new NamedThreadFactory(String.format("RedisRegistrationStore Cleaner (%ds)", cleanPeriodInSec))),
  104 + cleanPeriodInSec, lifetimeGracePeriodInSec, cleanLimit);
  105 + }
  106 +
  107 + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec,
  108 + long lifetimeGracePeriodInSec, int cleanLimit) {
  109 + this(connectionFactory, schedExecutor, cleanPeriodInSec, lifetimeGracePeriodInSec, cleanLimit, new SingleInstanceJedisLock());
  110 + }
  111 +
  112 + /**
  113 + * @since 1.1
  114 + */
  115 + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec,
  116 + long lifetimeGracePeriodInSec, int cleanLimit, JedisLock redisLock) {
  117 + this.connectionFactory = connectionFactory;
  118 + this.schedExecutor = schedExecutor;
  119 + this.cleanPeriod = cleanPeriodInSec;
  120 + this.cleanLimit = cleanLimit;
  121 + this.gracePeriod = lifetimeGracePeriodInSec;
  122 + this.lock = redisLock;
  123 + }
  124 +
  125 + /* *************** Redis Key utility function **************** */
  126 +
  127 + private byte[] toKey(byte[] prefix, byte[] key) {
  128 + byte[] result = new byte[prefix.length + key.length];
  129 + System.arraycopy(prefix, 0, result, 0, prefix.length);
  130 + System.arraycopy(key, 0, result, prefix.length, key.length);
  131 + return result;
  132 + }
  133 +
  134 + private byte[] toKey(String prefix, String registrationID) {
  135 + return (prefix + registrationID).getBytes();
  136 + }
  137 +
  138 + private byte[] toLockKey(String endpoint) {
  139 + return toKey(LOCK_EP, endpoint);
  140 + }
  141 +
  142 + private byte[] toLockKey(byte[] endpoint) {
  143 + return toKey(LOCK_EP.getBytes(UTF_8), endpoint);
  144 + }
  145 +
  146 + /* *************** Leshan Registration API **************** */
  147 +
  148 + @Override
  149 + public Deregistration addRegistration(Registration registration) {
  150 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  151 + byte[] lockValue = null;
  152 + byte[] lockKey = toLockKey(registration.getEndpoint());
  153 +
  154 + try {
  155 + lockValue = lock.acquire(j, lockKey);
  156 +
  157 + // add registration
  158 + byte[] k = toEndpointKey(registration.getEndpoint());
  159 + byte[] old = j.getSet(k, serializeReg(registration));
  160 +
  161 + // add registration: secondary indexes
  162 + byte[] regid_idx = toRegIdKey(registration.getId());
  163 + j.set(regid_idx, registration.getEndpoint().getBytes(UTF_8));
  164 + byte[] addr_idx = toRegAddrKey(registration.getSocketAddress());
  165 + j.set(addr_idx, registration.getEndpoint().getBytes(UTF_8));
  166 +
  167 + // Add or update expiration
  168 + addOrUpdateExpiration(j, registration);
  169 +
  170 + if (old != null) {
  171 + Registration oldRegistration = deserializeReg(old);
  172 + // remove old secondary index
  173 + if (!registration.getId().equals(oldRegistration.getId()))
  174 + j.del(toRegIdKey(oldRegistration.getId()));
  175 + if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) {
  176 + removeAddrIndex(j, oldRegistration);
  177 + }
  178 + // remove old observation
  179 + Collection<Observation> obsRemoved = unsafeRemoveAllObservations(j, oldRegistration.getId());
  180 +
  181 + return new Deregistration(oldRegistration, obsRemoved);
  182 + }
  183 +
  184 + return null;
  185 + } finally {
  186 + lock.release(j, lockKey, lockValue);
  187 + }
  188 + }
  189 + }
  190 +
  191 + @Override
  192 + public UpdatedRegistration updateRegistration(RegistrationUpdate update) {
  193 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  194 +
  195 + // Fetch the registration ep by registration ID index
  196 + byte[] ep = j.get(toRegIdKey(update.getRegistrationId()));
  197 + if (ep == null) {
  198 + return null;
  199 + }
  200 +
  201 + byte[] lockValue = null;
  202 + byte[] lockKey = toLockKey(ep);
  203 + try {
  204 + lockValue = lock.acquire(j, lockKey);
  205 +
  206 + // Fetch the registration
  207 + byte[] data = j.get(toEndpointKey(ep));
  208 + if (data == null) {
  209 + return null;
  210 + }
  211 +
  212 + Registration r = deserializeReg(data);
  213 +
  214 + Registration updatedRegistration = update.update(r);
  215 +
  216 + // Store the new registration
  217 + j.set(toEndpointKey(updatedRegistration.getEndpoint()), serializeReg(updatedRegistration));
  218 +
  219 + // Add or update expiration
  220 + addOrUpdateExpiration(j, updatedRegistration);
  221 +
  222 + // Update secondary index :
  223 + // If registration is already associated to this address we don't care as we only want to keep the most
  224 + // recent binding.
  225 + byte[] addr_idx = toRegAddrKey(updatedRegistration.getSocketAddress());
  226 + j.set(addr_idx, updatedRegistration.getEndpoint().getBytes(UTF_8));
  227 + if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) {
  228 + removeAddrIndex(j, r);
  229 + }
  230 +
  231 + return new UpdatedRegistration(r, updatedRegistration);
  232 +
  233 + } finally {
  234 + lock.release(j, lockKey, lockValue);
  235 + }
  236 + }
  237 + }
  238 +
  239 + @Override
  240 + public Registration getRegistration(String registrationId) {
  241 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  242 + return getRegistration(j, registrationId);
  243 + }
  244 + }
  245 +
  246 + @Override
  247 + public Registration getRegistrationByEndpoint(String endpoint) {
  248 + Validate.notNull(endpoint);
  249 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  250 + byte[] data = j.get(toEndpointKey(endpoint));
  251 + if (data == null) {
  252 + return null;
  253 + }
  254 + return deserializeReg(data);
  255 + }
  256 + }
  257 +
  258 + @Override
  259 + public Registration getRegistrationByAdress(InetSocketAddress address) {
  260 + Validate.notNull(address);
  261 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  262 + byte[] ep = j.get(toRegAddrKey(address));
  263 + if (ep == null) {
  264 + return null;
  265 + }
  266 + byte[] data = j.get(toEndpointKey(ep));
  267 + if (data == null) {
  268 + return null;
  269 + }
  270 + return deserializeReg(data);
  271 + }
  272 + }
  273 +
  274 + @Override
  275 + public Iterator<Registration> getAllRegistrations() {
  276 + return new TbLwM2mRedisRegistrationStore.RedisIterator(connectionFactory, new ScanParams().match(REG_EP + "*").count(100));
  277 + }
  278 +
  279 + protected class RedisIterator implements Iterator<Registration> {
  280 +
  281 + private RedisConnectionFactory connectionFactory;
  282 + private ScanParams scanParams;
  283 +
  284 + private String cursor;
  285 + private List<Registration> scanResult;
  286 +
  287 + public RedisIterator(RedisConnectionFactory connectionFactory, ScanParams scanParams) {
  288 + this.connectionFactory = connectionFactory;
  289 + this.scanParams = scanParams;
  290 + // init scan result
  291 + scanNext("0");
  292 + }
  293 +
  294 + private void scanNext(String cursor) {
  295 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  296 + do {
  297 + ScanResult<byte[]> sr = j.scan(cursor.getBytes(), scanParams);
  298 +
  299 + this.scanResult = new ArrayList<>();
  300 + if (sr.getResult() != null && !sr.getResult().isEmpty()) {
  301 + for (byte[] value : j.mget(sr.getResult().toArray(new byte[][]{}))) {
  302 + this.scanResult.add(deserializeReg(value));
  303 + }
  304 + }
  305 +
  306 + cursor = sr.getCursor();
  307 + } while (!"0".equals(cursor) && scanResult.isEmpty());
  308 +
  309 + this.cursor = cursor;
  310 + }
  311 + }
  312 +
  313 + @Override
  314 + public boolean hasNext() {
  315 + if (!scanResult.isEmpty()) {
  316 + return true;
  317 + }
  318 + if ("0".equals(cursor)) {
  319 + // no more elements to scan
  320 + return false;
  321 + }
  322 +
  323 + // read more elements
  324 + scanNext(cursor);
  325 + return !scanResult.isEmpty();
  326 + }
  327 +
  328 + @Override
  329 + public Registration next() {
  330 + if (!hasNext()) {
  331 + throw new NoSuchElementException();
  332 + }
  333 + return scanResult.remove(0);
  334 + }
  335 +
  336 + @Override
  337 + public void remove() {
  338 + throw new UnsupportedOperationException();
  339 + }
  340 + }
  341 +
  342 + @Override
  343 + public Deregistration removeRegistration(String registrationId) {
  344 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  345 + return removeRegistration(j, registrationId, false);
  346 + }
  347 + }
  348 +
  349 + private Deregistration removeRegistration(Jedis j, String registrationId, boolean removeOnlyIfNotAlive) {
  350 + // fetch the client ep by registration ID index
  351 + byte[] ep = j.get(toRegIdKey(registrationId));
  352 + if (ep == null) {
  353 + return null;
  354 + }
  355 +
  356 + byte[] lockValue = null;
  357 + byte[] lockKey = toLockKey(ep);
  358 + try {
  359 + lockValue = lock.acquire(j, lockKey);
  360 +
  361 + // fetch the client
  362 + byte[] data = j.get(toEndpointKey(ep));
  363 + if (data == null) {
  364 + return null;
  365 + }
  366 + Registration r = deserializeReg(data);
  367 +
  368 + if (!removeOnlyIfNotAlive || !r.isAlive(gracePeriod)) {
  369 + long nbRemoved = j.del(toRegIdKey(r.getId()));
  370 + if (nbRemoved > 0) {
  371 + j.del(toEndpointKey(r.getEndpoint()));
  372 + Collection<Observation> obsRemoved = unsafeRemoveAllObservations(j, r.getId());
  373 + removeAddrIndex(j, r);
  374 + removeExpiration(j, r);
  375 + return new Deregistration(r, obsRemoved);
  376 + }
  377 + }
  378 + return null;
  379 + } finally {
  380 + lock.release(j, lockKey, lockValue);
  381 + }
  382 + }
  383 +
  384 + private void removeAddrIndex(Jedis j, Registration registration) {
  385 + // Watch the key to remove.
  386 + byte[] regAddrKey = toRegAddrKey(registration.getSocketAddress());
  387 + j.watch(regAddrKey);
  388 +
  389 + byte[] epFromAddr = j.get(regAddrKey);
  390 + // Delete the key if needed.
  391 + if (Arrays.equals(epFromAddr, registration.getEndpoint().getBytes(UTF_8))) {
  392 + // Try to delete the key
  393 + Transaction transaction = j.multi();
  394 + transaction.del(regAddrKey);
  395 + transaction.exec();
  396 + // if transaction failed this is not an issue as the socket address is probably reused and we don't neeed to
  397 + // delete it anymore.
  398 + } else {
  399 + // the key must not be deleted.
  400 + j.unwatch();
  401 + }
  402 + }
  403 +
  404 + private void addOrUpdateExpiration(Jedis j, Registration registration) {
  405 + j.zadd(EXP_EP, registration.getExpirationTimeStamp(gracePeriod), registration.getEndpoint().getBytes(UTF_8));
  406 + }
  407 +
  408 + private void removeExpiration(Jedis j, Registration registration) {
  409 + j.zrem(EXP_EP, registration.getEndpoint().getBytes(UTF_8));
  410 + }
  411 +
  412 + private byte[] toRegIdKey(String registrationId) {
  413 + return toKey(REG_EP_REGID_IDX, registrationId);
  414 + }
  415 +
  416 + private byte[] toRegAddrKey(InetSocketAddress addr) {
  417 + return toKey(REG_EP_ADDR_IDX, addr.getAddress().toString() + ":" + addr.getPort());
  418 + }
  419 +
  420 + private byte[] toEndpointKey(String endpoint) {
  421 + return toKey(REG_EP, endpoint);
  422 + }
  423 +
  424 + private byte[] toEndpointKey(byte[] endpoint) {
  425 + return toKey(REG_EP.getBytes(UTF_8), endpoint);
  426 + }
  427 +
  428 + private byte[] serializeReg(Registration registration) {
  429 + return RegistrationSerDes.bSerialize(registration);
  430 + }
  431 +
  432 + private Registration deserializeReg(byte[] data) {
  433 + return RegistrationSerDes.deserialize(data);
  434 + }
  435 +
  436 + /* *************** Leshan Observation API **************** */
  437 +
  438 + /*
  439 + * The observation is not persisted here, it is done by the Californium layer (in the implementation of the
  440 + * org.eclipse.californium.core.observe.ObservationStore#add method)
  441 + */
  442 + @Override
  443 + public Collection<Observation> addObservation(String registrationId, Observation observation) {
  444 +
  445 + List<Observation> removed = new ArrayList<>();
  446 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  447 +
  448 + // fetch the client ep by registration ID index
  449 + byte[] ep = j.get(toRegIdKey(registrationId));
  450 + if (ep == null) {
  451 + return null;
  452 + }
  453 +
  454 + byte[] lockValue = null;
  455 + byte[] lockKey = toLockKey(ep);
  456 +
  457 + try {
  458 + lockValue = lock.acquire(j, lockKey);
  459 +
  460 + // cancel existing observations for the same path and registration id.
  461 + for (Observation obs : getObservations(j, registrationId)) {
  462 + if (observation.getPath().equals(obs.getPath())
  463 + && !Arrays.equals(observation.getId(), obs.getId())) {
  464 + removed.add(obs);
  465 + unsafeRemoveObservation(j, registrationId, obs.getId());
  466 + }
  467 + }
  468 +
  469 + } finally {
  470 + lock.release(j, lockKey, lockValue);
  471 + }
  472 + }
  473 + return removed;
  474 + }
  475 +
  476 + @Override
  477 + public Observation removeObservation(String registrationId, byte[] observationId) {
  478 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  479 +
  480 + // fetch the client ep by registration ID index
  481 + byte[] ep = j.get(toRegIdKey(registrationId));
  482 + if (ep == null) {
  483 + return null;
  484 + }
  485 +
  486 + // remove observation
  487 + byte[] lockValue = null;
  488 + byte[] lockKey = toLockKey(ep);
  489 + try {
  490 + lockValue = lock.acquire(j, lockKey);
  491 +
  492 + Observation observation = build(get(new Token(observationId)));
  493 + if (observation != null && registrationId.equals(observation.getRegistrationId())) {
  494 + unsafeRemoveObservation(j, registrationId, observationId);
  495 + return observation;
  496 + }
  497 + return null;
  498 +
  499 + } finally {
  500 + lock.release(j, lockKey, lockValue);
  501 + }
  502 + }
  503 + }
  504 +
  505 + @Override
  506 + public Observation getObservation(String registrationId, byte[] observationId) {
  507 + return build(get(new Token(observationId)));
  508 + }
  509 +
  510 + @Override
  511 + public Collection<Observation> getObservations(String registrationId) {
  512 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  513 + return getObservations(j, registrationId);
  514 + }
  515 + }
  516 +
  517 + private Collection<Observation> getObservations(Jedis j, String registrationId) {
  518 + Collection<Observation> result = new ArrayList<>();
  519 + for (byte[] token : j.lrange(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, -1)) {
  520 + byte[] obs = j.get(toKey(OBS_TKN, token));
  521 + if (obs != null) {
  522 + result.add(build(deserializeObs(obs)));
  523 + }
  524 + }
  525 + return result;
  526 + }
  527 +
  528 + @Override
  529 + public Collection<Observation> removeObservations(String registrationId) {
  530 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  531 + // check registration exists
  532 + Registration registration = getRegistration(j, registrationId);
  533 + if (registration == null)
  534 + return Collections.emptyList();
  535 +
  536 + // get endpoint and create lock
  537 + String endpoint = registration.getEndpoint();
  538 + byte[] lockValue = null;
  539 + byte[] lockKey = toKey(LOCK_EP, endpoint);
  540 + try {
  541 + lockValue = lock.acquire(j, lockKey);
  542 +
  543 + return unsafeRemoveAllObservations(j, registrationId);
  544 + } finally {
  545 + lock.release(j, lockKey, lockValue);
  546 + }
  547 + }
  548 + }
  549 +
  550 + /* *************** Californium ObservationStore API **************** */
  551 +
  552 + @Override
  553 + public org.eclipse.californium.core.observe.Observation putIfAbsent(Token token,
  554 + org.eclipse.californium.core.observe.Observation obs) throws ObservationStoreException {
  555 + return add(token, obs, true);
  556 + }
  557 +
  558 + @Override
  559 + public org.eclipse.californium.core.observe.Observation put(Token token,
  560 + org.eclipse.californium.core.observe.Observation obs) throws ObservationStoreException {
  561 + return add(token, obs, false);
  562 + }
  563 +
  564 + private org.eclipse.californium.core.observe.Observation add(Token token,
  565 + org.eclipse.californium.core.observe.Observation obs, boolean ifAbsent) throws ObservationStoreException {
  566 + String endpoint = ObserveUtil.validateCoapObservation(obs);
  567 + org.eclipse.californium.core.observe.Observation previousObservation = null;
  568 +
  569 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  570 + byte[] lockValue = null;
  571 + byte[] lockKey = toKey(LOCK_EP, endpoint);
  572 + try {
  573 + lockValue = lock.acquire(j, lockKey);
  574 +
  575 + String registrationId = ObserveUtil.extractRegistrationId(obs);
  576 + if (!j.exists(toRegIdKey(registrationId)))
  577 + throw new ObservationStoreException("no registration for this Id");
  578 + byte[] key = toKey(OBS_TKN, obs.getRequest().getToken().getBytes());
  579 + byte[] serializeObs = serializeObs(obs);
  580 + byte[] previousValue = null;
  581 + if (ifAbsent) {
  582 + previousValue = j.get(key);
  583 + if (previousValue == null || previousValue.length == 0) {
  584 + j.set(key, serializeObs);
  585 + } else {
  586 + return deserializeObs(previousValue);
  587 + }
  588 + } else {
  589 + previousValue = j.getSet(key, serializeObs);
  590 + }
  591 +
  592 + // secondary index to get the list by registrationId
  593 + j.lpush(toKey(OBS_TKNS_REGID_IDX, registrationId), obs.getRequest().getToken().getBytes());
  594 +
  595 + // log any collisions
  596 + if (previousValue != null && previousValue.length != 0) {
  597 + previousObservation = deserializeObs(previousValue);
  598 + LOG.warn(
  599 + "Token collision ? observation from request [{}] will be replaced by observation from request [{}] ",
  600 + previousObservation.getRequest(), obs.getRequest());
  601 + }
  602 + } finally {
  603 + lock.release(j, lockKey, lockValue);
  604 + }
  605 + }
  606 + return previousObservation;
  607 + }
  608 +
  609 + @Override
  610 + public void remove(Token token) {
  611 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  612 + byte[] tokenKey = toKey(OBS_TKN, token.getBytes());
  613 +
  614 + // fetch the observation by token
  615 + byte[] serializedObs = j.get(tokenKey);
  616 + if (serializedObs == null)
  617 + return;
  618 +
  619 + org.eclipse.californium.core.observe.Observation obs = deserializeObs(serializedObs);
  620 + String registrationId = ObserveUtil.extractRegistrationId(obs);
  621 + Registration registration = getRegistration(j, registrationId);
  622 + if (registration == null) {
  623 + LOG.warn("Unable to remove observation {}, registration {} does not exist anymore", obs.getRequest(),
  624 + registrationId);
  625 + return;
  626 + }
  627 +
  628 + String endpoint = registration.getEndpoint();
  629 + byte[] lockValue = null;
  630 + byte[] lockKey = toKey(LOCK_EP, endpoint);
  631 + try {
  632 + lockValue = lock.acquire(j, lockKey);
  633 +
  634 + unsafeRemoveObservation(j, registrationId, token.getBytes());
  635 + } finally {
  636 + lock.release(j, lockKey, lockValue);
  637 + }
  638 + }
  639 +
  640 + }
  641 +
  642 + @Override
  643 + public org.eclipse.californium.core.observe.Observation get(Token token) {
  644 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  645 + byte[] obs = j.get(toKey(OBS_TKN, token.getBytes()));
  646 + if (obs == null) {
  647 + return null;
  648 + } else {
  649 + return deserializeObs(obs);
  650 + }
  651 + }
  652 + }
  653 +
  654 + /* *************** Observation utility functions **************** */
  655 +
  656 + private Registration getRegistration(Jedis j, String registrationId) {
  657 + byte[] ep = j.get(toRegIdKey(registrationId));
  658 + if (ep == null) {
  659 + return null;
  660 + }
  661 + byte[] data = j.get(toEndpointKey(ep));
  662 + if (data == null) {
  663 + return null;
  664 + }
  665 +
  666 + return deserializeReg(data);
  667 + }
  668 +
  669 + private void unsafeRemoveObservation(Jedis j, String registrationId, byte[] observationId) {
  670 + if (j.del(toKey(OBS_TKN, observationId)) > 0L) {
  671 + j.lrem(toKey(OBS_TKNS_REGID_IDX, registrationId), 0, observationId);
  672 + }
  673 + }
  674 +
  675 + private Collection<Observation> unsafeRemoveAllObservations(Jedis j, String registrationId) {
  676 + Collection<Observation> removed = new ArrayList<>();
  677 + byte[] regIdKey = toKey(OBS_TKNS_REGID_IDX, registrationId);
  678 +
  679 + // fetch all observations by token
  680 + for (byte[] token : j.lrange(regIdKey, 0, -1)) {
  681 + byte[] obs = j.get(toKey(OBS_TKN, token));
  682 + if (obs != null) {
  683 + removed.add(build(deserializeObs(obs)));
  684 + }
  685 + j.del(toKey(OBS_TKN, token));
  686 + }
  687 + j.del(regIdKey);
  688 +
  689 + return removed;
  690 + }
  691 +
  692 + @Override
  693 + public void setContext(Token token, EndpointContext correlationContext) {
  694 + // In Leshan we always set context when we send the request, so this should not be needed to implement this.
  695 + }
  696 +
  697 + private byte[] serializeObs(org.eclipse.californium.core.observe.Observation obs) {
  698 + return ObservationSerDes.serialize(obs);
  699 + }
  700 +
  701 + private org.eclipse.californium.core.observe.Observation deserializeObs(byte[] data) {
  702 + return ObservationSerDes.deserialize(data);
  703 + }
  704 +
  705 + private Observation build(org.eclipse.californium.core.observe.Observation cfObs) {
  706 + if (cfObs == null)
  707 + return null;
  708 +
  709 + return ObserveUtil.createLwM2mObservation(cfObs.getRequest());
  710 + }
  711 +
  712 + /* *************** Expiration handling **************** */
  713 +
  714 + /**
  715 + * Start regular cleanup of dead registrations.
  716 + */
  717 + @Override
  718 + public synchronized void start() {
  719 + if (!started) {
  720 + started = true;
  721 + cleanerTask = schedExecutor.scheduleAtFixedRate(new TbLwM2mRedisRegistrationStore.Cleaner(), cleanPeriod, cleanPeriod, TimeUnit.SECONDS);
  722 + }
  723 + }
  724 +
  725 + /**
  726 + * Stop the underlying cleanup of the registrations.
  727 + */
  728 + @Override
  729 + public synchronized void stop() {
  730 + if (started) {
  731 + started = false;
  732 + if (cleanerTask != null) {
  733 + cleanerTask.cancel(false);
  734 + cleanerTask = null;
  735 + }
  736 + }
  737 + }
  738 +
  739 + /**
  740 + * Destroy "cleanup" scheduler.
  741 + */
  742 + @Override
  743 + public synchronized void destroy() {
  744 + started = false;
  745 + schedExecutor.shutdownNow();
  746 + try {
  747 + schedExecutor.awaitTermination(5, TimeUnit.SECONDS);
  748 + } catch (InterruptedException e) {
  749 + LOG.warn("Destroying RedisRegistrationStore was interrupted.", e);
  750 + }
  751 + }
  752 +
  753 + private class Cleaner implements Runnable {
  754 +
  755 + @Override
  756 + public void run() {
  757 +
  758 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  759 + Set<byte[]> endpointsExpired = j.zrangeByScore(EXP_EP, Double.NEGATIVE_INFINITY,
  760 + System.currentTimeMillis(), 0, cleanLimit);
  761 +
  762 + for (byte[] endpoint : endpointsExpired) {
  763 + Registration r = deserializeReg(j.get(toEndpointKey(endpoint)));
  764 + if (!r.isAlive(gracePeriod)) {
  765 + Deregistration dereg = removeRegistration(j, r.getId(), true);
  766 + if (dereg != null)
  767 + expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations());
  768 + }
  769 + }
  770 + } catch (Exception e) {
  771 + LOG.warn("Unexpected Exception while registration cleaning", e);
  772 + }
  773 + }
  774 + }
  775 +
  776 + @Override
  777 + public void setExpirationListener(ExpirationListener listener) {
  778 + expirationListener = listener;
  779 + }
  780 +
  781 + @Override
  782 + public void setExecutor(ScheduledExecutorService executor) {
  783 + // TODO should we reuse californium executor ?
  784 + }
  785 +}
... ...
  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 org.eclipse.leshan.server.redis.serialization.SecurityInfoSerDes;
  19 +import org.eclipse.leshan.server.security.EditableSecurityStore;
  20 +import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
  21 +import org.eclipse.leshan.server.security.SecurityInfo;
  22 +import org.eclipse.leshan.server.security.SecurityStoreListener;
  23 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  24 +import org.springframework.stereotype.Service;
  25 +import redis.clients.jedis.Jedis;
  26 +import redis.clients.jedis.ScanParams;
  27 +import redis.clients.jedis.ScanResult;
  28 +
  29 +import java.util.Collection;
  30 +import java.util.LinkedList;
  31 +
  32 +@Service
  33 +public class TbLwM2mRedisSecurityStore implements EditableSecurityStore {
  34 + private static final String SEC_EP = "SEC#EP#";
  35 +
  36 + private static final String PSKID_SEC = "PSKID#SEC";
  37 +
  38 + private final RedisConnectionFactory connectionFactory;
  39 + private SecurityStoreListener listener;
  40 +
  41 + public TbLwM2mRedisSecurityStore(RedisConnectionFactory connectionFactory) {
  42 + this.connectionFactory = connectionFactory;
  43 + }
  44 +
  45 + @Override
  46 + public SecurityInfo getByEndpoint(String endpoint) {
  47 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  48 + byte[] data = j.get((SEC_EP + endpoint).getBytes());
  49 + if (data == null) {
  50 + return null;
  51 + } else {
  52 + return deserialize(data);
  53 + }
  54 + }
  55 + }
  56 +
  57 + @Override
  58 + public SecurityInfo getByIdentity(String identity) {
  59 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  60 + String ep = j.hget(PSKID_SEC, identity);
  61 + if (ep == null) {
  62 + return null;
  63 + } else {
  64 + byte[] data = j.get((SEC_EP + ep).getBytes());
  65 + if (data == null) {
  66 + return null;
  67 + } else {
  68 + return deserialize(data);
  69 + }
  70 + }
  71 + }
  72 + }
  73 +
  74 + @Override
  75 + public Collection<SecurityInfo> getAll() {
  76 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  77 + ScanParams params = new ScanParams().match(SEC_EP + "*").count(100);
  78 + Collection<SecurityInfo> list = new LinkedList<>();
  79 + String cursor = "0";
  80 + do {
  81 + ScanResult<byte[]> res = j.scan(cursor.getBytes(), params);
  82 + for (byte[] key : res.getResult()) {
  83 + byte[] element = j.get(key);
  84 + list.add(deserialize(element));
  85 + }
  86 + cursor = res.getCursor();
  87 + } while (!"0".equals(cursor));
  88 + return list;
  89 + }
  90 + }
  91 +
  92 + @Override
  93 + public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {
  94 + byte[] data = serialize(info);
  95 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  96 + if (info.getIdentity() != null) {
  97 + // populate the secondary index (security info by PSK id)
  98 + String oldEndpoint = j.hget(PSKID_SEC, info.getIdentity());
  99 + if (oldEndpoint != null && !oldEndpoint.equals(info.getEndpoint())) {
  100 + throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used");
  101 + }
  102 + j.hset(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes());
  103 + }
  104 +
  105 + byte[] previousData = j.getSet((SEC_EP + info.getEndpoint()).getBytes(), data);
  106 + SecurityInfo previous = previousData == null ? null : deserialize(previousData);
  107 + String previousIdentity = previous == null ? null : previous.getIdentity();
  108 + if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) {
  109 + j.hdel(PSKID_SEC, previousIdentity);
  110 + }
  111 +
  112 + return previous;
  113 + }
  114 + }
  115 +
  116 + @Override
  117 + public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {
  118 + try (Jedis j = (Jedis) connectionFactory.getConnection().getNativeConnection()) {
  119 + byte[] data = j.get((SEC_EP + endpoint).getBytes());
  120 +
  121 + if (data != null) {
  122 + SecurityInfo info = deserialize(data);
  123 + if (info.getIdentity() != null) {
  124 + j.hdel(PSKID_SEC.getBytes(), info.getIdentity().getBytes());
  125 + }
  126 + j.del((SEC_EP + endpoint).getBytes());
  127 + if (listener != null) {
  128 + listener.securityInfoRemoved(infosAreCompromised, info);
  129 + }
  130 + return info;
  131 + }
  132 + }
  133 + return null;
  134 + }
  135 +
  136 + private byte[] serialize(SecurityInfo secInfo) {
  137 + return SecurityInfoSerDes.serialize(secInfo);
  138 + }
  139 +
  140 + private SecurityInfo deserialize(byte[] data) {
  141 + return SecurityInfoSerDes.deserialize(data);
  142 + }
  143 +
  144 + @Override
  145 + public void setListener(SecurityStoreListener listener) {
  146 + this.listener = listener;
  147 + }
  148 +}
... ...
  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 org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
  19 +import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore;
  20 +import org.eclipse.leshan.server.security.EditableSecurityStore;
  21 +import org.eclipse.leshan.server.security.InMemorySecurityStore;
  22 +import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
  23 +import org.eclipse.leshan.server.security.SecurityInfo;
  24 +import org.eclipse.leshan.server.security.SecurityStoreListener;
  25 +import org.springframework.beans.factory.annotation.Autowired;
  26 +import org.springframework.beans.factory.annotation.Value;
  27 +import org.springframework.context.annotation.Bean;
  28 +import org.springframework.context.annotation.Lazy;
  29 +import org.springframework.stereotype.Service;
  30 +import org.thingsboard.server.cache.TBRedisCacheConfiguration;
  31 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  32 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
  33 +
  34 +import java.util.Collection;
  35 +import java.util.Optional;
  36 +
  37 +@Service
  38 +@TbLwM2mTransportComponent
  39 +public class TbLwM2mStoreConfiguration {
  40 +
  41 + @Autowired(required = false)
  42 + private Optional<TBRedisCacheConfiguration> redisConfiguration;
  43 +
  44 + @Autowired
  45 + @Lazy
  46 + private LwM2mClientContext clientContext;
  47 +
  48 + @Value("${transport.lwm2m.redis.enabled:false}")
  49 + private boolean useRedis;
  50 +
  51 + @Bean
  52 + private CaliforniumRegistrationStore registrationStore() {
  53 + return redisConfiguration.isPresent() && useRedis ?
  54 + new TbLwM2mRedisRegistrationStore(redisConfiguration.get().redisConnectionFactory()) : new InMemoryRegistrationStore();
  55 + }
  56 +
  57 + @Bean
  58 + private EditableSecurityStore securityStore() {
  59 + return new TbLwM2mSecurityStoreWrapper(redisConfiguration.isPresent() && useRedis ?
  60 + new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new InMemorySecurityStore());
  61 + }
  62 +
  63 + public class TbLwM2mSecurityStoreWrapper implements EditableSecurityStore {
  64 +
  65 + private final EditableSecurityStore securityStore;
  66 +
  67 + public TbLwM2mSecurityStoreWrapper(EditableSecurityStore securityStore) {
  68 + this.securityStore = securityStore;
  69 + }
  70 +
  71 + @Override
  72 + public Collection<SecurityInfo> getAll() {
  73 + return securityStore.getAll();
  74 + }
  75 +
  76 + @Override
  77 + public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {
  78 + return securityStore.add(info);
  79 + }
  80 +
  81 + @Override
  82 + public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {
  83 + return securityStore.remove(endpoint, infosAreCompromised);
  84 + }
  85 +
  86 + @Override
  87 + public void setListener(SecurityStoreListener listener) {
  88 + securityStore.setListener(listener);
  89 + }
  90 +
  91 + @Override
  92 + public SecurityInfo getByEndpoint(String endpoint) {
  93 + SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint);
  94 + if (securityInfo == null) {
  95 + securityInfo = clientContext.addLwM2mClientToSession(endpoint).getSecurityInfo();
  96 + try {
  97 + if (securityInfo != null) {
  98 + add(securityInfo);
  99 + }
  100 + } catch (NonUniqueSecurityInfoException e) {
  101 + e.printStackTrace();
  102 + }
  103 + }
  104 + return securityInfo;
  105 + }
  106 +
  107 + @Override
  108 + public SecurityInfo getByIdentity(String pskIdentity) {
  109 + SecurityInfo securityInfo = securityStore.getByIdentity(pskIdentity);
  110 + if (securityInfo == null) {
  111 + securityInfo = clientContext.addLwM2mClientToSession(pskIdentity).getSecurityInfo();
  112 + try {
  113 + if (securityInfo != null) {
  114 + add(securityInfo);
  115 + }
  116 + } catch (NonUniqueSecurityInfoException e) {
  117 + e.printStackTrace();
  118 + }
  119 + }
  120 + return securityInfo;
  121 + }
  122 + }
  123 +}
... ...
... ... @@ -54,6 +54,10 @@
54 54 </dependency>
55 55 <dependency>
56 56 <groupId>org.thingsboard.common</groupId>
  57 + <artifactId>cache</artifactId>
  58 + </dependency>
  59 + <dependency>
  60 + <groupId>org.thingsboard.common</groupId>
57 61 <artifactId>util</artifactId>
58 62 </dependency>
59 63 <dependency>
... ...
... ... @@ -20,10 +20,10 @@ import lombok.Data;
20 20 import lombok.Getter;
21 21 import lombok.extern.slf4j.Slf4j;
22 22 import org.springframework.beans.factory.annotation.Autowired;
23   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
24 23 import org.springframework.stereotype.Service;
25 24 import org.thingsboard.server.queue.discovery.TbServiceInfoProvider;
26 25 import org.thingsboard.server.queue.scheduler.SchedulerComponent;
  26 +import org.thingsboard.server.queue.util.TbTransportComponent;
27 27
28 28 import javax.annotation.PostConstruct;
29 29 import javax.annotation.PreDestroy;
... ... @@ -35,8 +35,6 @@ import java.util.concurrent.Executors;
35 35 */
36 36 @Slf4j
37 37 @Data
38   -@Service
39   -@ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true')")
40 38 public abstract class TransportContext {
41 39
42 40 protected final ObjectMapper mapper = new ObjectMapper();
... ...
... ... @@ -186,10 +186,6 @@ public class LwM2MTransportConfigServer {
186 186 @Value("${transport.lwm2m.server.secure.alias:}")
187 187 private String serverAlias;
188 188
189   - @Getter
190   - @Value("${transport.lwm2m.secure.redis_url:}")
191   - private String redisUrl;
192   -
193 189 @PostConstruct
194 190 public void init() {
195 191 modelsValue = ObjectLoader.loadDefault();
... ...
... ... @@ -46,6 +46,10 @@
46 46 <artifactId>javax.annotation-api</artifactId>
47 47 </dependency>
48 48 <dependency>
  49 + <groupId>com.fasterxml.jackson.core</groupId>
  50 + <artifactId>jackson-databind</artifactId>
  51 + </dependency>
  52 + <dependency>
49 53 <groupId>org.slf4j</groupId>
50 54 <artifactId>slf4j-api</artifactId>
51 55 </dependency>
... ...
common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java renamed from common/dao-api/src/main/java/org/thingsboard/server/dao/util/mapping/JacksonUtil.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.dao.util.mapping;
  16 +package org.thingsboard.common.util;
17 17
18 18 import com.fasterxml.jackson.core.JsonProcessingException;
19 19 import com.fasterxml.jackson.core.type.TypeReference;
... ...
... ... @@ -41,6 +41,10 @@
41 41 </dependency>
42 42 <dependency>
43 43 <groupId>org.thingsboard.common</groupId>
  44 + <artifactId>cache</artifactId>
  45 + </dependency>
  46 + <dependency>
  47 + <groupId>org.thingsboard.common</groupId>
44 48 <artifactId>message</artifactId>
45 49 </dependency>
46 50 <dependency>
... ...
... ... @@ -49,7 +49,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionRequest;
49 49 import org.thingsboard.server.dao.entity.EntityService;
50 50 import org.thingsboard.server.dao.exception.DataValidationException;
51 51 import org.thingsboard.server.dao.service.DataValidator;
52   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  52 +import org.thingsboard.common.util.JacksonUtil;
53 53
54 54 import java.io.PrintWriter;
55 55 import java.io.StringWriter;
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.cache;
17 17
18 18 import org.springframework.cache.interceptor.KeyGenerator;
  19 +import org.springframework.stereotype.Component;
19 20 import org.thingsboard.server.common.data.id.TenantId;
20 21 import org.thingsboard.server.common.data.security.DeviceCredentials;
21 22 import org.thingsboard.server.dao.device.DeviceCredentialsService;
... ... @@ -24,6 +25,7 @@ import java.lang.reflect.Method;
24 25
25 26 import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CREDENTIALS_CACHE;
26 27
  28 +@Component("previousDeviceCredentialsId")
27 29 public class PreviousDeviceCredentialsIdKeyGenerator implements KeyGenerator {
28 30
29 31 private static final String NOT_VALID_DEVICE = DEVICE_CREDENTIALS_CACHE + "_notValidDeviceCredentialsId";
... ...
... ... @@ -33,7 +33,7 @@ import org.thingsboard.server.common.msg.EncryptionUtil;
33 33 import org.thingsboard.server.dao.entity.AbstractEntityService;
34 34 import org.thingsboard.server.dao.exception.DataValidationException;
35 35 import org.thingsboard.server.dao.service.DataValidator;
36   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  36 +import org.thingsboard.common.util.JacksonUtil;
37 37
38 38 import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CREDENTIALS_CACHE;
39 39 import static org.thingsboard.server.dao.service.Validator.validateId;
... ...
... ... @@ -75,7 +75,7 @@ import org.thingsboard.server.dao.service.DataValidator;
75 75 import org.thingsboard.server.dao.service.PaginatedRemover;
76 76 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
77 77 import org.thingsboard.server.dao.tenant.TenantDao;
78   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  78 +import org.thingsboard.common.util.JacksonUtil;
79 79
80 80 import javax.annotation.Nullable;
81 81 import java.util.ArrayList;
... ...
... ... @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.id.TenantId;
31 31 import org.thingsboard.server.dao.model.BaseSqlEntity;
32 32 import org.thingsboard.server.dao.model.ModelConstants;
33 33 import org.thingsboard.server.dao.model.SearchTextEntity;
34   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  34 +import org.thingsboard.common.util.JacksonUtil;
35 35 import org.thingsboard.server.dao.util.mapping.JsonBinaryType;
36 36 import org.thingsboard.server.dao.util.mapping.JsonStringType;
37 37
... ...
... ... @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.id.TenantId;
32 32 import org.thingsboard.server.dao.model.BaseSqlEntity;
33 33 import org.thingsboard.server.dao.model.ModelConstants;
34 34 import org.thingsboard.server.dao.model.SearchTextEntity;
35   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  35 +import org.thingsboard.common.util.JacksonUtil;
36 36 import org.thingsboard.server.dao.util.mapping.JsonBinaryType;
37 37
38 38 import javax.persistence.Column;
... ...
... ... @@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.tenant.profile.TenantProfileData;
27 27 import org.thingsboard.server.dao.model.BaseSqlEntity;
28 28 import org.thingsboard.server.dao.model.ModelConstants;
29 29 import org.thingsboard.server.dao.model.SearchTextEntity;
30   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  30 +import org.thingsboard.common.util.JacksonUtil;
31 31 import org.thingsboard.server.dao.util.mapping.JsonBinaryType;
32 32
33 33 import javax.persistence.Column;
... ...
... ... @@ -48,7 +48,7 @@ import org.thingsboard.server.dao.service.DataValidator;
48 48 import org.thingsboard.server.dao.service.PaginatedRemover;
49 49 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
50 50 import org.thingsboard.server.dao.tenant.TenantDao;
51   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  51 +import org.thingsboard.common.util.JacksonUtil;
52 52
53 53 import java.util.HashMap;
54 54 import java.util.Map;
... ...
... ... @@ -19,6 +19,7 @@ import org.hibernate.type.descriptor.WrapperOptions;
19 19 import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
20 20 import org.hibernate.type.descriptor.java.MutableMutabilityPlan;
21 21 import org.hibernate.usertype.DynamicParameterizedType;
  22 +import org.thingsboard.common.util.JacksonUtil;
22 23
23 24 import java.util.Properties;
24 25
... ...
... ... @@ -46,7 +46,7 @@ import org.thingsboard.server.common.data.query.EntityKeyType;
46 46 import org.thingsboard.server.common.data.relation.EntityRelation;
47 47 import org.thingsboard.server.common.data.relation.RelationTypeGroup;
48 48 import org.thingsboard.server.dao.alarm.AlarmOperationResult;
49   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  49 +import org.thingsboard.common.util.JacksonUtil;
50 50
51 51 import java.util.Arrays;
52 52 import java.util.Collections;
... ...
... ... @@ -854,6 +854,11 @@
854 854 </dependency>
855 855 <dependency>
856 856 <groupId>org.thingsboard.common</groupId>
  857 + <artifactId>cache</artifactId>
  858 + <version>${project.version}</version>
  859 + </dependency>
  860 + <dependency>
  861 + <groupId>org.thingsboard.common</groupId>
857 862 <artifactId>actor</artifactId>
858 863 <version>${project.version}</version>
859 864 </dependency>
... ...
... ... @@ -23,7 +23,7 @@ import org.mockito.junit.MockitoJUnitRunner;
23 23 import org.thingsboard.server.common.data.id.TenantId;
24 24 import org.thingsboard.server.common.msg.TbMsg;
25 25 import org.thingsboard.server.common.msg.TbMsgMetaData;
26   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  26 +import org.thingsboard.common.util.JacksonUtil;
27 27
28 28 @RunWith(MockitoJUnitRunner.class)
29 29 public class TbNodeUtilsTest {
... ...
... ... @@ -28,7 +28,7 @@ import org.thingsboard.rule.engine.api.TbNodeException;
28 28 import org.thingsboard.server.common.data.DataConstants;
29 29 import org.thingsboard.server.common.msg.TbMsg;
30 30 import org.thingsboard.server.common.msg.TbMsgMetaData;
31   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  31 +import org.thingsboard.common.util.JacksonUtil;
32 32
33 33 import static org.thingsboard.common.util.DonAsynchron.withCallback;
34 34
... ...
... ... @@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
35 35 import org.thingsboard.server.common.msg.TbMsg;
36 36 import org.thingsboard.server.common.msg.session.SessionMsgType;
37 37 import org.thingsboard.server.dao.timeseries.TimeseriesService;
38   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  38 +import org.thingsboard.common.util.JacksonUtil;
39 39
40 40 import java.math.BigDecimal;
41 41 import java.math.RoundingMode;
... ...
... ... @@ -25,20 +25,17 @@ import org.thingsboard.rule.engine.api.TbContext;
25 25 import org.thingsboard.rule.engine.profile.state.PersistedAlarmRuleState;
26 26 import org.thingsboard.rule.engine.profile.state.PersistedAlarmState;
27 27 import org.thingsboard.server.common.data.DataConstants;
28   -import org.thingsboard.server.common.data.Tenant;
29 28 import org.thingsboard.server.common.data.alarm.Alarm;
30 29 import org.thingsboard.server.common.data.alarm.AlarmSeverity;
31 30 import org.thingsboard.server.common.data.alarm.AlarmStatus;
32 31 import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm;
33   -import org.thingsboard.server.common.data.id.CustomerId;
34 32 import org.thingsboard.server.common.data.id.EntityId;
35   -import org.thingsboard.server.common.data.id.TenantId;
36 33 import org.thingsboard.server.common.data.query.EntityKeyType;
37 34 import org.thingsboard.server.common.data.query.KeyFilter;
38 35 import org.thingsboard.server.common.msg.TbMsg;
39 36 import org.thingsboard.server.common.msg.TbMsgMetaData;
40 37 import org.thingsboard.server.common.msg.queue.ServiceQueue;
41   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  38 +import org.thingsboard.common.util.JacksonUtil;
42 39
43 40 import java.util.ArrayList;
44 41 import java.util.Comparator;
... ...
... ... @@ -40,7 +40,7 @@ import org.thingsboard.server.common.msg.TbMsg;
40 40 import org.thingsboard.server.common.msg.session.SessionMsgType;
41 41 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
42 42 import org.thingsboard.server.dao.sql.query.EntityKeyMapping;
43   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  43 +import org.thingsboard.common.util.JacksonUtil;
44 44
45 45 import java.util.ArrayList;
46 46 import java.util.HashMap;
... ...
... ... @@ -38,7 +38,7 @@ import org.thingsboard.server.common.data.rule.RuleNodeState;
38 38 import org.thingsboard.server.common.msg.TbMsg;
39 39 import org.thingsboard.server.common.msg.TbMsgMetaData;
40 40 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
41   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  41 +import org.thingsboard.common.util.JacksonUtil;
42 42
43 43 import java.util.Map;
44 44 import java.util.UUID;
... ...
... ... @@ -16,31 +16,8 @@
16 16 package org.thingsboard.rule.engine.profile;
17 17
18 18 import lombok.Data;
19   -import lombok.extern.slf4j.Slf4j;
20 19 import org.codehaus.jackson.annotate.JsonIgnoreProperties;
21   -import org.thingsboard.rule.engine.api.EmptyNodeConfiguration;
22 20 import org.thingsboard.rule.engine.api.NodeConfiguration;
23   -import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache;
24   -import org.thingsboard.rule.engine.api.RuleNode;
25   -import org.thingsboard.rule.engine.api.TbContext;
26   -import org.thingsboard.rule.engine.api.TbNode;
27   -import org.thingsboard.rule.engine.api.TbNodeConfiguration;
28   -import org.thingsboard.rule.engine.api.TbNodeException;
29   -import org.thingsboard.server.common.data.DataConstants;
30   -import org.thingsboard.server.common.data.Device;
31   -import org.thingsboard.server.common.data.DeviceProfile;
32   -import org.thingsboard.server.common.data.EntityType;
33   -import org.thingsboard.server.common.data.id.DeviceId;
34   -import org.thingsboard.server.common.data.id.DeviceProfileId;
35   -import org.thingsboard.server.common.data.plugin.ComponentType;
36   -import org.thingsboard.server.common.msg.TbMsg;
37   -import org.thingsboard.server.common.msg.TbMsgMetaData;
38   -import org.thingsboard.server.dao.util.mapping.JacksonUtil;
39   -
40   -import java.util.Map;
41   -import java.util.concurrent.ConcurrentHashMap;
42   -import java.util.concurrent.ExecutionException;
43   -import java.util.concurrent.TimeUnit;
44 21
45 22 @Data
46 23 @JsonIgnoreProperties(ignoreUnknown = true)
... ...
... ... @@ -45,9 +45,21 @@
45 45 </properties>
46 46
47 47 <dependencies>
  48 +<!-- <dependency>-->
  49 +<!-- <groupId>org.thingsboard.common.transport</groupId>-->
  50 +<!-- <artifactId>transport-api</artifactId>-->
  51 +<!-- </dependency>-->
48 52 <dependency>
49 53 <groupId>org.thingsboard.common.transport</groupId>
50   - <artifactId>transport-api</artifactId>
  54 + <artifactId>lwm2m</artifactId>
  55 + </dependency>
  56 + <dependency>
  57 + <groupId>org.thingsboard.common</groupId>
  58 + <artifactId>queue</artifactId>
  59 + </dependency>
  60 + <dependency>
  61 + <groupId>org.thingsboard.common</groupId>
  62 + <artifactId>cache</artifactId>
51 63 </dependency>
52 64 <dependency>
53 65 <groupId>org.springframework</groupId>
... ...
... ... @@ -26,7 +26,7 @@ import java.util.Arrays;
26 26 @SpringBootConfiguration
27 27 @EnableAsync
28 28 @EnableScheduling
29   -@ComponentScan({"org.thingsboard.server.lwm2m", "org.thingsboard.server.common", "org.thingsboard.server.transport.lwm2m", "org.thingsboard.server.queue"})
  29 +@ComponentScan({"org.thingsboard.server.lwm2m", "org.thingsboard.server.common", "org.thingsboard.server.transport.lwm2m", "org.thingsboard.server.queue", "org.thingsboard.server.cache"})
30 30 public class ThingsboardLwm2mTransportApplication {
31 31
32 32 private static final String SPRING_CONFIG_NAME_KEY = "--spring.config.name";
... ...
... ... @@ -40,6 +40,83 @@ zk:
40 40 # Name of the directory in zookeeper 'filesystem'
41 41 zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}"
42 42
  43 +cache:
  44 + # caffeine or redis
  45 + type: "${CACHE_TYPE:caffeine}"
  46 +
  47 +caffeine:
  48 + specs:
  49 + relations:
  50 + timeToLiveInMinutes: 1440
  51 + maxSize: 0
  52 + deviceCredentials:
  53 + timeToLiveInMinutes: 1440
  54 + maxSize: 0
  55 + devices:
  56 + timeToLiveInMinutes: 1440
  57 + maxSize: 0
  58 + sessions:
  59 + timeToLiveInMinutes: 1440
  60 + maxSize: 0
  61 + assets:
  62 + timeToLiveInMinutes: 1440
  63 + maxSize: 0
  64 + entityViews:
  65 + timeToLiveInMinutes: 1440
  66 + maxSize: 0
  67 + claimDevices:
  68 + timeToLiveInMinutes: 1
  69 + maxSize: 0
  70 + securitySettings:
  71 + timeToLiveInMinutes: 1440
  72 + maxSize: 0
  73 + tenantProfiles:
  74 + timeToLiveInMinutes: 1440
  75 + maxSize: 0
  76 + deviceProfiles:
  77 + timeToLiveInMinutes: 1440
  78 + maxSize: 0
  79 +
  80 +redis:
  81 + # standalone or cluster
  82 + connection:
  83 + type: "${REDIS_CONNECTION_TYPE:standalone}"
  84 + standalone:
  85 + host: "${REDIS_HOST:localhost}"
  86 + port: "${REDIS_PORT:6379}"
  87 + useDefaultClientConfig: "${REDIS_USE_DEFAULT_CLIENT_CONFIG:true}"
  88 + # this value may be used only if you used not default ClientConfig
  89 + clientName: "${REDIS_CLIENT_NAME:standalone}"
  90 + # this value may be used only if you used not default ClientConfig
  91 + connectTimeout: "${REDIS_CLIENT_CONNECT_TIMEOUT:30000}"
  92 + # this value may be used only if you used not default ClientConfig
  93 + readTimeout: "${REDIS_CLIENT_READ_TIMEOUT:60000}"
  94 + # this value may be used only if you used not default ClientConfig
  95 + usePoolConfig: "${REDIS_CLIENT_USE_POOL_CONFIG:false}"
  96 + cluster:
  97 + # Comma-separated list of "host:port" pairs to bootstrap from.
  98 + nodes: "${REDIS_NODES:}"
  99 + # Maximum number of redirects to follow when executing commands across the cluster.
  100 + max-redirects: "${REDIS_MAX_REDIRECTS:12}"
  101 + useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}"
  102 + # db index
  103 + db: "${REDIS_DB:0}"
  104 + # db password
  105 + password: "${REDIS_PASSWORD:}"
  106 + # pool config
  107 + pool_config:
  108 + maxTotal: "${REDIS_POOL_CONFIG_MAX_TOTAL:128}"
  109 + maxIdle: "${REDIS_POOL_CONFIG_MAX_IDLE:128}"
  110 + minIdle: "${REDIS_POOL_CONFIG_MIN_IDLE:16}"
  111 + testOnBorrow: "${REDIS_POOL_CONFIG_TEST_ON_BORROW:true}"
  112 + testOnReturn: "${REDIS_POOL_CONFIG_TEST_ON_RETURN:true}"
  113 + testWhileIdle: "${REDIS_POOL_CONFIG_TEST_WHILE_IDLE:true}"
  114 + minEvictableMs: "${REDIS_POOL_CONFIG_MIN_EVICTABLE_MS:60000}"
  115 + evictionRunsMs: "${REDIS_POOL_CONFIG_EVICTION_RUNS_MS:30000}"
  116 + maxWaitMills: "${REDIS_POOL_CONFIG_MAX_WAIT_MS:60000}"
  117 + numberTestsPerEvictionRun: "${REDIS_POOL_CONFIG_NUMBER_TESTS_PER_EVICTION_RUN:3}"
  118 + blockWhenExhausted: "${REDIS_POOL_CONFIG_BLOCK_WHEN_EXHAUSTED:true}"
  119 +
43 120 # LWM2M server parameters
44 121 transport:
45 122 # Local LwM2M transport parameters
... ... @@ -102,8 +179,8 @@ transport:
102 179 public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
103 180 private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}" # Only Certificate_x509:
104 181 alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}"
105   - # Redis
106   - redis_url: "${LWM2M_REDIS_URL:''}"
  182 + # Use redis for Security and Registration stores
  183 + redis.enabled: "${LWM2M_REDIS_ENABLED:false}"
107 184
108 185 sessions:
109 186 inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}"
... ...
... ... @@ -88,6 +88,9 @@
88 88 <mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsValue').hasError('required')">
89 89 {{ 'device.lwm2m-value-required' | translate }}
90 90 </mat-error>
  91 + <mat-error *ngIf="deviceCredentialsFormGroup.get('credentialsValue').hasError('jsonError')">
  92 + {{ 'device.lwm2m-value-json-error' | translate }}
  93 + </mat-error>
91 94 <div mat-dialog-actions fxLayoutAlign="center center">
92 95 <button mat-raised-button color="primary"
93 96 matTooltip="{{'device.lwm2m-value-edit-tip' | translate }}"
... ...
... ... @@ -14,7 +14,7 @@
14 14 /// limitations under the License.
15 15 ///
16 16
17   -import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
  17 +import {Component, forwardRef, Input, OnDestroy, OnInit} from '@angular/core';
18 18 import {
19 19 ControlValueAccessor,
20 20 FormBuilder,
... ... @@ -33,19 +33,19 @@ import {
33 33 DeviceCredentials,
34 34 DeviceCredentialsType
35 35 } from '@shared/models/device.models';
36   -import { Subscription } from 'rxjs';
37   -import { distinctUntilChanged } from 'rxjs/operators';
38   -import { SecurityConfigComponent } from '@home/pages/device/lwm2m/security-config.component';
  36 +import {Subscription} from 'rxjs';
  37 +import {distinctUntilChanged} from 'rxjs/operators';
  38 +import {SecurityConfigComponent} from '@home/pages/device/lwm2m/security-config.component';
39 39 import {
40 40 DEFAULT_END_POINT,
41 41 DeviceCredentialsDialogLwm2mData,
42 42 END_POINT,
43 43 getDefaultSecurityConfig,
44   - JSON_ALL_CONFIG
  44 + JSON_ALL_CONFIG, SecurityConfigModels, validateSecurityConfig
45 45 } from '@home/pages/device/lwm2m/security-config.models';
46   -import { TranslateService } from '@ngx-translate/core';
47   -import { MatDialog } from '@angular/material/dialog';
48   -import { isDefinedAndNotNull } from '@core/utils';
  46 +import {TranslateService} from '@ngx-translate/core';
  47 +import {MatDialog} from '@angular/material/dialog';
  48 +import {isDefinedAndNotNull} from '@core/utils';
49 49
50 50 @Component({
51 51 selector: 'tb-device-credentials',
... ... @@ -196,13 +196,19 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
196 196 this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false});
197 197 break;
198 198 case DeviceCredentialsType.X509_CERTIFICATE:
199   - case DeviceCredentialsType.LWM2M_CREDENTIALS:
200 199 this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([Validators.required]);
201 200 this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false});
202 201 this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]);
203 202 this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false});
204 203 this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false});
205 204 break;
  205 + case DeviceCredentialsType.LWM2M_CREDENTIALS:
  206 + this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([Validators.required, this.jsonValidator]);
  207 + this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false});
  208 + this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]);
  209 + this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false});
  210 + this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false});
  211 + break;
206 212 case DeviceCredentialsType.MQTT_BASIC:
207 213 this.deviceCredentialsFormGroup.get('credentialsBasic').enable({emitEvent: false});
208 214 this.deviceCredentialsFormGroup.get('credentialsBasic').updateValueAndValidity({emitEvent: false});
... ... @@ -247,7 +253,11 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
247 253 if (credentialsValue === null || credentialsValue.length === 0) {
248 254 credentialsValue = getDefaultSecurityConfig();
249 255 } else {
250   - credentialsValue = JSON.parse(credentialsValue);
  256 + try {
  257 + credentialsValue = JSON.parse(credentialsValue);
  258 + } catch (e) {
  259 + credentialsValue = getDefaultSecurityConfig();
  260 + }
251 261 }
252 262 const credentialsId = this.deviceCredentialsFormGroup.get('credentialsId').value || DEFAULT_END_POINT;
253 263 this.dialog.open<SecurityConfigComponent, DeviceCredentialsDialogLwm2mData, object>(SecurityConfigComponent, {
... ... @@ -273,4 +283,8 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
273 283 private isDefautLw2mResponse(response: object): boolean {
274 284 return Object.keys(response).length === 0 || JSON.stringify(response) === '[{}]';
275 285 }
  286 +
  287 + private jsonValidator(control: FormControl) {
  288 + return validateSecurityConfig(control.value) ? null: {jsonError: {parsedJson: "error"}};
  289 + }
276 290 }
... ...
... ... @@ -395,21 +395,4 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
395 395 }
396 396 });
397 397 }
398   -
399   - isPathInJson(path: string): boolean {
400   - let isPath = this.findPathInJson(path, ATTRIBUTE);
401   - if (!isPath) {
402   - isPath = this.findPathInJson(path, TELEMETRY);
403   - }
404   - return !!isPath;
405   - }
406   -
407   - private findPathInJson = (path: string, side: string): string => {
408   - if (this.configurationValue.observeAttr) {
409   - if (this.configurationValue.observeAttr[side]) {
410   - return this.configurationValue.bootstrap[side].find(
411   - pathJs => pathJs === path);
412   - }
413   - }
414   - }
415 398 }
... ...
... ... @@ -134,7 +134,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
134 134 }
135 135
136 136 private add(object: ObjectLwM2M): void {
137   - if (this.modelValue.indexOf(object.id) === -1) {
  137 + if (isDefinedAndNotNull(this.modelValue) && this.modelValue.indexOf(object.id) === -1) {
138 138 this.modelValue.push(object.id);
139 139 this.objectsList.push(object);
140 140 this.lwm2mListFormGroup.get('objectsList').setValue(this.objectsList);
... ... @@ -151,9 +151,6 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
151 151 index = this.modelValue.indexOf(object.id);
152 152 this.modelValue.splice(index, 1);
153 153 this.removeList.next(object);
154   - if (!this.modelValue.length) {
155   - this.modelValue = null;
156   - }
157 154 this.clear();
158 155 }
159 156 }
... ...
... ... @@ -27,7 +27,7 @@ export const DEFAULT_ID_SERVER = 123;
27 27 export const DEFAULT_ID_BOOTSTRAP = 111;
28 28 export const DEFAULT_HOST_NAME = 'localhost';
29 29 export const DEFAULT_PORT_SERVER_NO_SEC = 5685;
30   -export const DEFAULT_PORT_BOOTSTRAP_NO_SEC = 5686;
  30 +export const DEFAULT_PORT_BOOTSTRAP_NO_SEC = 5687;
31 31 export const DEFAULT_CLIENT_HOLD_OFF_TIME = 1;
32 32 export const DEFAULT_LIFE_TIME = 300;
33 33 export const DEFAULT_MIN_PERIOD = 1;
... ...
... ... @@ -20,7 +20,6 @@ export const DEFAULT_END_POINT = 'default_client_lwm2m_end_point_no_sec';
20 20 export const BOOTSTRAP_SERVERS = 'servers';
21 21 export const BOOTSTRAP_SERVER = 'bootstrapServer';
22 22 export const LWM2M_SERVER = 'lwm2mServer';
23   -export const JSON_OBSERVE = 'jsonObserve';
24 23 export const LEN_MAX_PSK = 64;
25 24 export const LEN_MAX_PRIVATE_KEY = 134;
26 25 export const LEN_MAX_PUBLIC_KEY_RPK = 182;
... ... @@ -148,4 +147,41 @@ export function getDefaultSecurityConfig(): SecurityConfigModels {
148 147 return securityConfigModels;
149 148 }
150 149
  150 +const isSecurityConfigModels = (p: any): p is SecurityConfigModels =>
  151 + p.hasOwnProperty('client') &&
  152 + isClientSecurityConfigType(p['client']) &&
  153 + p.hasOwnProperty('bootstrap') &&
  154 + isBootstrapSecurityConfig(p['bootstrap']);
  155 +
  156 +const isClientSecurityConfigType = (p: any): p is ClientSecurityConfigType =>
  157 + p.hasOwnProperty('securityConfigClientMode') &&
  158 + p.hasOwnProperty('endpoint') &&
  159 + p.hasOwnProperty('identity') &&
  160 + p.hasOwnProperty('key') &&
  161 + p.hasOwnProperty('x509');
  162 +
  163 +const isBootstrapSecurityConfig = (p: any): p is BootstrapSecurityConfig =>
  164 + p.hasOwnProperty('bootstrapServer') &&
  165 + isServerSecurityConfig(p['bootstrapServer']) &&
  166 + p.hasOwnProperty('lwm2mServer') &&
  167 + isServerSecurityConfig(p['lwm2mServer']);
  168 +
  169 +const isServerSecurityConfig = (p: any): p is ServerSecurityConfig =>
  170 + p.hasOwnProperty('securityMode') &&
  171 + p.hasOwnProperty('clientPublicKeyOrId') &&
  172 + p.hasOwnProperty('clientSecretKey');
  173 +
  174 +export function validateSecurityConfig(config: string): boolean {
  175 + try {
  176 + const securityConfig= JSON.parse(config);
  177 + if (isSecurityConfigModels(securityConfig)) {
  178 + return true;
  179 + } else {
  180 + return false;
  181 + }
  182 + } catch (e) {
  183 + return false;
  184 + }
  185 +}
  186 +
151 187
... ...
... ... @@ -912,6 +912,7 @@
912 912 "lwm2m-key-required": "LwM2M Security config key is required.",
913 913 "lwm2m-value": "LwM2M Security config",
914 914 "lwm2m-value-required": "LwM2M Security config value is required.",
  915 + "lwm2m-value-json-error": "LwM2M Security config value is not json format.",
915 916 "lwm2m-endpoint": "Client endpoint/identity",
916 917 "lwm2m-security-info": "Security Config Info",
917 918 "lwm2m-value-edit": "Edit Security config",
... ...