Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support of several endpoint providers #1525

Merged
merged 7 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public static LeshanBootstrapServer createBsLeshanServer(LeshanBsServerDemoCLI c
endpointsBuilder.addEndpoint(coapsAddr, Protocol.COAPS);

// Create LWM2M server
builder.setEndpointsProvider(endpointsBuilder.build());
builder.setEndpointsProviders(endpointsBuilder.build());
return builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.server.bootstrap.LeshanBootstrapServer;
import org.eclipse.leshan.server.bootstrap.endpoint.LwM2mBootstrapServerEndpoint;
import org.eclipse.leshan.server.core.demo.json.PublicKeySerDes;
import org.eclipse.leshan.server.core.demo.json.X509CertificateSerDes;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

Expand Down Expand Up @@ -86,22 +86,22 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
}

// search coap and coaps port
Integer coapPort = null;
Integer coapsPort = null;
for (LwM2mBootstrapServerEndpoint endpoint : server.getEndpoints()) {
if (endpoint.getProtocol().equals(Protocol.COAP)) {
coapPort = endpoint.getURI().getPort();
} else if (endpoint.getProtocol().equals(Protocol.COAPS)) {
coapsPort = endpoint.getURI().getPort();
}
}

if ("endpoint".equals(path[0])) {
resp.setStatus(HttpServletResponse.SC_OK);
ArrayNode endpoints = JsonNodeFactory.instance.arrayNode();
for (LwM2mBootstrapServerEndpoint endpoint : server.getEndpoints()) {
ObjectNode ep = JsonNodeFactory.instance.objectNode();
ObjectNode uri = JsonNodeFactory.instance.objectNode();
ep.set("uri", uri);
uri.put("full", endpoint.getURI().toString());
uri.put("scheme", endpoint.getURI().getScheme());
uri.put("host", endpoint.getURI().getHost());
uri.put("port", endpoint.getURI().getPort());
ep.put("description", endpoint.getDescription());
endpoints.add(ep);
}
resp.setContentType("application/json");
resp.getOutputStream().write(String
.format("{ \"securedEndpointPort\":\"%s\", \"unsecuredEndpointPort\":\"%s\"}", coapsPort, coapPort)
.getBytes(StandardCharsets.UTF_8));
resp.getOutputStream().write(endpoints.toString().getBytes(StandardCharsets.UTF_8));
resp.setStatus(HttpServletResponse.SC_OK);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class CaliforniumClientEndpoint implements LwM2mClientEndpoint {
private final Logger LOG = LoggerFactory.getLogger(CaliforniumClientEndpoint.class);

private final Protocol protocol;
private final String description;
private final ScheduledExecutorService executor;
private final CoapEndpoint endpoint;
private final ClientEndpointToolbox toolbox;
Expand All @@ -57,11 +58,12 @@ public class CaliforniumClientEndpoint implements LwM2mClientEndpoint {
private final LwM2mModel model;
private final ExceptionTranslator exceptionTranslator;

public CaliforniumClientEndpoint(Protocol protocol, CoapEndpoint endpoint, ClientCoapMessageTranslator translator,
ClientEndpointToolbox toolbox, IdentityHandler identityHandler,
public CaliforniumClientEndpoint(Protocol protocol, String description, CoapEndpoint endpoint,
ClientCoapMessageTranslator translator, ClientEndpointToolbox toolbox, IdentityHandler identityHandler,
CaliforniumConnectionController connectionController, LwM2mModel model,
ExceptionTranslator exceptionTranslator, ScheduledExecutorService executor) {
this.protocol = protocol;
this.description = description;
this.translator = translator;
this.toolbox = toolbox;
this.endpoint = endpoint;
Expand All @@ -84,11 +86,15 @@ public URI getURI() {
getCoapEndpoint().getAddress().getPort(), null, null, null);
} catch (URISyntaxException e) {
// TODO TL : handle this properly
e.printStackTrace();
throw new IllegalStateException(e);
}
}

@Override
public String getDescription() {
return description;
}

@Override
public long getMaxCommunicationPeriodFor(long lifetimeInMs) {
// See https://github.com/OpenMobileAlliance/OMA_LwM2M_for_Developers/issues/283 to better understand.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public interface CaliforniumClientEndpointFactory {

Protocol getProtocol();

String getEndpointDescription();

CoapEndpoint createCoapEndpoint(InetAddress clientAddress, Configuration defaultConfiguration,
ServerInfo serverInfo, boolean clientInitiatedOnly, List<Certificate> trustStore,
ClientEndpointToolbox toolbox);
Expand All @@ -41,5 +43,4 @@ CoapEndpoint createCoapEndpoint(InetAddress clientAddress, Configuration default
IdentityHandler createIdentityHandler();

ExceptionTranslator createExceptionTranslator();

}
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,10 @@ public LwM2mServer createEndpoint(ServerInfo serverInfo, boolean clientInitiated
identityHandlerProvider.addIdentityHandler(coapEndpoint, identityHandler);

// create LWM2M endpoint
endpoint = new CaliforniumClientEndpoint(endpointFactory.getProtocol(), coapEndpoint,
messagetranslator, toolbox, identityHandler, endpointFactory.createConnectionController(),
objectTree.getModel(), endpointFactory.createExceptionTranslator(), executor);
endpoint = new CaliforniumClientEndpoint(endpointFactory.getProtocol(),
endpointFactory.getEndpointDescription(), coapEndpoint, messagetranslator, toolbox,
identityHandler, endpointFactory.createConnectionController(), objectTree.getModel(),
endpointFactory.createExceptionTranslator(), executor);

// add Californium endpoint to coap server
coapServer.addEndpoint(coapEndpoint);
Expand All @@ -194,8 +195,8 @@ public LwM2mServer createEndpoint(ServerInfo serverInfo, boolean clientInitiated
coapServer.start();
try {
coapEndpoint.start();
LOG.info("New endpoint created for server {} at {}", currentServer.getUri(),
coapEndpoint.getUri());
LOG.info("New {} created, \n for server {} at {}.", endpoint.getDescription(),
currentServer.getUri(), coapEndpoint.getUri());
} catch (IOException e) {
throw new RuntimeException("Unable to start endpoint", e);
}
Expand Down Expand Up @@ -261,7 +262,7 @@ public CoapServer getCoapServer() {

@Override
public LwM2mClientEndpoint getEndpoint(LwM2mServer server) {
if (currentServer.equals(server)) {
if (currentServer != null && currentServer.equals(server)) {
return endpoint;
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public Protocol getProtocol() {
return Protocol.COAP;
}

@Override
public String getEndpointDescription() {
return "CoAP over UDP endpoint based on Californium library";
}

protected String getLoggingTag(URI uri) {
if (loggingTagPrefix != null) {
return String.format("[%s-%s]", loggingTagPrefix, uri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ public class CoapOscoreClientEndpointFactory extends CoapClientEndpointFactory {

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

@Override
public String getEndpointDescription() {
return super.getEndpointDescription() + " with very experimental support of OSCORE";
}

/**
* This method is intended to be overridden.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ public CoapsClientEndpointFactory() {
this("LWM2M Client");
}

@Override
public String getEndpointDescription() {
return "CoAP over DTLS endpoint based on Californium/Scandium library";
}

public CoapsClientEndpointFactory(String loggingTagPrefix) {
this.loggingTagPrefix = loggingTagPrefix;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;

import org.eclipse.leshan.client.bootstrap.BootstrapConsistencyChecker;
import org.eclipse.leshan.client.bootstrap.DefaultBootstrapConsistencyChecker;
import org.eclipse.leshan.client.endpoint.DefaultCompositeClientEndpointsProvider;
import org.eclipse.leshan.client.endpoint.LwM2mClientEndpointsProvider;
import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory;
import org.eclipse.leshan.client.engine.RegistrationEngine;
Expand Down Expand Up @@ -266,10 +268,28 @@ public LeshanClientBuilder setSharedExecutor(ScheduledExecutorService executor)
}

/**
* @return the builder for fluent client creation.
* By default LeshanClient doesn't support any protocol. Users need to provide 1 or several
* {@link LwM2mClientEndpointsProvider} implementation.
* <p>
* Leshan project provides {@code coap} and {@code coaps} support based on Californium/Scandium in
* <strong>leshan-client-cf</strong>.
*/
public LeshanClientBuilder setEndpointsProviders(LwM2mClientEndpointsProvider... endpointsProvider) {
return setEndpointsProviders(Arrays.asList(endpointsProvider));
}

/**
* @see #setEndpointsProviders(LwM2mClientEndpointsProvider...)
*/
public LeshanClientBuilder setEndpointsProvider(LwM2mClientEndpointsProvider endpointsProvider) {
this.endpointsProvider = endpointsProvider;
public LeshanClientBuilder setEndpointsProviders(Collection<LwM2mClientEndpointsProvider> providers) {
if (providers == null || providers.isEmpty()) {
throw new IllegalStateException("At least one endpoint provider should be set");
}
if (providers.size() == 1) {
endpointsProvider = providers.iterator().next();
} else {
endpointsProvider = new DefaultCompositeClientEndpointsProvider(providers);
}
return this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2023 Sierra Wireless and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.leshan.client.endpoint;

import java.util.Collection;

/**
* A {@link LwM2mClientEndpointsProvider} composed of several internal {@link LwM2mClientEndpointsProvider}.
* <p>
* Implementation should allow to use several {@link LwM2mClientEndpointsProvider}.
*
* @see DefaultCompositeClientEndpointsProvider
*/
public interface CompositeClientEndpointsProvider extends LwM2mClientEndpointsProvider {
Collection<LwM2mClientEndpointsProvider> getProviders();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*******************************************************************************
* Copyright (c) 2023 Sierra Wireless and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.leshan.client.endpoint;

import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.eclipse.leshan.client.request.DownlinkRequestReceiver;
import org.eclipse.leshan.client.resource.LwM2mObjectTree;
import org.eclipse.leshan.client.servers.LwM2mServer;
import org.eclipse.leshan.client.servers.ServerInfo;

/**
* Default implementation of {@link CompositeClientEndpointsProvider}.
* <p>
* It allows to use several {@link LwM2mClientEndpointsProvider} on same Leshan server.
*/
public class DefaultCompositeClientEndpointsProvider implements CompositeClientEndpointsProvider {

private final List<LwM2mClientEndpointsProvider> providers;

public DefaultCompositeClientEndpointsProvider(LwM2mClientEndpointsProvider... providers) {
this(Arrays.asList(providers));
}

public DefaultCompositeClientEndpointsProvider(Collection<LwM2mClientEndpointsProvider> providers) {
this.providers = Collections.unmodifiableList(new ArrayList<>(providers));
}

@Override
public void init(LwM2mObjectTree objectTree, DownlinkRequestReceiver requestReceiver,
ClientEndpointToolbox toolbox) {
for (LwM2mClientEndpointsProvider provider : providers) {
provider.init(objectTree, requestReceiver, toolbox);
}
}

@Override
public LwM2mServer createEndpoint(ServerInfo serverInfo, boolean clientInitiatedOnly, List<Certificate> trustStore,
ClientEndpointToolbox toolbox) {
for (LwM2mClientEndpointsProvider provider : providers) {
LwM2mServer server = provider.createEndpoint(serverInfo, clientInitiatedOnly, trustStore, toolbox);
if (server != null) {
return server;
}
}
return null;
}

@Override
public Collection<LwM2mServer> createEndpoints(Collection<? extends ServerInfo> serverInfo,
boolean clientInitiatedOnly, List<Certificate> trustStore, ClientEndpointToolbox toolbox) {
// not implemented yet ...
return null;
}

@Override
public void destroyEndpoints() {
for (LwM2mClientEndpointsProvider provider : providers) {
provider.destroyEndpoints();
}
}

@Override
public void start() {
for (LwM2mClientEndpointsProvider provider : providers) {
provider.start();
}
}

@Override
public List<LwM2mClientEndpoint> getEndpoints() {
List<LwM2mClientEndpoint> endpoints = new ArrayList<>();
for (LwM2mClientEndpointsProvider provider : providers) {
endpoints.addAll(provider.getEndpoints());
}
return endpoints;
}

@Override
public LwM2mClientEndpoint getEndpoint(LwM2mServer server) {
for (LwM2mClientEndpointsProvider provider : providers) {
LwM2mClientEndpoint endpoint = provider.getEndpoint(server);
if (endpoint != null) {
return endpoint;
}
}
return null;
}

@Override
public void stop() {
for (LwM2mClientEndpointsProvider provider : providers) {
provider.stop();
}

}

@Override
public void destroy() {
for (LwM2mClientEndpointsProvider provider : providers) {
provider.destroy();
}
}

@Override
public Collection<LwM2mClientEndpointsProvider> getProviders() {
return providers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public interface LwM2mClientEndpoint {

URI getURI();

String getDescription();

void forceReconnection(LwM2mServer server, boolean resume);

long getMaxCommunicationPeriodFor(long lifetimeInMs);
Expand Down
Loading