diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/CaliforniumClientEndpointsProvider.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/CaliforniumClientEndpointsProvider.java index 2dac882fd4..1be948c179 100644 --- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/CaliforniumClientEndpointsProvider.java +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/CaliforniumClientEndpointsProvider.java @@ -261,7 +261,7 @@ public CoapServer getCoapServer() { @Override public LwM2mClientEndpoint getEndpoint(LwM2mServer server) { - if (currentServer.equals(server)) { + if (currentServer != null && currentServer.equals(server)) { return endpoint; } return null; diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/LeshanClientBuilder.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/LeshanClientBuilder.java index 7c01f5df6f..c3d49f78ef 100644 --- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/LeshanClientBuilder.java +++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/LeshanClientBuilder.java @@ -19,6 +19,7 @@ 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; @@ -26,6 +27,7 @@ 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; @@ -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. + *

+ * Leshan project provides {@code coap} and {@code coaps} support based on Californium/Scandium in + * leshan-client-cf. + */ + 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 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; } diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/endpoint/CompositeClientEndpointsProvider.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/endpoint/CompositeClientEndpointsProvider.java new file mode 100644 index 0000000000..dd9d1e742c --- /dev/null +++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/endpoint/CompositeClientEndpointsProvider.java @@ -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}. + *

+ * Implementation should allow to use several {@link LwM2mClientEndpointsProvider}. + * + * @see DefaultCompositeClientEndpointsProvider + */ +public interface CompositeClientEndpointsProvider extends LwM2mClientEndpointsProvider { + Collection getProviders(); +} diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/endpoint/DefaultCompositeClientEndpointsProvider.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/endpoint/DefaultCompositeClientEndpointsProvider.java new file mode 100644 index 0000000000..64e8192e12 --- /dev/null +++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/endpoint/DefaultCompositeClientEndpointsProvider.java @@ -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}. + *

+ * It allows to use several {@link LwM2mClientEndpointsProvider} on same Leshan server. + */ +public class DefaultCompositeClientEndpointsProvider implements CompositeClientEndpointsProvider { + + private final List providers; + + public DefaultCompositeClientEndpointsProvider(LwM2mClientEndpointsProvider... providers) { + this(Arrays.asList(providers)); + } + + public DefaultCompositeClientEndpointsProvider(Collection 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 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 createEndpoints(Collection serverInfo, + boolean clientInitiatedOnly, List 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 getEndpoints() { + List 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 getProviders() { + return providers; + } +} diff --git a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/LeshanClientDemo.java b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/LeshanClientDemo.java index bcef53caeb..03045c1a60 100644 --- a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/LeshanClientDemo.java +++ b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/LeshanClientDemo.java @@ -291,7 +291,7 @@ protected DtlsConnectorConfig.Builder createRootDtlsConnectorConfigBuilder( // Create client LeshanClientBuilder builder = new LeshanClientBuilder(cli.main.endpoint); builder.setObjects(enablers); - builder.setEndpointsProvider(endpointsBuilder.build()); + builder.setEndpointsProviders(endpointsBuilder.build()); builder.setDataSenders(new ManualDataSender()); if (cli.identity.isx509()) builder.setTrustStore(cli.identity.getX509().trustStore); diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/ServerOnlySecurityTest.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/ServerOnlySecurityTest.java index ad8d7926d3..8e64c8744b 100644 --- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/ServerOnlySecurityTest.java +++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/ServerOnlySecurityTest.java @@ -147,7 +147,7 @@ protected Builder createEffectiveDtlsConnectorConfigBuilder(InetSocketAddress ad }; CaliforniumClientEndpointsProvider endpointsProvider = new CaliforniumClientEndpointsProvider.Builder( coapsProtocolProvider).build(); - givenClient.setEndpointsProvider(endpointsProvider); + givenClient.setEndpointsProviders(endpointsProvider); } @AfterEach diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/util/LeshanTestClientBuilder.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/util/LeshanTestClientBuilder.java index aa04b0190b..1145ce3935 100644 --- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/util/LeshanTestClientBuilder.java +++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/util/LeshanTestClientBuilder.java @@ -248,17 +248,17 @@ public static LeshanTestClientBuilder givenClient() { } public LeshanTestClientBuilder with(LwM2mClientEndpointsProvider endpointsProvider) { - setEndpointsProvider(endpointsProvider); + setEndpointsProviders(endpointsProvider); return this; } public LeshanTestClientBuilder with(String endpointProvider) { if (endpointProvider.equals("Californium")) { - setEndpointsProvider( + setEndpointsProviders( new CaliforniumClientEndpointsProvider.Builder(getCaliforniumProtocolProvider(protocolToUse)) .build()); } else if (endpointProvider.equals("Californium-OSCORE")) { - setEndpointsProvider(new CaliforniumClientEndpointsProvider.Builder( + setEndpointsProviders(new CaliforniumClientEndpointsProvider.Builder( getCaliforniumProtocolProviderSupportingOscore(protocolToUse)).build()); } return this;