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/CoapTcpEndpointFactory.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpEndpointFactory.java new file mode 100644 index 0000000000..8415636c38 --- /dev/null +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpEndpointFactory.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.core.server.resources.CoapExchange; +import org.eclipse.californium.elements.Connector; +import org.eclipse.californium.elements.EndpointContext; +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.CaliforniumIdentityExtractor; +import org.eclipse.leshan.client.californium.enpoint.CaliforniumEndpointFactory; +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.endpoint.Protocol; +import org.eclipse.leshan.core.request.Identity; + +public class CoapTcpEndpointFactory implements CaliforniumEndpointFactory { + + private final String loggingTag = null; + protected EndpointContextMatcher unsecuredContextMatcher = new TcpEndpointContextMatcher(); + protected InetSocketAddress addr = null; + + public CoapTcpEndpointFactory(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 CaliforniumIdentityExtractor createIdentityExtractor() { + return new CaliforniumIdentityExtractor() { + @Override + public Identity getIdentity(CoapExchange exchange) { + EndpointContext context = getForeignPeerContext(exchange); + InetSocketAddress peerAddress = context.getPeerAddress(); + return Identity.unsecure(peerAddress); + } + }; + } + + @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/CoapTcpProtocolProvider.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpProtocolProvider.java new file mode 100644 index 0000000000..028188dbcd --- /dev/null +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/endpoint/coaptcp/CoapTcpProtocolProvider.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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.core.config.CoapConfig.TrackerMode; +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.enpoint.CaliforniumEndpointFactory; +import org.eclipse.leshan.client.californium.enpoint.CaliforniumProtocolProvider; +import org.eclipse.leshan.core.endpoint.Protocol; + +public class CoapTcpProtocolProvider implements CaliforniumProtocolProvider { + + @Override + public Protocol getProtocol() { + return Protocol.COAP_TCP; + } + + @Override + public void applyDefaultValue(Configuration configuration) { + configuration.set(CoapConfig.MID_TRACKER, TrackerMode.NULL); + 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 CaliforniumEndpointFactory createDefaultEndpointFactory(InetSocketAddress address) { + return new CoapTcpEndpointFactory(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 898ab6e791..567ffa3320 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 @@ -46,6 +46,7 @@ import org.eclipse.leshan.client.californium.endpoint.coap.CoapProtocolProvider; import org.eclipse.leshan.client.californium.endpoint.coaps.CoapsEndpointFactory; import org.eclipse.leshan.client.californium.endpoint.coaps.CoapsProtocolProvider; +import org.eclipse.leshan.client.californium.endpoint.coaptcp.CoapTcpProtocolProvider; import org.eclipse.leshan.client.californium.enpoint.CaliforniumEndpointFactory; import org.eclipse.leshan.client.californium.enpoint.CaliforniumEndpointsProvider; import org.eclipse.leshan.client.demo.cli.LeshanClientDemoCLI; @@ -254,7 +255,7 @@ protected DtlsConnectorConfig.Builder createDtlsConfigBuilder(Configuration conf }; CaliforniumEndpointsProvider.Builder endpointsBuilder = new CaliforniumEndpointsProvider.Builder( - new CoapProtocolProvider(), customCoapsProtocolProvider); + new CoapProtocolProvider(), customCoapsProtocolProvider, new CoapTcpProtocolProvider()); // Create Californium Configuration Configuration clientCoapConfig = endpointsBuilder.createDefaultCoapServerConfiguration(); 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/CoapTcpEndpointFactory.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpEndpointFactory.java new file mode 100644 index 0000000000..3368bfcb52 --- /dev/null +++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpEndpointFactory.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * 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.Endpoint; +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.endpoint.EndpointUriUtil; +import org.eclipse.leshan.core.endpoint.Protocol; +import org.eclipse.leshan.server.californium.endpoint.CaliforniumEndpointFactory; +import org.eclipse.leshan.server.californium.observation.LwM2mObservationStore; +import org.eclipse.leshan.server.californium.observation.ObservationSerDes; +import org.eclipse.leshan.server.endpoint.LwM2mNotificationReceiver; +import org.eclipse.leshan.server.endpoint.LwM2mServer; +import org.eclipse.leshan.server.endpoint.ServerSecurityInfo; + +public class CoapTcpEndpointFactory implements CaliforniumEndpointFactory { + + private final String loggingTag = null; + protected EndpointContextMatcher unsecuredContextMatcher = new TcpEndpointContextMatcher(); + protected URI endpointUri = null; + + public CoapTcpEndpointFactory(URI uri) { + this.endpointUri = uri; + } + + @Override + public Protocol getProtocol() { + return Protocol.COAP_TCP; + } + + @Override + public URI getUri() { + return endpointUri; + } + + @Override + public Endpoint createEndpoint(Configuration defaultConfiguration, ServerSecurityInfo serverSecurityInfo, + LwM2mServer server, LwM2mNotificationReceiver notificationReceiver) { + return createUnsecuredEndpointBuilder(EndpointUriUtil.getSocketAddr(endpointUri), defaultConfiguration, 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, + LwM2mServer 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); + } +} diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpProtocolProvider.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpProtocolProvider.java new file mode 100644 index 0000000000..a612449119 --- /dev/null +++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/endpoint/coaptcp/CoapTcpProtocolProvider.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * 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.core.config.CoapConfig.TrackerMode; +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.CaliforniumEndpointFactory; +import org.eclipse.leshan.server.californium.endpoint.CaliforniumProtocolProvider; + +public class CoapTcpProtocolProvider implements CaliforniumProtocolProvider { + + @Override + public Protocol getProtocol() { + return Protocol.COAP_TCP; + } + + @Override + public void applyDefaultValue(Configuration configuration) { + configuration.set(CoapConfig.MID_TRACKER, TrackerMode.NULL); + } + + @Override + public List getModuleDefinitionsProviders() { + return Arrays.asList(SystemConfig.DEFINITIONS, CoapConfig.DEFINITIONS, UdpConfig.DEFINITIONS, + TcpConfig.DEFINITIONS); + } + + @Override + public CaliforniumEndpointFactory createDefaultEndpointFactory(URI uri) { + return new CoapTcpEndpointFactory(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 d64c19c054..9ce3678e2b 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.CoapProtocolProvider; import org.eclipse.leshan.server.californium.endpoint.coap.OscoreCoapEndpointFactory; import org.eclipse.leshan.server.californium.endpoint.coaps.CoapsProtocolProvider; +import org.eclipse.leshan.server.californium.endpoint.coaptcp.CoapTcpProtocolProvider; 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: // ------------------ CaliforniumEndpointsProvider.Builder endpointsBuilder = new CaliforniumEndpointsProvider.Builder( - new CoapProtocolProvider(), new CoapsProtocolProvider()); + new CoapProtocolProvider(), new CoapsProtocolProvider(), new CoapTcpProtocolProvider()); // Create Californium Configuration Configuration serverCoapConfig = endpointsBuilder.createDefaultCoapServerConfiguration(); @@ -238,6 +239,9 @@ public static LeshanServer createLeshanServer(LeshanServerDemoCLI cli) throws Ex : new InetSocketAddress(cli.main.secureLocalAddress, coapsPort); endpointsBuilder.addEndpoint(coapsAddr, Protocol.COAPS); + // Create CoAP over TCP endpoint + endpointsBuilder.addEndpoint(new InetSocketAddress("127.0.0.1", 5683), Protocol.COAP_TCP); + // Create LWM2M server builder.setEndpointProvider(endpointsBuilder.build()); return builder.build(); diff --git a/pom.xml b/pom.xml index 42f775240e..0fad1964c7 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