diff --git a/leshan-client-cf/pom.xml b/leshan-client-cf/pom.xml index dff23b746b..f768984e44 100644 --- a/leshan-client-cf/pom.xml +++ b/leshan-client-cf/pom.xml @@ -47,6 +47,10 @@ Contributors: org.eclipse.californium scandium + + org.eclipse.californium + element-connector-tcp-netty + org.eclipse.californium cf-oscore diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpClientEndpointFactory.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpClientEndpointFactory.java new file mode 100644 index 0000000000..bb4898213a --- /dev/null +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpClientEndpointFactory.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2022 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.californium.endpoint.coaptcp; + +import java.net.InetSocketAddress; +import java.security.cert.Certificate; +import java.util.List; + +import org.eclipse.californium.core.network.CoapEndpoint; +import org.eclipse.californium.core.network.CoapEndpoint.Builder; +import org.eclipse.californium.core.network.Endpoint; +import org.eclipse.californium.elements.Connector; +import org.eclipse.californium.elements.EndpointContextMatcher; +import org.eclipse.californium.elements.TcpEndpointContextMatcher; +import org.eclipse.californium.elements.UDPConnector; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.californium.elements.tcp.netty.TcpClientConnector; +import org.eclipse.leshan.client.californium.CaliforniumConnectionController; +import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpointFactory; +import org.eclipse.leshan.client.endpoint.ClientEndpointToolbox; +import org.eclipse.leshan.client.servers.ServerIdentity; +import org.eclipse.leshan.client.servers.ServerInfo; +import org.eclipse.leshan.core.californium.DefaultExceptionTranslator; +import org.eclipse.leshan.core.californium.ExceptionTranslator; +import org.eclipse.leshan.core.californium.identity.DefaultCoapIdentityHandler; +import org.eclipse.leshan.core.californium.identity.IdentityHandler; +import org.eclipse.leshan.core.endpoint.Protocol; + +public class CoapTcpClientEndpointFactory implements CaliforniumClientEndpointFactory { + + private final String loggingTag = null; + protected EndpointContextMatcher unsecuredContextMatcher = new TcpEndpointContextMatcher(); + protected InetSocketAddress addr = null; + + public CoapTcpClientEndpointFactory(InetSocketAddress addr) { + this.addr = addr; + } + + @Override + public Protocol getProtocol() { + return Protocol.COAP_TCP; + } + + @Override + public Endpoint createEndpoint(Configuration defaultConfiguration, ServerInfo serverInfo, + boolean clientInitiatedOnly, List trustStore, ClientEndpointToolbox toolbox) { + return createUnsecuredEndpointBuilder(addr, serverInfo, defaultConfiguration).build(); + } + + /** + * This method is intended to be overridden. + * + * @param address the IP address and port, if null the connector is bound to an ephemeral port on the wildcard + * address. + * @param coapConfig the CoAP config used to create this endpoint. + * @return the {@link Builder} used for unsecured communication. + */ + protected CoapEndpoint.Builder createUnsecuredEndpointBuilder(InetSocketAddress address, ServerInfo serverInfo, + Configuration coapConfig) { + CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); + builder.setConnector(createUnsecuredConnector(address, coapConfig)); + builder.setConfiguration(coapConfig); + if (loggingTag != null) { + builder.setLoggingTag("[" + loggingTag + "-coap://]"); + } else { + builder.setLoggingTag("[coap://]"); + } + if (unsecuredContextMatcher != null) { + builder.setEndpointContextMatcher(unsecuredContextMatcher); + } + return builder; + } + + /** + * By default create an {@link UDPConnector}. + *

+ * This method is intended to be overridden. + * + * @param address the IP address and port, if null the connector is bound to an ephemeral port on the wildcard + * address + * @param coapConfig the Configuration + * @return the {@link Connector} used for unsecured {@link CoapEndpoint} + */ + protected Connector createUnsecuredConnector(InetSocketAddress address, Configuration coapConfig) { + return new TcpClientConnector(coapConfig); + } + + @Override + public IdentityHandler createIdentityHandler() { + // TODO TCP : maybe we need a more specific one + return new DefaultCoapIdentityHandler(); + } + + @Override + public ExceptionTranslator createExceptionTranslator() { + // TODO TCP : maybe we need a more specific one + return new DefaultExceptionTranslator(); + } + + @Override + public CaliforniumConnectionController createConnectionController() { + return new CaliforniumConnectionController() { + @Override + public void forceReconnection(Endpoint endpoint, ServerIdentity identity, boolean resume) { + // no connection in coap, so nothing to do; + } + }; + } +} diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpClientProtocolProvider.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpClientProtocolProvider.java new file mode 100644 index 0000000000..1eb00bdf68 --- /dev/null +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpClientProtocolProvider.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2022 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.californium.endpoint.coaptcp; + +import java.net.InetSocketAddress; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.californium.core.config.CoapConfig; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.californium.elements.config.Configuration.ModuleDefinitionsProvider; +import org.eclipse.californium.elements.config.SystemConfig; +import org.eclipse.californium.elements.config.TcpConfig; +import org.eclipse.californium.elements.config.UdpConfig; +import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpointFactory; +import org.eclipse.leshan.client.californium.endpoint.ClientProtocolProvider; +import org.eclipse.leshan.core.endpoint.Protocol; + +public class CoapTcpClientProtocolProvider implements ClientProtocolProvider { + + @Override + public Protocol getProtocol() { + return Protocol.COAP_TCP; + } + + @Override + public void applyDefaultValue(Configuration configuration) { + configuration.set(CoapConfig.MAX_ACTIVE_PEERS, 10); + configuration.set(CoapConfig.PROTOCOL_STAGE_THREAD_COUNT, 1); + } + + @Override + public List getModuleDefinitionsProviders() { + return Arrays.asList(SystemConfig.DEFINITIONS, CoapConfig.DEFINITIONS, UdpConfig.DEFINITIONS, + TcpConfig.DEFINITIONS); + } + + @Override + public CaliforniumClientEndpointFactory createDefaultEndpointFactory(InetSocketAddress address) { + return new CoapTcpClientEndpointFactory(address); + } +} 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 c9c1cdc8fe..69dee33eff 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 @@ -48,6 +48,7 @@ import org.eclipse.leshan.client.californium.endpoint.coap.CoapOscoreProtocolProvider; import org.eclipse.leshan.client.californium.endpoint.coaps.CoapsClientEndpointFactory; import org.eclipse.leshan.client.californium.endpoint.coaps.CoapsClientProtocolProvider; +import org.eclipse.leshan.client.californium.endpoint.coaptcp.CoapTcpClientProtocolProvider; import org.eclipse.leshan.client.demo.cli.LeshanClientDemoCLI; import org.eclipse.leshan.client.demo.cli.interactive.InteractiveCommands; import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory; @@ -254,7 +255,7 @@ protected DtlsConnectorConfig.Builder createDtlsConfigBuilder(Configuration conf }; CaliforniumClientEndpointsProvider.Builder endpointsBuilder = new CaliforniumClientEndpointsProvider.Builder( - new CoapOscoreProtocolProvider(), customCoapsProtocolProvider); + new CoapOscoreProtocolProvider(), customCoapsProtocolProvider, new CoapTcpClientProtocolProvider()); // Create Californium Configuration Configuration clientCoapConfig = endpointsBuilder.createDefaultConfiguration(); diff --git a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/cli/LeshanClientDemoCLI.java b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/cli/LeshanClientDemoCLI.java index db9c2bb8c8..82232acef8 100644 --- a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/cli/LeshanClientDemoCLI.java +++ b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/cli/LeshanClientDemoCLI.java @@ -305,7 +305,7 @@ public void run() { int indexOf = main.url.indexOf("://"); String scheme = main.url.substring(0, indexOf); // we support only coap and coaps - if (!"coap".equals(scheme) && !"coaps".equals(scheme)) { + if (!"coap".equals(scheme) && !"coaps".equals(scheme) && !"coap+tcp".equals(scheme)) { throw new MultiParameterException(spec.commandLine(), String.format("Invalid URL %s : unknown scheme '%s', we support only 'coap' or 'coaps' for now", main.url, scheme), @@ -319,7 +319,7 @@ public void run() { main.url, scheme), "-u"); } } else { - if (!scheme.equals("coap")) { + if (!scheme.equals("coap") && !scheme.equals("coap+tcp")) { throw new MultiParameterException(spec.commandLine(), String.format( "Invalid URL %s : '%s' scheme must be used with PSK, RPK or x509 option. Do you mean 'coap' ? ", main.url, scheme), "-u"); diff --git a/leshan-server-cf/pom.xml b/leshan-server-cf/pom.xml index 4f6ff8ba04..a0a060b414 100644 --- a/leshan-server-cf/pom.xml +++ b/leshan-server-cf/pom.xml @@ -47,6 +47,10 @@ Contributors: org.eclipse.californium scandium + + org.eclipse.californium + element-connector-tcp-netty + diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpServerEndpointFactory.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpServerEndpointFactory.java new file mode 100644 index 0000000000..d40108f1ee --- /dev/null +++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpServerEndpointFactory.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2022 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.server.californium.endpoint.coaptcp; + +import java.net.InetSocketAddress; +import java.net.URI; + +import org.eclipse.californium.core.network.CoapEndpoint; +import org.eclipse.californium.core.network.CoapEndpoint.Builder; +import org.eclipse.californium.core.network.serialization.TcpDataParser; +import org.eclipse.californium.core.network.serialization.TcpDataSerializer; +import org.eclipse.californium.elements.Connector; +import org.eclipse.californium.elements.EndpointContextMatcher; +import org.eclipse.californium.elements.TcpEndpointContextMatcher; +import org.eclipse.californium.elements.UDPConnector; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.californium.elements.tcp.netty.TcpServerConnector; +import org.eclipse.leshan.core.californium.DefaultExceptionTranslator; +import org.eclipse.leshan.core.californium.ExceptionTranslator; +import org.eclipse.leshan.core.californium.identity.DefaultCoapIdentityHandler; +import org.eclipse.leshan.core.californium.identity.IdentityHandler; +import org.eclipse.leshan.core.endpoint.EndpointUriUtil; +import org.eclipse.leshan.core.endpoint.Protocol; +import org.eclipse.leshan.server.LeshanServer; +import org.eclipse.leshan.server.californium.endpoint.CaliforniumServerEndpointFactory; +import org.eclipse.leshan.server.californium.observation.LwM2mObservationStore; +import org.eclipse.leshan.server.californium.observation.ObservationSerDes; +import org.eclipse.leshan.server.observation.LwM2mNotificationReceiver; +import org.eclipse.leshan.server.security.ServerSecurityInfo; + +public class CoapTcpServerEndpointFactory implements CaliforniumServerEndpointFactory { + + private final String loggingTag = null; + protected EndpointContextMatcher unsecuredContextMatcher = new TcpEndpointContextMatcher(); + protected URI endpointUri = null; + + public CoapTcpServerEndpointFactory(URI uri) { + this.endpointUri = uri; + } + + @Override + public Protocol getProtocol() { + return Protocol.COAP_TCP; + } + + @Override + public URI getUri() { + return endpointUri; + } + + @Override + public CoapEndpoint createCoapEndpoint(Configuration defaultCaliforniumConfiguration, + ServerSecurityInfo serverSecurityInfo, LwM2mNotificationReceiver notificationReceiver, + LeshanServer server) { + return createUnsecuredEndpointBuilder(EndpointUriUtil.getSocketAddr(endpointUri), + defaultCaliforniumConfiguration, server, notificationReceiver).build(); + } + + /** + * This method is intended to be overridden. + * + * @param address the IP address and port, if null the connector is bound to an ephemeral port on the wildcard + * address. + * @param coapConfig the CoAP config used to create this endpoint. + * @return the {@link Builder} used for unsecured communication. + */ + protected CoapEndpoint.Builder createUnsecuredEndpointBuilder(InetSocketAddress address, Configuration coapConfig, + LeshanServer server, LwM2mNotificationReceiver notificationReceiver) { + CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); + builder.setConnector(createUnsecuredConnector(address, coapConfig)); + builder.setConfiguration(coapConfig); + if (loggingTag != null) { + builder.setLoggingTag("[" + loggingTag + "-coap://]"); + } else { + builder.setLoggingTag("[coap://]"); + } + if (unsecuredContextMatcher != null) { + builder.setEndpointContextMatcher(unsecuredContextMatcher); + } + builder.setObservationStore(new LwM2mObservationStore(server.getRegistrationStore(), notificationReceiver, + new ObservationSerDes(new TcpDataParser(), new TcpDataSerializer()))); + return builder; + } + + /** + * By default create an {@link UDPConnector}. + *

+ * This method is intended to be overridden. + * + * @param address the IP address and port, if null the connector is bound to an ephemeral port on the wildcard + * address + * @param coapConfig the Configuration + * @return the {@link Connector} used for unsecured {@link CoapEndpoint} + */ + protected Connector createUnsecuredConnector(InetSocketAddress address, Configuration coapConfig) { + return new TcpServerConnector(address, coapConfig); + } + + @Override + public IdentityHandler createIdentityHandler() { + // TODO TCP : maybe we need a more specific one + return new DefaultCoapIdentityHandler(); + } + + @Override + public ExceptionTranslator createExceptionTranslator() { + // TODO TCP : maybe we need a more specific one + return new DefaultExceptionTranslator(); + } +} diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpServerProtocolProvider.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpServerProtocolProvider.java new file mode 100644 index 0000000000..3c83b5c4f1 --- /dev/null +++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpServerProtocolProvider.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2022 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.server.californium.endpoint.coaptcp; + +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.californium.core.config.CoapConfig; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.californium.elements.config.Configuration.ModuleDefinitionsProvider; +import org.eclipse.californium.elements.config.SystemConfig; +import org.eclipse.californium.elements.config.TcpConfig; +import org.eclipse.californium.elements.config.UdpConfig; +import org.eclipse.leshan.core.endpoint.EndpointUriUtil; +import org.eclipse.leshan.core.endpoint.Protocol; +import org.eclipse.leshan.server.californium.endpoint.CaliforniumServerEndpointFactory; +import org.eclipse.leshan.server.californium.endpoint.ServerProtocolProvider; + +public class CoapTcpServerProtocolProvider implements ServerProtocolProvider { + + @Override + public Protocol getProtocol() { + return Protocol.COAP_TCP; + } + + @Override + public void applyDefaultValue(Configuration configuration) { + } + + @Override + public List getModuleDefinitionsProviders() { + return Arrays.asList(SystemConfig.DEFINITIONS, CoapConfig.DEFINITIONS, UdpConfig.DEFINITIONS, + TcpConfig.DEFINITIONS); + } + + @Override + public CaliforniumServerEndpointFactory createDefaultEndpointFactory(URI uri) { + return new CoapTcpServerEndpointFactory(uri); + } + + @Override + public URI getDefaultUri(Configuration configuration) { + return EndpointUriUtil.createUri(getProtocol().getUriScheme(), + new InetSocketAddress(configuration.get(CoapConfig.COAP_PORT))); + } +} diff --git a/leshan-server-demo/src/main/java/org/eclipse/leshan/server/demo/LeshanServerDemo.java b/leshan-server-demo/src/main/java/org/eclipse/leshan/server/demo/LeshanServerDemo.java index c5095599b2..a27160df64 100644 --- a/leshan-server-demo/src/main/java/org/eclipse/leshan/server/demo/LeshanServerDemo.java +++ b/leshan-server-demo/src/main/java/org/eclipse/leshan/server/demo/LeshanServerDemo.java @@ -48,6 +48,7 @@ import org.eclipse.leshan.server.californium.endpoint.coap.CoapOscoreServerEndpointFactory; import org.eclipse.leshan.server.californium.endpoint.coap.CoapServerProtocolProvider; import org.eclipse.leshan.server.californium.endpoint.coaps.CoapsServerProtocolProvider; +import org.eclipse.leshan.server.californium.endpoint.coaptcp.CoapTcpServerProtocolProvider; import org.eclipse.leshan.server.core.demo.json.servlet.SecurityServlet; import org.eclipse.leshan.server.demo.cli.LeshanServerDemoCLI; import org.eclipse.leshan.server.demo.servlet.ClientServlet; @@ -178,7 +179,7 @@ public static LeshanServer createLeshanServer(LeshanServerDemoCLI cli) throws Ex // Create Californium Endpoints Provider: // ------------------ CaliforniumServerEndpointsProvider.Builder endpointsBuilder = new CaliforniumServerEndpointsProvider.Builder( - new CoapServerProtocolProvider(), new CoapsServerProtocolProvider()); + new CoapServerProtocolProvider(), new CoapsServerProtocolProvider(), new CoapTcpServerProtocolProvider()); // Create Californium Configuration Configuration serverCoapConfig = endpointsBuilder.createDefaultConfiguration(); @@ -238,6 +239,10 @@ public static LeshanServer createLeshanServer(LeshanServerDemoCLI cli) throws Ex : new InetSocketAddress(cli.main.secureLocalAddress, coapsPort); endpointsBuilder.addEndpoint(coapsAddr, Protocol.COAPS); + // Create CoAP over TCP endpoint + // TODO TCP : add command line for this endpoint + endpointsBuilder.addEndpoint(new InetSocketAddress(5683), Protocol.COAP_TCP); + // Create LWM2M server builder.setEndpointsProvider(endpointsBuilder.build()); return builder.build(); diff --git a/pom.xml b/pom.xml index d7deab321f..1aec1ddc4a 100644 --- a/pom.xml +++ b/pom.xml @@ -199,6 +199,11 @@ Contributors: scandium ${californium.version} + + org.eclipse.californium + element-connector-tcp-netty + ${californium.version} + com.fasterxml.jackson.core jackson-databind