Browse Source

Merge improvements from outdated PR 4527

pull/4536/head
Andrii Shvaika 5 years ago
parent
commit
54543ae4b5
  1. 1
      application/src/main/resources/thingsboard.yml
  2. 27
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/client/LwM2mSoftwareUpdate.java
  3. 17
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java
  4. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java
  5. 30
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java
  6. 105
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java
  7. 47
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java

1
application/src/main/resources/thingsboard.yml

@ -674,6 +674,7 @@ transport:
registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}"
update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}"
un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}"
log_max_length: "${LWM2M_LOG_MAX_LENGTH:100}"
# Use redis for Security and Registration stores
redis.enabled: "${LWM2M_REDIS_ENABLED:false}"
snmp:

27
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/client/LwM2mSoftwareUpdate.java

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.lwm2m.client;
import lombok.Data;
import java.util.UUID;
@Data
public class LwM2mSoftwareUpdate {
private volatile String clientSwVersion;
private volatile String currentSwVersion;
private volatile UUID currentSwId;
}

17
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java

@ -29,6 +29,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
@ -136,18 +137,26 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
@Getter
@Value("${transport.lwm2m.server.security.alias:}")
private String certificateAlias;
@Getter
@Value("${transport.lwm2m.log_max_length:}")
private int logMaxLength;
@PostConstruct
public void init() {
URI uri = null;
try {
File keyStoreFile = new File(Resources.getResource(keyStorePathFile).toURI());
uri = Resources.getResource(keyStorePathFile).toURI();
log.error("URI: {}", uri);
File keyStoreFile = new File(uri);
InputStream inKeyStore = new FileInputStream(keyStoreFile);
keyStoreValue = KeyStore.getInstance(keyStoreType);
keyStoreValue.load(inKeyStore, keyStorePassword == null ? null : keyStorePassword.toCharArray());
} catch (Exception e) {
log.error("Unable to lookup LwM2M keystore. Reason: " + e.getMessage(), e);
throw new RuntimeException("Failed to lookup LwM2M keystore", e);
// Absence of the key store should not block user from using plain LwM2M
// throw new RuntimeException("Failed to lookup LwM2M keystore: " + (uri != null ? uri.toString() : ""), e);
}
}
}

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java

@ -87,6 +87,7 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.CLIENT_NOT_AUTHORIZED;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.DEVICE_ATTRIBUTES_REQUEST;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.FR_OBJECT_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.FR_PATH_RESOURCE_VER_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_ERROR;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LOG_LW2M_INFO;
@ -1420,9 +1421,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
int chunkSize = 0;
int chunk = 0;
byte[] firmwareChunk = firmwareDataCache.get(lwM2MClient.getFrUpdate().getCurrentFwId().toString(), chunkSize, chunk);
Integer objectId = 5;
String verSupportedObject = lwM2MClient.getRegistration().getSupportedObject().get(objectId);
String targetIdVer = LWM2M_SEPARATOR_PATH + objectId + LWM2M_SEPARATOR_KEY + verSupportedObject + LWM2M_SEPARATOR_PATH + 0 + LWM2M_SEPARATOR_PATH + 0;
String verSupportedObject = lwM2MClient.getRegistration().getSupportedObject().get(FR_OBJECT_ID);
String targetIdVer = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_KEY + verSupportedObject + LWM2M_SEPARATOR_PATH + 0 + LWM2M_SEPARATOR_PATH + 0;
lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(),
firmwareChunk, config.getTimeout(), null);
log.warn("updateFirmwareClient [{}] [{}]", lwM2MClient.getFrUpdate().getCurrentFwVersion(), lwM2MClient.getFrUpdate().getClientFwVersion());

30
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java

@ -117,29 +117,29 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
builder.setLocalAddress(config.getHost(), serverPortNoSec);
builder.setLocalSecureAddress(config.getSecureHost(), serverSecurePort);
builder.setDecoder(new DefaultLwM2mNodeDecoder());
/** Use a magic converter to support bad type send by the UI. */
/* Use a magic converter to support bad type send by the UI. */
builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance()));
/** Create CoAP Config */
/* Create CoAP Config */
NetworkConfig networkConfig = getCoapConfig(serverPortNoSec, serverSecurePort);
BlockwiseLayer blockwiseLayer = new BlockwiseLayer(networkConfig);
builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort));
/** Define model provider (Create Models )*/
/* Define model provider (Create Models )*/
LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.helper, this.context);
config.setModelProvider(modelProvider);
builder.setObjectModelProvider(modelProvider);
/** Create credentials */
/* Create credentials */
this.setServerWithCredentials(builder);
/** Set securityStore with new registrationStore */
/* Set securityStore with new registrationStore */
builder.setSecurityStore(securityStore);
builder.setRegistrationStore(registrationStore);
/** Create DTLS Config */
/* Create DTLS Config */
DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();
dtlsConfig.setServerOnly(true);
dtlsConfig.setRecommendedSupportedGroupsOnly(config.isRecommendedSupportedGroups());
@ -156,10 +156,10 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);
}
/** Set DTLS Config */
/* Set DTLS Config */
builder.setDtlsConfig(dtlsConfig);
/** Create LWM2M server */
/* Create LWM2M server */
return builder.build();
}
@ -173,10 +173,10 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
trustedCertificates[0] = rootCAX509Cert;
builder.setTrustedCertificates(trustedCertificates);
} else {
/** by default trust all */
/* by default trust all */
builder.setTrustedCertificates(new X509Certificate[0]);
}
/** Set securityStore with registrationStore*/
/* Set securityStore with registrationStore*/
builder.setAuthorizer(new DefaultAuthorizer(securityStore, new SecurityChecker() {
@Override
protected boolean matchX509Identity(String endpoint, String receivedX509CommonName,
@ -189,7 +189,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
this.infoPramsUri("RPK");
this.infoParamsServerKey(this.publicKey, this.privateKey);
} else {
/** by default trust all */
/* by default trust all */
builder.setTrustedCertificates(new X509Certificate[0]);
log.info("Unable to load X509 files for LWM2MServer");
this.pskMode = true;
@ -256,7 +256,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
}
private void generateKeyForRPK() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException {
/** Get Elliptic Curve Parameter spec for secp256r1 */
/* Get Elliptic Curve Parameter spec for secp256r1 */
AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC");
algoParameters.init(new ECGenParameterSpec("secp256r1"));
ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class);
@ -280,17 +280,17 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
}
private void infoParamsServerKey(PublicKey publicKey, PrivateKey privateKey) {
/** Get x coordinate */
/* Get x coordinate */
byte[] x = ((ECPublicKey) publicKey).getW().getAffineX().toByteArray();
if (x[0] == 0)
x = Arrays.copyOfRange(x, 1, x.length);
/** Get Y coordinate */
/* Get Y coordinate */
byte[] y = ((ECPublicKey) publicKey).getW().getAffineY().toByteArray();
if (y[0] == 0)
y = Arrays.copyOfRange(y, 1, y.length);
/** Get Curves params */
/* Get Curves params */
String params = ((ECPublicKey) publicKey).getParams().toString();
String privHex = Hex.encodeHexString(privateKey.getEncoded());
log.info(" \n- Public Key (Hex): [{}] \n" +

105
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java

@ -23,73 +23,72 @@ public class LwM2mNetworkConfig {
NetworkConfig coapConfig = new NetworkConfig();
coapConfig.setInt(NetworkConfig.Keys.COAP_PORT,serverPortNoSec);
coapConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT,serverSecurePort);
/**
* Example:Property for large packet:
* #NetworkConfig config = new NetworkConfig();
* #config.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE,32);
* #config.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE,32);
* #config.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE,2048);
* #config.setInt(NetworkConfig.Keys.MAX_RETRANSMIT,3);
* #config.setInt(NetworkConfig.Keys.MAX_TRANSMIT_WAIT,120000);
/*
Example:Property for large packet:
#NetworkConfig config = new NetworkConfig();
#config.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE,32);
#config.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE,32);
#config.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE,2048);
#config.setInt(NetworkConfig.Keys.MAX_RETRANSMIT,3);
#config.setInt(NetworkConfig.Keys.MAX_TRANSMIT_WAIT,120000);
*/
/**
* Property to indicate if the response should always include the Block2 option \
* when client request early blockwise negociation but the response can be sent on one packet.
* - value of false indicate that the server will respond without block2 option if no further blocks are required.
* - value of true indicate that the server will response with block2 option event if no further blocks are required.
* CoAP client will try to use block mode
* or adapt the block size when receiving a 4.13 Entity too large response code
/*
Property to indicate if the response should always include the Block2 option \
when client request early blockwise negociation but the response can be sent on one packet.
- value of false indicate that the server will respond without block2 option if no further blocks are required.
- value of true indicate that the server will response with block2 option event if no further blocks are required.
CoAP client will try to use block mode
or adapt the block size when receiving a 4.13 Entity too large response code
*/
coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_STRICT_BLOCK2_OPTION, true);
/***
* Property to indicate if the response should always include the Block2 option \
* when client request early blockwise negociation but the response can be sent on one packet.
* - value of false indicate that the server will respond without block2 option if no further blocks are required.
* - value of true indicate that the server will response with block2 option event if no further blocks are required.
/*
Property to indicate if the response should always include the Block2 option \
when client request early blockwise negociation but the response can be sent on one packet.
- value of false indicate that the server will respond without block2 option if no further blocks are required.
- value of true indicate that the server will response with block2 option event if no further blocks are required.
*/
coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true);
coapConfig.setInt(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, 300000);
/**
* !!! REQUEST_ENTITY_TOO_LARGE CODE=4.13
* The maximum size of a resource body (in bytes) that will be accepted
* as the payload of a POST/PUT or the response to a GET request in a
* transparent> blockwise transfer.
* This option serves as a safeguard against excessive memory
* consumption when many resources contain large bodies that cannot be
* transferred in a single CoAP message. This option has no impact on
* *manually* managed blockwise transfers in which the blocks are handled individually.
* Note that this option does not prevent local clients or resource
* implementations from sending large bodies as part of a request or response to a peer.
* The default value of this property is DEFAULT_MAX_RESOURCE_BODY_SIZE = 8192
* A value of {@code 0} turns off transparent handling of blockwise transfers altogether.
/*
!!! REQUEST_ENTITY_TOO_LARGE CODE=4.13
The maximum size of a resource body (in bytes) that will be accepted
as the payload of a POST/PUT or the response to a GET request in a
transparent> blockwise transfer.
This option serves as a safeguard against excessive memory
consumption when many resources contain large bodies that cannot be
transferred in a single CoAP message. This option has no impact on
*manually* managed blockwise transfers in which the blocks are handled individually.
Note that this option does not prevent local clients or resource
implementations from sending large bodies as part of a request or response to a peer.
The default value of this property is DEFAULT_MAX_RESOURCE_BODY_SIZE = 8192
A value of {@code 0} turns off transparent handling of blockwise transfers altogether.
*/
// coapConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 8192);
coapConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 256 * 1024 * 1024);
/**
* The default DTLS response matcher.
* Supported values are STRICT, RELAXED, or PRINCIPAL.
* The default value is STRICT.
* Create new instance of udp endpoint context matcher.
* Params:
* checkAddress
* true with address check, (STRICT, UDP)
* - false, without
/*
The default DTLS response matcher.
Supported values are STRICT, RELAXED, or PRINCIPAL.
The default value is STRICT.
Create new instance of udp endpoint context matcher.
Params:
checkAddress
true with address check, (STRICT, UDP)
- false, without
*/
coapConfig.setString(NetworkConfig.Keys.RESPONSE_MATCHING, "STRICT");
/**
* https://tools.ietf.org/html/rfc7959#section-2.9.3
* The block size (number of bytes) to use when doing a blockwise transfer. \
* This value serves as the upper limit for block size in blockwise transfers
/*
https://tools.ietf.org/html/rfc7959#section-2.9.3
The block size (number of bytes) to use when doing a blockwise transfer. \
This value serves as the upper limit for block size in blockwise transfers
*/
coapConfig.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE, 1024);
/**
* The maximum payload size (in bytes) that can be transferred in a
* single message, i.e. without requiring a blockwise transfer.
* NB: this value MUST be adapted to the maximum message size supported by the transport layer.
* In particular, this value cannot exceed the network's MTU if UDP is used as the transport protocol
* DEFAULT_VALUE = 1024
/*
The maximum payload size (in bytes) that can be transferred in a
single message, i.e. without requiring a blockwise transfer.
NB: this value MUST be adapted to the maximum message size supported by the transport layer.
In particular, this value cannot exceed the network's MTU if UDP is used as the transport protocol
DEFAULT_VALUE = 1024
*/
coapConfig.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE, 1024);

47
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java

@ -404,17 +404,40 @@ public class LwM2mTransportRequest {
}
}
private void infoWriteResponse(Registration registration, LwM2mResponse response,
DownlinkRequest request) {
LwM2mNode node = ((WriteRequest) request).getNode();
Object value = this.converter.convertValue(((LwM2mSingleResource) node).getValue(),
((LwM2mSingleResource) node).getType(), ResourceModel.Type.STRING, request.getPath());
String msg = String.format("%s: Update finished successfully: CoapCde - %s Lwm2m code - %d name - %s Resource path - %s value - %s",
LOG_LW2M_INFO, ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(),
response.getCode().getName(), request.getPath().toString(), value);
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
log.trace("[{}] [{}] [{}] - [{}] [{}] Update finished successfully: [{}]", request.getClass().getName().toString(), registration.getEndpoint(),
((Response) response.getCoapResponse()).getCode(), response.getCode(),
request.getPath().toString(), value);
private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request) {
try {
LwM2mNode node = ((WriteRequest) request).getNode();
String msg;
Object value;
LwM2mSingleResource singleResource = (LwM2mSingleResource) node;
if (singleResource.getType() == ResourceModel.Type.STRING || singleResource.getType() == ResourceModel.Type.OPAQUE) {
int valueLength;
if (singleResource.getType() == ResourceModel.Type.STRING) {
valueLength = ((String) singleResource.getValue()).length();
value = ((String) singleResource.getValue())
.substring(Math.min(valueLength, config.getLogMaxLength()));
} else {
valueLength = ((byte[]) singleResource.getValue()).length;
value = new String(Arrays.copyOf(((byte[]) singleResource.getValue()),
Math.min(valueLength, config.getLogMaxLength())));
}
value = valueLength > config.getLogMaxLength() ? value + "..." : value;
msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path - %s length - %s value - %s",
LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value);
} else {
value = this.converter.convertValue(singleResource.getValue(),
singleResource.getType(), ResourceModel.Type.STRING, request.getPath());
msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path - %s value - %s",
LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value);
}
if (msg != null) {
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
log.warn("[{}] [{}] [{}] - [{}] [{}] Update finished successfully: [{}]", request.getClass().getName(), registration.getEndpoint(),
((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString(), value);
}
} catch (Exception e) {
log.trace("Fail convert value from request to string. ", e);
}
}
}

Loading…
Cancel
Save