Skip to content

Commit

Permalink
More work about adding coap layer for server using java-coap
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Jan 11, 2023
1 parent d66bfde commit 5b0b66f
Show file tree
Hide file tree
Showing 10 changed files with 1,176 additions and 140 deletions.
5 changes: 5 additions & 0 deletions leshan-server-demo/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ Contributors:
<groupId>org.eclipse.leshan</groupId>
<artifactId>leshan-core-demo</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.leshan</groupId>
<artifactId>leshan-tl-javacoap-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.leshan</groupId>
<artifactId>leshan-server-core-demo</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,30 @@
*******************************************************************************/
package org.eclipse.leshan.server.demo;

import java.io.File;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.List;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;

import org.eclipse.californium.core.config.CoapConfig;
import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.californium.elements.util.CertPathUtil;
import org.eclipse.californium.scandium.config.DtlsConfig;
import org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.leshan.core.californium.PrincipalMdcConnectionListener;
import org.eclipse.leshan.core.demo.LwM2mDemoConstant;
import org.eclipse.leshan.core.demo.cli.ShortErrorMessageHandler;
import org.eclipse.leshan.core.endpoint.EndpointUriUtil;
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.core.model.ObjectLoader;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.server.LeshanServer;
import org.eclipse.leshan.server.LeshanServerBuilder;
import org.eclipse.leshan.server.californium.endpoint.CaliforniumServerEndpointFactory;
import org.eclipse.leshan.server.californium.endpoint.CaliforniumServerEndpointsProvider;
import org.eclipse.leshan.server.californium.endpoint.ServerProtocolProvider;
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.CoapsServerEndpointFactory;
import org.eclipse.leshan.server.californium.endpoint.coaps.CoapsServerProtocolProvider;
import org.eclipse.leshan.server.core.demo.json.servlet.SecurityServlet;
Expand All @@ -66,6 +55,7 @@
import org.eclipse.leshan.server.redis.RedisSecurityStore;
import org.eclipse.leshan.server.security.EditableSecurityStore;
import org.eclipse.leshan.server.security.FileSecurityStore;
import org.eclipse.leshan.transport.javacoap.endpoint.JavaCoapServerEndpointsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -204,69 +194,72 @@ protected Builder createDtlsConnectorConfigBuilder(Configuration endpointConfigu
};

// Create Server Endpoints Provider
CaliforniumServerEndpointsProvider.Builder endpointsBuilder = new CaliforniumServerEndpointsProvider.Builder(
new CoapServerProtocolProvider(), coapsProtocolProvider);

// Create Californium Configuration
Configuration serverCoapConfig = endpointsBuilder.createDefaultConfiguration();

// Set some DTLS stuff
// These configuration values are always overwritten by CLI therefore set them to transient.
serverCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY);
serverCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !cli.dtls.supportDeprecatedCiphers);
serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH);
if (cli.dtls.cid != null) {
serverCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, cli.dtls.cid);
}

// Persist configuration
File configFile = new File(CF_CONFIGURATION_FILENAME);
if (configFile.isFile()) {
serverCoapConfig.load(configFile);
} else {
serverCoapConfig.store(configFile, CF_CONFIGURATION_HEADER);
}

// Enforce DTLS role to ServerOnly if needed
if (cli.identity.isx509()) {
X509Certificate serverCertificate = cli.identity.getCertChain()[0];
if (serverCoapConfig.get(DtlsConfig.DTLS_ROLE) == DtlsRole.BOTH) {
if (serverCertificate != null) {
if (CertPathUtil.canBeUsedForAuthentication(serverCertificate, false)) {
if (!CertPathUtil.canBeUsedForAuthentication(serverCertificate, true)) {
serverCoapConfig.set(DtlsConfig.DTLS_ROLE, DtlsRole.SERVER_ONLY);
LOG.warn("Server certificate does not allow Client Authentication usage."
+ "\nThis will prevent this LWM2M server to initiate DTLS connection."
+ "\nSee : https://github.com/eclipse/leshan/wiki/Server-Failover#about-connections");
}
}
}
}
}

// Set Californium Configuration
endpointsBuilder.setConfiguration(serverCoapConfig);

// Create CoAP endpoint
int coapPort = cli.main.localPort == null ? serverCoapConfig.get(CoapConfig.COAP_PORT) : cli.main.localPort;
InetSocketAddress coapAddr = cli.main.localAddress == null ? new InetSocketAddress(coapPort)
: new InetSocketAddress(cli.main.localAddress, coapPort);
if (cli.main.disableOscore) {
endpointsBuilder.addEndpoint(coapAddr, Protocol.COAP);
} else {
endpointsBuilder.addEndpoint(new CoapOscoreServerEndpointFactory(
EndpointUriUtil.createUri(Protocol.COAP.getUriScheme(), coapAddr)));
}

// Create CoAP over DTLS endpoint
int coapsPort = cli.main.secureLocalPort == null ? serverCoapConfig.get(CoapConfig.COAP_SECURE_PORT)
: cli.main.secureLocalPort;
InetSocketAddress coapsAddr = cli.main.secureLocalAddress == null ? new InetSocketAddress(coapsPort)
: new InetSocketAddress(cli.main.secureLocalAddress, coapsPort);
endpointsBuilder.addEndpoint(coapsAddr, Protocol.COAPS);
// CaliforniumServerEndpointsProvider.Builder endpointsBuilder = new CaliforniumServerEndpointsProvider.Builder(
// new CoapServerProtocolProvider(), coapsProtocolProvider);
//
// // Create Californium Configuration
// Configuration serverCoapConfig = endpointsBuilder.createDefaultConfiguration();
//
// // Set some DTLS stuff
// // These configuration values are always overwritten by CLI therefore set them to transient.
// serverCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY);
// serverCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !cli.dtls.supportDeprecatedCiphers);
// serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH);
// if (cli.dtls.cid != null) {
// serverCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, cli.dtls.cid);
// }
//
// // Persist configuration
// File configFile = new File(CF_CONFIGURATION_FILENAME);
// if (configFile.isFile()) {
// serverCoapConfig.load(configFile);
// } else {
// serverCoapConfig.store(configFile, CF_CONFIGURATION_HEADER);
// }
//
// // Enforce DTLS role to ServerOnly if needed
// if (cli.identity.isx509()) {
// X509Certificate serverCertificate = cli.identity.getCertChain()[0];
// if (serverCoapConfig.get(DtlsConfig.DTLS_ROLE) == DtlsRole.BOTH) {
// if (serverCertificate != null) {
// if (CertPathUtil.canBeUsedForAuthentication(serverCertificate, false)) {
// if (!CertPathUtil.canBeUsedForAuthentication(serverCertificate, true)) {
// serverCoapConfig.set(DtlsConfig.DTLS_ROLE, DtlsRole.SERVER_ONLY);
// LOG.warn("Server certificate does not allow Client Authentication usage."
// + "\nThis will prevent this LWM2M server to initiate DTLS connection."
// + "\nSee : https://github.com/eclipse/leshan/wiki/Server-Failover#about-connections");
// }
// }
// }
// }
// }
//
// // Set Californium Configuration
// endpointsBuilder.setConfiguration(serverCoapConfig);
//
// // Create CoAP endpoint
// int coapPort = cli.main.localPort == null ? serverCoapConfig.get(CoapConfig.COAP_PORT) : cli.main.localPort;
// InetSocketAddress coapAddr = cli.main.localAddress == null ? new InetSocketAddress(coapPort)
// : new InetSocketAddress(cli.main.localAddress, coapPort);
// if (cli.main.disableOscore) {
// endpointsBuilder.addEndpoint(coapAddr, Protocol.COAP);
// } else {
// endpointsBuilder.addEndpoint(new CoapOscoreServerEndpointFactory(
// EndpointUriUtil.createUri(Protocol.COAP.getUriScheme(), coapAddr)));
// }
//
// // Create CoAP over DTLS endpoint
// int coapsPort = cli.main.secureLocalPort == null ? serverCoapConfig.get(CoapConfig.COAP_SECURE_PORT)
// : cli.main.secureLocalPort;
// InetSocketAddress coapsAddr = cli.main.secureLocalAddress == null ? new InetSocketAddress(coapsPort)
// : new InetSocketAddress(cli.main.secureLocalAddress, coapsPort);
// endpointsBuilder.addEndpoint(coapsAddr, Protocol.COAPS);

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

JavaCoapServerEndpointsProvider endpointsProvider = new JavaCoapServerEndpointsProvider(cli.main.localPort);
builder.setEndpointsProvider(endpointsProvider);
return builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,35 @@
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.core.observation.Observation;
import org.eclipse.leshan.core.request.DownlinkRequest;
import org.eclipse.leshan.core.request.exception.SendFailedException;
import org.eclipse.leshan.core.response.ErrorCallback;
import org.eclipse.leshan.core.response.LwM2mResponse;
import org.eclipse.leshan.core.response.ResponseCallback;
import org.eclipse.leshan.server.endpoint.LwM2mServerEndpoint;
import org.eclipse.leshan.server.endpoint.ServerEndpointToolbox;
import org.eclipse.leshan.server.profile.ClientProfile;
import org.eclipse.leshan.server.request.LowerLayerConfig;

import com.mbed.coap.client.CoapClient;
import com.mbed.coap.client.CoapClientBuilder;
import com.mbed.coap.exception.CoapException;
import com.mbed.coap.packet.CoapRequest;
import com.mbed.coap.packet.CoapResponse;
import com.mbed.coap.server.CoapServer;

public class JavaCoapServerEndpoint implements LwM2mServerEndpoint {

private final URI endpointUri;
private final CoapServer coapServer;
private final ServerCoapMessageTranslator translator;
private final ServerEndpointToolbox toolbox;

public JavaCoapServerEndpoint(URI endpointUri, CoapServer coapServer) {
public JavaCoapServerEndpoint(URI endpointUri, CoapServer coapServer, ServerCoapMessageTranslator translator,
ServerEndpointToolbox toolbox) {
this.endpointUri = endpointUri;
this.coapServer = coapServer;
this.translator = translator;
this.toolbox = toolbox;
}

@Override
Expand All @@ -53,6 +65,21 @@ public URI getURI() {
public <T extends LwM2mResponse> T send(ClientProfile destination, DownlinkRequest<T> request,
LowerLayerConfig lowerLayerConfig, long timeoutInMs) throws InterruptedException {

final CoapRequest coapRequest = translator.createCoapRequest(destination, request, toolbox);

// create a Coap Client to send request
CoapClient coapClient = CoapClientBuilder.clientFor(destination.getIdentity().getPeerAddress(), coapServer);

// Send CoAP request synchronously
CoapResponse coapResponse = null;
try {
coapResponse = coapClient.sendSync(coapRequest);
} catch (CoapException e) {
throw new IllegalStateException("Unable to send request");
}

return translator.createLwM2mResponse(destination, request, coapRequest, coapResponse, toolbox);

// TODO send request using code like this ?
// from
// https://github.com/open-coap/java-coap/blob/42032086dca3bf0482d3a4461d0431c9502fcf98/example-client/src/main/java/com/mbed/coap/cli/CoapCli.java#L112-L139
Expand All @@ -71,14 +98,30 @@ public <T extends LwM2mResponse> T send(ClientProfile destination, DownlinkReque
// .blockSize(blockSize)
// .payload(payload)
// );
return null;
}

@Override
public <T extends LwM2mResponse> void send(ClientProfile destination, DownlinkRequest<T> request,
ResponseCallback<T> responseCallback, ErrorCallback errorCallback, LowerLayerConfig lowerLayerConfig,
long timeoutInMs) {
// TODO not implemented yet
final CoapRequest coapRequest = translator.createCoapRequest(destination, request, toolbox);

// create a Coap Client to send request
CoapClient coapClient = CoapClientBuilder.clientFor(destination.getIdentity().getPeerAddress(), coapServer);

// Send CoAP request asynchronously
coapClient.send(coapRequest)
// Handle Exception
.exceptionally((exception) -> {
errorCallback.onError(new SendFailedException(exception));
return null;
})
// Handle CoAP Response
.thenAccept((coapResponse) -> {
T lwM2mResponse = translator.createLwM2mResponse(destination, request, coapRequest, coapResponse,
toolbox);
responseCallback.onResponse(lwM2mResponse);
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.eclipse.leshan.core.endpoint.EndpointUriUtil;
import org.eclipse.leshan.server.LeshanServer;
Expand All @@ -33,10 +32,7 @@
import org.eclipse.leshan.transport.javacoap.resource.RegistrationResource;
import org.eclipse.leshan.transport.javacoap.resource.ResourcesService;

import com.mbed.coap.packet.CoapRequest;
import com.mbed.coap.packet.CoapResponse;
import com.mbed.coap.server.CoapServer;
import com.mbed.coap.utils.Service;

public class JavaCoapServerEndpointsProvider implements LwM2mServerEndpointsProvider {

Expand All @@ -53,25 +49,17 @@ public JavaCoapServerEndpointsProvider(int coapPort) {
public void createEndpoints(UplinkRequestReceiver requestReceiver, LwM2mNotificationReceiver observationService,
ServerEndpointToolbox toolbox, ServerSecurityInfo serverSecurityInfo, LeshanServer server) {

// TODO we should get endpoint used URI dynamically in Resources
// TODO we should get endpoint URI dynamically in Resources
URI endpointURI = EndpointUriUtil.createUri("coap", "0.0.0.0", coapPort);

// create Resources / Routes
RegistrationResource registerResource = new RegistrationResource(requestReceiver, toolbox.getLinkParser(),
endpointURI);
ResourcesService resources = ResourcesService.builder() //
.add("/rd/*", new RegistrationResource(requestReceiver, toolbox.getLinkParser(), endpointURI)).build();
coapServer = CoapServer.builder().transport(5683).route(resources).build();
.add("/rd/*", registerResource).add("/rd", registerResource).build();
coapServer = CoapServer.builder().transport(coapPort).route(resources).build();

lwm2mEndpoint = new JavaCoapServerEndpoint(endpointURI, coapServer);
}

protected Service<CoapRequest, CoapResponse> createRequestsHandler() {
return new Service<CoapRequest, CoapResponse>() {
@Override
public CompletableFuture<CoapResponse> apply(CoapRequest t) {
// TODO Auto-generated method stub
return null;
}
};
lwm2mEndpoint = new JavaCoapServerEndpoint(endpointURI, coapServer, new ServerCoapMessageTranslator(), toolbox);
}

@Override
Expand Down
Loading

0 comments on commit 5b0b66f

Please sign in to comment.