Repository: eclipse/leshan
Pull request #665 (2019-03-14 15:08:50)

Integration of Californium 2.0.0-M14


Patch:
diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/CaliforniumEndpointsManager.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/CaliforniumEndpointsManager.java
index 857b780a..622e7975 100644
--- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/CaliforniumEndpointsManager.java
+++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/CaliforniumEndpointsManager.java
@@ -115,8 +115,7 @@ public class CaliforniumEndpointsManager implements EndpointsManager {
                 serverIdentity = Identity.rpk(serverInfo.getAddress(), expectedKey);
             } else if (serverInfo.secureMode == SecurityMode.X509) {
                 // set identity
-                newBuilder.setIdentity(serverInfo.privateKey, new Certificate[] { serverInfo.clientCertificate },
-                        false);
+                newBuilder.setIdentity(serverInfo.privateKey, new Certificate[] { serverInfo.clientCertificate });
 
                 // set X509 verifier
                 final Certificate expectedServerCertificate = serverInfo.serverCertificate;
@@ -149,15 +148,6 @@ public class CaliforniumEndpointsManager implements EndpointsManager {
                         return null;
                     }
                 });
-
-                // disable the possibility to use RPK as client should use X509.
-                // TODO add a way in Scandium to say that we don't accept RPK certificate type
-                newBuilder.setRpkTrustStore(new TrustedRpkStore() {
-                    @Override
-                    public boolean isTrusted(RawPublicKeyIdentity id) {
-                        return false;
-                    }
-                });
                 serverIdentity = Identity.x509(serverInfo.getAddress(), EndpointContextUtil
                         .extractCN(((X509Certificate) expectedServerCertificate).getSubjectX500Principal().getName()));
             } else {
@@ -166,7 +156,7 @@ public class CaliforniumEndpointsManager implements EndpointsManager {
             if (endpointFactory != null) {
                 currentEndpoint = endpointFactory.createSecuredEndpoint(newBuilder.build(), coapConfig, null);
             } else {
-                CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+                CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
                 builder.setConnector(new DTLSConnector(newBuilder.build()));
                 builder.setNetworkConfig(coapConfig);
                 currentEndpoint = builder.build();
@@ -175,7 +165,7 @@ public class CaliforniumEndpointsManager implements EndpointsManager {
             if (endpointFactory != null) {
                 currentEndpoint = endpointFactory.createUnsecuredEndpoint(localAddress, coapConfig, null);
             } else {
-                CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+                CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
                 builder.setInetSocketAddress(localAddress);
                 builder.setNetworkConfig(coapConfig);
                 currentEndpoint = builder.build();
@@ -258,7 +248,11 @@ public class CaliforniumEndpointsManager implements EndpointsManager {
 
     @Override
     public synchronized void destroy() {
+        // TODO we should be able to destroy a not started coapServer.
+        if (!started)
+            return;
         started = false;
+
         coapServer.destroy();
     }
 }
diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanBootstrapServerBuilder.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanBootstrapServerBuilder.java
index f9a033bc..e170b7a0 100644
--- a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanBootstrapServerBuilder.java
+++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanBootstrapServerBuilder.java
@@ -29,6 +29,7 @@ import org.eclipse.californium.core.network.config.NetworkConfig.Keys;
 import org.eclipse.californium.scandium.DTLSConnector;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
+import org.eclipse.californium.scandium.dtls.CertificateType;
 import org.eclipse.leshan.LwM2m;
 import org.eclipse.leshan.core.californium.EndpointFactory;
 import org.eclipse.leshan.core.californium.Lwm2mEndpointContextMatcher;
@@ -295,12 +296,18 @@ public class LeshanBootstrapServerBuilder {
 
             // handle trusted certificates
             if (trustedCertificates != null) {
-                if (incompleteConfig.getTrustStore() == null) {
-                    dtlsConfigBuilder.setTrustStore(trustedCertificates);
-                } else if (!Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
-                    throw new IllegalStateException(String.format(
-                            "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
-                            Arrays.toString(trustedCertificates), Arrays.toString(incompleteConfig.getTrustStore())));
+                if (incompleteConfig.getCertificateVerifier() == null) {
+                    if (incompleteConfig.getTrustStore() == null) {
+                        dtlsConfigBuilder.setTrustStore(trustedCertificates);
+                    } else if (!Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
+                        throw new IllegalStateException(String.format(
+                                "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
+                                Arrays.toString(trustedCertificates),
+                                Arrays.toString(incompleteConfig.getTrustStore())));
+                    }
+                } else if (trustedCertificates != null) {
+                    throw new IllegalStateException(
+                            "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder: if a CertificateVerifier is set, trustedCertificates must not be set.");
                 }
             }
 
@@ -319,20 +326,27 @@ public class LeshanBootstrapServerBuilder {
                                 "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for public key: %s != %s",
                                 publicKey, incompleteConfig.getPublicKey()));
                     }
-
+                    // by default trust all RPK
+                    if (incompleteConfig.getRpkTrustStore() == null) {
+                        dtlsConfigBuilder.setRpkTrustAll();
+                    }
                     dtlsConfigBuilder.setIdentity(privateKey, publicKey);
                 }
                 // if in X.509 mode set the private key, certificate chain, public key is extracted from the certificate
                 if (certificateChain != null && certificateChain.length > 0) {
                     if (incompleteConfig.getCertificateChain() != null
-                            && !Arrays.equals(incompleteConfig.getCertificateChain(), certificateChain)) {
+                            && !Arrays.asList(certificateChain).equals(incompleteConfig.getCertificateChain())) {
                         throw new IllegalStateException(String.format(
                                 "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for certificate chain: %s != %s",
-                                Arrays.toString(certificateChain),
-                                Arrays.toString(incompleteConfig.getCertificateChain())));
+                                Arrays.toString(certificateChain), incompleteConfig.getCertificateChain()));
                     }
 
-                    dtlsConfigBuilder.setIdentity(privateKey, certificateChain, false);
+                    // by default trust all RPK
+                    if (incompleteConfig.getRpkTrustStore() == null) {
+                        dtlsConfigBuilder.setRpkTrustAll();
+                    }
+                    dtlsConfigBuilder.setIdentity(privateKey, certificateChain, CertificateType.X_509,
+                            CertificateType.RAW_PUBLIC_KEY);
                 }
             }
 
@@ -346,6 +360,7 @@ public class LeshanBootstrapServerBuilder {
             try {
                 dtlsConfig = dtlsConfigBuilder.build();
             } catch (IllegalStateException e) {
+                LOG.warn("Unable to create DTLS config and so secured endpoint.", e);
             }
         }
 
@@ -354,7 +369,7 @@ public class LeshanBootstrapServerBuilder {
             if (endpointFactory != null) {
                 unsecuredEndpoint = endpointFactory.createUnsecuredEndpoint(localAddress, coapConfig, null);
             } else {
-                CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+                CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
                 builder.setInetSocketAddress(localAddress);
                 builder.setNetworkConfig(coapConfig);
                 unsecuredEndpoint = builder.build();
@@ -366,7 +381,7 @@ public class LeshanBootstrapServerBuilder {
             if (endpointFactory != null) {
                 securedEndpoint = endpointFactory.createSecuredEndpoint(dtlsConfig, coapConfig, null);
             } else {
-                CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+                CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
                 builder.setConnector(new DTLSConnector(dtlsConfig));
                 builder.setNetworkConfig(coapConfig);
                 builder.setEndpointContextMatcher(new Lwm2mEndpointContextMatcher());
diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanServerBuilder.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanServerBuilder.java
index 6b4ce86f..813ef492 100644
--- a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanServerBuilder.java
+++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/LeshanServerBuilder.java
@@ -30,6 +30,7 @@ import org.eclipse.californium.core.network.config.NetworkConfig;
 import org.eclipse.californium.core.network.config.NetworkConfig.Keys;
 import org.eclipse.californium.scandium.DTLSConnector;
 import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
+import org.eclipse.californium.scandium.dtls.CertificateType;
 import org.eclipse.leshan.LwM2m;
 import org.eclipse.leshan.core.californium.EndpointFactory;
 import org.eclipse.leshan.core.californium.Lwm2mEndpointContextMatcher;
@@ -412,12 +413,15 @@ public class LeshanServerBuilder {
 
             // handle trusted certificates
             if (trustedCertificates != null) {
-                if (incompleteConfig.getTrustStore() == null) {
-                    dtlsConfigBuilder.setTrustStore(trustedCertificates);
-                } else if (!Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
-                    throw new IllegalStateException(String.format(
-                            "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
-                            Arrays.toString(trustedCertificates), Arrays.toString(incompleteConfig.getTrustStore())));
+                if (incompleteConfig.getCertificateVerifier() == null) {
+                    if (incompleteConfig.getTrustStore() == null) {
+                        dtlsConfigBuilder.setTrustStore(trustedCertificates);
+                    } else if (!Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
+                        throw new IllegalStateException(String.format(
+                                "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
+                                Arrays.toString(trustedCertificates),
+                                Arrays.toString(incompleteConfig.getTrustStore())));
+                    }
                 }
             }
 
@@ -437,19 +441,27 @@ public class LeshanServerBuilder {
                                 publicKey, incompleteConfig.getPublicKey()));
                     }
 
+                    // by default trust all RPK
+                    if (incompleteConfig.getRpkTrustStore() == null) {
+                        dtlsConfigBuilder.setRpkTrustAll();
+                    }
                     dtlsConfigBuilder.setIdentity(privateKey, publicKey);
                 }
                 // if in X.509 mode set the private key, certificate chain, public key is extracted from the certificate
                 if (certificateChain != null && certificateChain.length > 0) {
                     if (incompleteConfig.getCertificateChain() != null
-                            && !Arrays.equals(incompleteConfig.getCertificateChain(), certificateChain)) {
+                            && !Arrays.asList(certificateChain).equals(incompleteConfig.getCertificateChain())) {
                         throw new IllegalStateException(String.format(
                                 "Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for certificate chain: %s != %s",
-                                Arrays.toString(certificateChain),
-                                Arrays.toString(incompleteConfig.getCertificateChain())));
+                                Arrays.toString(certificateChain), incompleteConfig.getCertificateChain()));
                     }
 
-                    dtlsConfigBuilder.setIdentity(privateKey, certificateChain, false);
+                    // by default trust all RPK
+                    if (incompleteConfig.getRpkTrustStore() == null) {
+                        dtlsConfigBuilder.setRpkTrustAll();
+                    }
+                    dtlsConfigBuilder.setIdentity(privateKey, certificateChain, CertificateType.X_509,
+                            CertificateType.RAW_PUBLIC_KEY);
                 }
             }
 
@@ -463,6 +475,7 @@ public class LeshanServerBuilder {
             try {
                 dtlsConfig = dtlsConfigBuilder.build();
             } catch (IllegalStateException e) {
+                LOG.warn("Unable to create DTLS config and so secured endpoint.", e);
             }
         }
 
@@ -473,7 +486,7 @@ public class LeshanServerBuilder {
                 unsecuredEndpoint = endpointFactory.createUnsecuredEndpoint(localAddress, coapConfig,
                         registrationStore);
             } else {
-                CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+                CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
                 builder.setInetSocketAddress(localAddress);
                 builder.setNetworkConfig(coapConfig);
                 builder.setObservationStore(registrationStore);
@@ -486,7 +499,7 @@ public class LeshanServerBuilder {
             if (endpointFactory != null) {
                 securedEndpoint = endpointFactory.createSecuredEndpoint(dtlsConfig, coapConfig, registrationStore);
             } else {
-                CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+                CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
                 builder.setConnector(new DTLSConnector(dtlsConfig));
                 builder.setNetworkConfig(coapConfig);
                 builder.setObservationStore(registrationStore);
diff --git a/pom.xml b/pom.xml
index b3da97a7..b441d794 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,7 +108,7 @@ Contributors:
         <test.exclusion.pattern>**/Redis*.java</test.exclusion.pattern>
 
         <!-- dependencies version -->
-        <californium.version>2.0.0-M12</californium.version>
+        <californium.version>2.0.0-M14</californium.version>
         <logback.version>1.2.3</logback.version>
         <slf4j.api.version>1.7.25</slf4j.api.version>
         <jetty.version>9.1.4.v20140401</jetty.version>
@@ -492,7 +492,7 @@ Contributors:
             <dependency>
                 <groupId>junit</groupId>
                 <artifactId>junit</artifactId>
-                <version>4.11</version>
+                <version>4.12</version>
                 <scope>test</scope>
             </dependency>
             <dependency>


Test patch:
diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/RegistrationTest.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/RegistrationTest.java
index 8a0d5de9..62c9a2cd 100644
--- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/RegistrationTest.java
+++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/RegistrationTest.java
@@ -46,6 +46,7 @@ import org.eclipse.leshan.core.observation.Observation;
 import org.eclipse.leshan.core.request.ContentFormat;
 import org.eclipse.leshan.core.request.ObserveRequest;
 import org.eclipse.leshan.core.request.ReadRequest;
+import org.eclipse.leshan.core.request.exception.SendFailedException;
 import org.eclipse.leshan.core.response.ObserveResponse;
 import org.eclipse.leshan.core.response.ReadResponse;
 import org.eclipse.leshan.server.registration.Registration;
@@ -230,12 +231,12 @@ public class RegistrationTest {
         assertTrue(observations.isEmpty());
 
         // try to send a new observation
-        observeResponse = helper.server.send(currentRegistration, new ObserveRequest(3, 0), 50);
-        assertNull(observeResponse);
-
-        // check observationStore is empty
-        observations = helper.server.getObservationService().getObservations(currentRegistration);
-        assertTrue(observations.isEmpty());
+        try {
+            observeResponse = helper.server.send(currentRegistration, new ObserveRequest(3, 0), 50);
+        } catch (SendFailedException e) {
+            return;
+        }
+        fail("Observe request should be sent");
     }
 
     // TODO not really a registration test
@@ -287,7 +288,7 @@ public class RegistrationTest {
         coapRequest.getOptions().addUriQuery("ep=" + helper.currentEndpointIdentifier);
 
         // send request
-        CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+        CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
         builder.setInetSocketAddress(new InetSocketAddress(0));
         CoapEndpoint coapEndpoint = builder.build();
         coapEndpoint.start();
diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java
index 30598948..db73224d 100644
--- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java
+++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/SecureIntegrationTestHelper.java
@@ -206,7 +206,7 @@ public class SecureIntegrationTestHelper extends IntegrationTestHelper {
             @Override
             public CoapEndpoint createUnsecuredEndpoint(InetSocketAddress address, NetworkConfig coapConfig,
                     ObservationStore store) {
-                CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+                CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
                 builder.setInetSocketAddress(address);
                 builder.setNetworkConfig(coapConfig);
                 return builder.build();
@@ -215,7 +215,7 @@ public class SecureIntegrationTestHelper extends IntegrationTestHelper {
             @Override
             public CoapEndpoint createSecuredEndpoint(DtlsConnectorConfig dtlsConfig, NetworkConfig coapConfig,
                     ObservationStore store) {
-                CoapEndpoint.CoapEndpointBuilder builder = new CoapEndpoint.CoapEndpointBuilder();
+                CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
                 Builder dtlsConfigBuilder = new Builder(dtlsConfig);
                 if (dtlsConfig.getPskStore() != null) {
                     String identity = dtlsConfig.getPskStore().getIdentity(null);