Skip to content

Commit

Permalink
Leshan client refactoring : use one CoAP endpoint by server
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Aug 16, 2018
1 parent fc627d0 commit ad6fe62
Show file tree
Hide file tree
Showing 19 changed files with 745 additions and 449 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,20 @@
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.californium.core.CoapServer;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.core.network.config.NetworkConfig;
import org.eclipse.californium.core.server.resources.Resource;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
import org.eclipse.leshan.client.LwM2mClient;
import org.eclipse.leshan.client.californium.impl.BootstrapResource;
import org.eclipse.leshan.client.californium.impl.CaliforniumEndpointsManager;
import org.eclipse.leshan.client.californium.impl.CaliforniumLwM2mRequestSender;
import org.eclipse.leshan.client.californium.impl.ObjectResource;
import org.eclipse.leshan.client.californium.impl.RootResource;
import org.eclipse.leshan.client.observer.LwM2mClientObserver;
import org.eclipse.leshan.client.observer.LwM2mClientObserverAdapter;
import org.eclipse.leshan.client.observer.LwM2mClientObserverDispatcher;
import org.eclipse.leshan.client.resource.LwM2mObjectEnabler;
import org.eclipse.leshan.client.servers.BootstrapHandler;
import org.eclipse.leshan.client.servers.DmServerInfo;
import org.eclipse.leshan.client.servers.RegistrationEngine;
import org.eclipse.leshan.client.servers.ServerInfo;
import org.eclipse.leshan.core.californium.EndpointFactory;
import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder;
import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder;
import org.eclipse.leshan.util.Validate;
Expand All @@ -60,12 +57,11 @@ public class LeshanClient implements LwM2mClient {
private final BootstrapHandler bootstrapHandler;
private final LwM2mClientObserverDispatcher observers;

private CoapEndpoint securedEndpoint;
private CoapEndpoint unsecuredEndpoint;
private final CaliforniumEndpointsManager endpointsManager;

public LeshanClient(String endpoint, CoapEndpoint unsecuredEndpoint, CoapEndpoint securedEndpoint,
List<? extends LwM2mObjectEnabler> objectEnablers, NetworkConfig coapConfig,
Map<String, String> additionalAttributes) {
public LeshanClient(String endpoint, InetSocketAddress localAddress,
List<? extends LwM2mObjectEnabler> objectEnablers, NetworkConfig coapConfig, Builder dtlsConfigBuilder,
EndpointFactory endpointFactory, Map<String, String> additionalAttributes) {

Validate.notNull(endpoint);
Validate.notEmpty(objectEnablers);
Expand All @@ -84,58 +80,16 @@ public LeshanClient(String endpoint, CoapEndpoint unsecuredEndpoint, CoapEndpoin
// Create Client Observers
observers = new LwM2mClientObserverDispatcher();

// Set unsecured CoAP endpoint
this.unsecuredEndpoint = unsecuredEndpoint;

// Set secured CoAP endpoint
this.securedEndpoint = securedEndpoint;
if (securedEndpoint != null) {
if (securedEndpoint.getConnector() instanceof DTLSConnector) {
final DTLSConnector dtlsConnector = (DTLSConnector) securedEndpoint.getConnector();
observers.addObserver(new LwM2mClientObserverAdapter() {
@Override
public void onBootstrapSuccess(ServerInfo bsserver) {
dtlsConnector.clearConnectionState();
}

@Override
public void onBootstrapTimeout(ServerInfo bsserver) {
dtlsConnector.clearConnectionState();
}

@Override
public void onRegistrationTimeout(DmServerInfo server) {
dtlsConnector.clearConnectionState();
}

@Override
public void onUpdateTimeout(DmServerInfo server) {
dtlsConnector.clearConnectionState();
}
});
}
}

// Create sender
requestSender = new CaliforniumLwM2mRequestSender(securedEndpoint, unsecuredEndpoint);

// Create registration engine
bootstrapHandler = new BootstrapHandler(this.objectEnablers);
engine = new RegistrationEngine(endpoint, this.objectEnablers, requestSender, bootstrapHandler, observers,
additionalAttributes);

// Create CoAP Server
clientSideServer = new CoapServer(coapConfig) {
@Override
protected Resource createRoot() {
// Use to handle Delete on "/"
return new RootResource(bootstrapHandler);
return new org.eclipse.leshan.client.californium.impl.RootResource(bootstrapHandler);
}
};
if (securedEndpoint != null)
clientSideServer.addEndpoint(securedEndpoint);
if (unsecuredEndpoint != null)
clientSideServer.addEndpoint(unsecuredEndpoint);

// Create CoAP resources for each lwm2m Objects.
for (LwM2mObjectEnabler enabler : objectEnablers) {
Expand All @@ -146,34 +100,43 @@ protected Resource createRoot() {

// Create CoAP resources needed for the bootstrap sequence
clientSideServer.add(new BootstrapResource(bootstrapHandler));

// Create EndpointHandler
endpointsManager = new CaliforniumEndpointsManager(clientSideServer, localAddress, coapConfig,
dtlsConfigBuilder, endpointFactory);

// Create sender
requestSender = new CaliforniumLwM2mRequestSender(endpointsManager);

// Create registration engine
engine = new RegistrationEngine(endpoint, this.objectEnablers, endpointsManager, requestSender,
bootstrapHandler, observers, additionalAttributes);

}

@Override
public void start() {
LOG.info("Starting Leshan client ...");
clientSideServer.start();
endpointsManager.start();
engine.start();

if (LOG.isInfoEnabled()) {
LOG.info("Leshan client[endpoint:{}] started at {} {}", engine.getEndpoint(),
getUnsecuredAddress() == null ? "" : "coap://" + getUnsecuredAddress(),
getSecuredAddress() == null ? "" : "coaps://" + getSecuredAddress());
LOG.info("Leshan client[endpoint:{}] started.", engine.getEndpoint());
}
}

@Override
public void stop(boolean deregister) {
LOG.info("Stopping Leshan Client ...");
engine.stop(deregister);
clientSideServer.stop();
endpointsManager.stop();
LOG.info("Leshan client stopped.");
}

@Override
public void destroy(boolean deregister) {
LOG.info("Destroying Leshan client ...");
engine.destroy(deregister);
clientSideServer.destroy();
endpointsManager.destroy();
LOG.info("Leshan client destroyed.");
}

Expand All @@ -190,16 +153,8 @@ public CoapServer getCoapServer() {
return clientSideServer;
}

public InetSocketAddress getUnsecuredAddress() {
if (unsecuredEndpoint == null)
return null;
return unsecuredEndpoint.getAddress();
}

public InetSocketAddress getSecuredAddress() {
if (securedEndpoint == null)
return null;
return securedEndpoint.getAddress();
public InetSocketAddress getAddress() {
return endpointsManager.getEndpoint(null).getAddress();
}

public void addObserver(LwM2mClientObserver observer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@
import java.util.List;
import java.util.Map;

import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.core.network.config.NetworkConfig;
import org.eclipse.californium.core.network.config.NetworkConfig.Keys;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
import org.eclipse.leshan.LwM2mId;
import org.eclipse.leshan.client.californium.impl.SecurityObjectPskStore;
import org.eclipse.leshan.client.object.Device;
import org.eclipse.leshan.client.object.Security;
import org.eclipse.leshan.client.object.Server;
Expand All @@ -35,28 +32,20 @@
import org.eclipse.leshan.core.californium.EndpointFactory;
import org.eclipse.leshan.core.request.BindingMode;
import org.eclipse.leshan.util.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Helper class to build and configure a Californium based Leshan Lightweight M2M client.
*/
public class LeshanClientBuilder {

private static final Logger LOG = LoggerFactory.getLogger(LeshanClientBuilder.class);

private final String endpoint;

private InetSocketAddress localAddress;
private InetSocketAddress localSecureAddress;
private List<? extends LwM2mObjectEnabler> objectEnablers;

private NetworkConfig coapConfig;
private Builder dtlsConfigBuilder;

private boolean noSecuredEndpoint;
private boolean noUnsecuredEndpoint;

private EndpointFactory endpointFactory;
private Map<String, String> additionalAttributes;

Expand All @@ -66,7 +55,6 @@ public class LeshanClientBuilder {
* The builder is initialized with the following default values:
* <ul>
* <li><em>local address</em>: a local address and an ephemeral port (picked up during binding)</li>
* <li><em>local secure address</em>: a local address and an ephemeral port (picked up during binding)</li>
* <li><em>object enablers</em>:
* <ul>
* <li>Security(0) with one instance (DM server security): uri=<em>coap://leshan.eclipse.org:5683</em>, mode=NoSec
Expand Down Expand Up @@ -96,18 +84,6 @@ public LeshanClientBuilder setLocalAddress(String hostname, int port) {
return this;
}

/**
* Sets the local secure end-point address
*/
public LeshanClientBuilder setLocalSecureAddress(String hostname, int port) {
if (hostname == null) {
this.localSecureAddress = new InetSocketAddress(port);
} else {
this.localSecureAddress = new InetSocketAddress(hostname, port);
}
return this;
}

/**
* <p>
* Sets the list of objects enablers
Expand Down Expand Up @@ -145,22 +121,6 @@ public LeshanClientBuilder setEndpointFactory(EndpointFactory endpointFactory) {
return this;
}

/**
* deactivate unsecured CoAP endpoint
*/
public LeshanClientBuilder disableUnsecuredEndpoint() {
this.noUnsecuredEndpoint = true;
return this;
}

/**
* deactivate secured CoAP endpoint (DTLS)
*/
public LeshanClientBuilder disableSecuredEndpoint() {
this.noSecuredEndpoint = true;
return this;
}

/**
* Set the additionalAttributes for {@link org.eclipse.leshan.core.request.RegisterRequest}.
*/
Expand Down Expand Up @@ -201,33 +161,21 @@ public LeshanClient build() {
}

// handle dtlsConfig
DtlsConnectorConfig dtlsConfig = null;
if (dtlsConfigBuilder == null) {
dtlsConfigBuilder = new DtlsConnectorConfig.Builder();
}
DtlsConnectorConfig incompleteConfig = dtlsConfigBuilder.getIncompleteConfig();

// Handle PSK Store
LwM2mObjectEnabler securityEnabler = this.objectEnablers.get(LwM2mId.SECURITY);
if (securityEnabler == null) {
throw new IllegalArgumentException("Security object is mandatory");
}
if (incompleteConfig.getPskStore() == null) {
dtlsConfigBuilder.setPskStore(new SecurityObjectPskStore(securityEnabler));
} else {
LOG.warn("PskStore should be automatically set by Leshan. Using a custom implementation is not advised.");
}

// Handle secure address
if (incompleteConfig.getAddress() == null) {
if (localSecureAddress == null) {
localSecureAddress = new InetSocketAddress(0);
if (localAddress == null) {
localAddress = new InetSocketAddress(0);
}
dtlsConfigBuilder.setAddress(localSecureAddress);
} else if (localSecureAddress != null && !localSecureAddress.equals(incompleteConfig.getAddress())) {
dtlsConfigBuilder.setAddress(localAddress);
} else if (localAddress != null && !localAddress.equals(incompleteConfig.getAddress())) {
throw new IllegalStateException(String.format(
"Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for secure address: %s != %s",
localSecureAddress, incompleteConfig.getAddress()));
"Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for address: %s != %s",
localAddress, incompleteConfig.getAddress()));
}

// Handle active peers
Expand All @@ -247,39 +195,7 @@ public LeshanClient build() {
dtlsConfigBuilder.setSniEnabled(false);
}

dtlsConfig = dtlsConfigBuilder.build();

// create endpoints
CoapEndpoint unsecuredEndpoint = null;
if (!noUnsecuredEndpoint) {
if (endpointFactory != null) {
unsecuredEndpoint = endpointFactory.createUnsecuredEndpoint(localAddress, coapConfig, null);
} else {
CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
builder.setInetSocketAddress(localAddress);
builder.setNetworkConfig(coapConfig);
unsecuredEndpoint = builder.build();
}
}

CoapEndpoint securedEndpoint = null;
if (!noSecuredEndpoint) {
if (endpointFactory != null) {
securedEndpoint = endpointFactory.createSecuredEndpoint(dtlsConfig, coapConfig, null);
} else {
CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
builder.setConnector(new DTLSConnector(dtlsConfig));
builder.setNetworkConfig(coapConfig);
securedEndpoint = builder.build();
}
}

if (securedEndpoint == null && unsecuredEndpoint == null) {
throw new IllegalStateException(
"All CoAP enpoints are deactivated, at least one endpoint should be activated");
}

return new LeshanClient(endpoint, unsecuredEndpoint, securedEndpoint, objectEnablers, coapConfig,
return new LeshanClient(endpoint, localAddress, objectEnablers, coapConfig, dtlsConfigBuilder, endpointFactory,
additionalAttributes);
}
}
Loading

0 comments on commit ad6fe62

Please sign in to comment.