From a33ba34e70279be7098c5d041ddfe039db4ce37a Mon Sep 17 00:00:00 2001 From: sanshengshui Date: Fri, 3 Nov 2023 22:32:32 +0800 Subject: [PATCH] =?UTF-8?q?:closed=5Flock=5Fwith=5Fkey:=20add=20psk=20for?= =?UTF-8?q?=20coap=20get=E3=80=81put=E3=80=81post=20and=20delete=20operati?= =?UTF-8?q?ons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../toolkit/coap/command/CoapCommand.java | 2 - .../coap/command/sub/CoapDeleteCommand.java | 35 ++++-- .../coap/command/sub/CoapDiscoverCommand.java | 34 +++++- .../coap/command/sub/CoapGetCommand.java | 28 ++++- .../coap/command/sub/CoapPostCommand.java | 38 +++++-- .../coap/command/sub/CoapPutCommand.java | 38 +++++-- .../coap/service/CoapClientService.java | 104 ++++++++++++++---- .../toolkit/coap/service/DtlsClient.java | 76 +++++++++++-- 8 files changed, 289 insertions(+), 66 deletions(-) diff --git a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/CoapCommand.java b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/CoapCommand.java index c10ab632..46d10d4e 100644 --- a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/CoapCommand.java +++ b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/CoapCommand.java @@ -18,13 +18,11 @@ import iot.technology.client.toolkit.coap.command.sub.*; import iot.technology.client.toolkit.common.constants.ExitCodeEnum; import iot.technology.client.toolkit.common.constants.StorageConstants; -import iot.technology.client.toolkit.common.utils.StringUtils; import picocli.CommandLine; import java.util.ResourceBundle; import java.util.concurrent.Callable; -import static iot.technology.client.toolkit.common.utils.ColorUtils.colorItalic; /** * @author mushuwei diff --git a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapDeleteCommand.java b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapDeleteCommand.java index 3012e2d5..fad4ffe0 100644 --- a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapDeleteCommand.java +++ b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapDeleteCommand.java @@ -16,10 +16,8 @@ package iot.technology.client.toolkit.coap.command.sub; import iot.technology.client.toolkit.coap.service.CoapClientService; -import iot.technology.client.toolkit.coap.validator.CoapCommandParamValidator; import iot.technology.client.toolkit.common.constants.ExitCodeEnum; -import org.eclipse.californium.core.CoapClient; -import org.eclipse.californium.core.CoapResponse; +import org.eclipse.californium.core.coap.CoAP; import picocli.CommandLine; import java.net.URI; @@ -40,7 +38,7 @@ footerHeading = "%nCopyright (c) 2019-2023, ${bundle:general.copyright}", footer = "%nDeveloped by mushuwei" ) -public class CoapDeleteCommand implements Callable { +public class CoapDeleteCommand extends AbstractCoapContext implements Callable { private final CoapClientService coapClientService = new CoapClientService(); @@ -52,12 +50,35 @@ public class CoapDeleteCommand implements Callable { description = "${bundle:coap.uri.description}") private URI uri; + /* ********************************** Identity Section ******************************** */ + @CommandLine.ArgGroup(exclusive = false, + heading = "%n@|bold,underline PSK Options|@ %n%n"// + + "@|italic " // + + "By default use non secure connection.%n"// + + "To use CoAP over DTLS with Pre-Shared Key, -i and -p options should be used together." // + + "|@%n%n") + private PskSection psk = new PskSection(); + + public static class PskSection { + @CommandLine.Option(required = true, + names = { "-i", "--psk-identity" }, + description = { // + "Set the server PSK identity in ascii." }) + public String identity; + + @CommandLine.Option(required = true, + names = { "-p", "--psk-key" }, + description = { // + "Set the server Pre-Shared-Key" }) + public String sharekey; + } + @Override public Integer call() throws Exception { - CoapCommandParamValidator.validateUri(uri); + String scheme = validateUri(uri); + String protocol = CoAP.getProtocolForScheme(scheme); - CoapClient coapClient = coapClientService.getCoapClient(uri); - CoapResponse response = coapClient.delete(); + var response = coapClientService.deletePayload(uri, protocol, psk.identity, psk.sharekey); StringBuffer result = new StringBuffer(); String requestInfo = coapClientService.requestInfo("delete", uri.toString()); diff --git a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapDiscoverCommand.java b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapDiscoverCommand.java index 72836e5e..6c680180 100644 --- a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapDiscoverCommand.java +++ b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapDiscoverCommand.java @@ -16,12 +16,12 @@ package iot.technology.client.toolkit.coap.command.sub; import iot.technology.client.toolkit.coap.service.CoapClientService; -import iot.technology.client.toolkit.coap.validator.CoapCommandParamValidator; import iot.technology.client.toolkit.common.constants.ExitCodeEnum; import iot.technology.client.toolkit.common.constants.StorageConstants; import iot.technology.client.toolkit.common.utils.StringUtils; import org.eclipse.californium.core.CoapClient; import org.eclipse.californium.core.WebLink; +import org.eclipse.californium.core.coap.CoAP; import picocli.CommandLine; import java.net.URI; @@ -44,7 +44,7 @@ footerHeading = "%nCopyright (c) 2019-2023, ${bundle:general.copyright}", footer = "%nDeveloped by mushuwei" ) -public class CoapDiscoverCommand implements Callable { +public class CoapDiscoverCommand extends AbstractCoapContext implements Callable { ResourceBundle bundle = ResourceBundle.getBundle(StorageConstants.LANG_MESSAGES); @@ -58,11 +58,35 @@ public class CoapDiscoverCommand implements Callable { description = "${bundle:coap.uri.description}") private URI uri; + /* ********************************** Identity Section ******************************** */ + /* ********************************** Identity Section ******************************** */ + @CommandLine.ArgGroup(exclusive = false, + heading = "%n@|bold,underline PSK Options|@ %n%n"// + + "@|italic " // + + "By default use non secure connection.%n"// + + "To use CoAP over DTLS with Pre-Shared Key, -i and -p options should be used together." // + + "|@%n%n") + private PskSection psk = new PskSection(); - public Integer call() throws Exception { - CoapCommandParamValidator.validateUri(uri); + public static class PskSection { + @CommandLine.Option(required = true, + names = { "-i", "--psk-identity" }, + description = { // + "Set the server PSK identity in ascii." }) + public String identity; + + @CommandLine.Option(required = true, + names = { "-p", "--psk-key" }, + description = { // + "Set the server Pre-Shared-Key" }) + public String sharekey; + } - CoapClient coapClient = coapClientService.getCoapClient(uri); + + public Integer call() throws Exception { + String scheme = validateUri(uri); + String protocol = CoAP.getProtocolForScheme(scheme); + CoapClient coapClient = CoapClientService.getCoapClient(uri, protocol, psk.identity, psk.sharekey); Set webLinks = coapClient.discover(); String availableResources = coapClientService.getAvailableResources(webLinks); diff --git a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapGetCommand.java b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapGetCommand.java index c031335b..2d4a9ac9 100644 --- a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapGetCommand.java +++ b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapGetCommand.java @@ -16,10 +16,7 @@ package iot.technology.client.toolkit.coap.command.sub; import iot.technology.client.toolkit.coap.service.CoapClientService; -import iot.technology.client.toolkit.coap.validator.CoapCommandParamValidator; import iot.technology.client.toolkit.common.constants.ExitCodeEnum; -import org.eclipse.californium.core.CoapClient; -import org.eclipse.californium.core.CoapResponse; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.MediaTypeRegistry; import org.eclipse.californium.core.coap.Response; @@ -64,8 +61,27 @@ public class CoapGetCommand extends AbstractCoapContext implements Callable { +public class CoapPostCommand extends AbstractCoapContext implements Callable { private final CoapClientService coapClientService = new CoapClientService(); @@ -73,17 +72,38 @@ public class CoapPostCommand implements Callable { defaultValue = COAP_TEXT_PLAIN) private String accept; + /* ********************************** Identity Section ******************************** */ + @CommandLine.ArgGroup(exclusive = false, + heading = "%n@|bold,underline PSK Options|@ %n%n"// + + "@|italic " // + + "By default use non secure connection.%n"// + + "To use CoAP over DTLS with Pre-Shared Key, -i and -p options should be used together." // + + "|@%n%n") + private PskSection psk = new PskSection(); + + public static class PskSection { + @CommandLine.Option(required = true, + names = { "-i", "--psk-identity" }, + description = { // + "Set the server PSK identity in ascii." }) + public String identity; + + @CommandLine.Option(required = true, + names = { "-pk", "--psk-key" }, + description = { // + "Set the server Pre-Shared-Key" }) + public String sharekey; + } + @Override public Integer call() throws Exception { - CoapCommandParamValidator.validateUri(uri); - String payloadContent = CoapCommandParamValidator.validatePayloadAndFile(payload); + var scheme = validateUri(uri); + var protocol = CoAP.getProtocolForScheme(scheme); + var payloadContent = CoapCommandParamValidator.validatePayloadAndFile(payload); - CoapClient coapClient = coapClientService.getCoapClient(uri); - int formatCode = coapClientService.coapContentType(format); - int acceptCode = coapClientService.coapContentType(accept); + var response = coapClientService.postPayload(uri, protocol, psk.identity, psk.sharekey, payloadContent, format, accept); StringBuffer result = new StringBuffer(); - CoapResponse response = coapClient.post(payloadContent, formatCode, acceptCode); String requestInfo = coapClientService.requestInfo("post", uri.toString()); String responseStr = coapClientService.prettyPrint(response, requestInfo); result.append(responseStr); diff --git a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapPutCommand.java b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapPutCommand.java index e38e0727..daaf527a 100644 --- a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapPutCommand.java +++ b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/sub/CoapPutCommand.java @@ -18,8 +18,7 @@ import iot.technology.client.toolkit.coap.service.CoapClientService; import iot.technology.client.toolkit.coap.validator.CoapCommandParamValidator; import iot.technology.client.toolkit.common.constants.ExitCodeEnum; -import org.eclipse.californium.core.CoapClient; -import org.eclipse.californium.core.CoapResponse; +import org.eclipse.californium.core.coap.CoAP; import picocli.CommandLine; import java.net.URI; @@ -41,7 +40,7 @@ footerHeading = "%nCopyright (c) 2019-2023, ${bundle:general.copyright}", footer = "%nDeveloped by mushuwei" ) -public class CoapPutCommand implements Callable { +public class CoapPutCommand extends AbstractCoapContext implements Callable { private final CoapClientService coapClientService = new CoapClientService(); @@ -67,13 +66,36 @@ public class CoapPutCommand implements Callable { defaultValue = COAP_TEXT_PLAIN) private String format; + /* ********************************** Identity Section ******************************** */ + @CommandLine.ArgGroup(exclusive = false, + heading = "%n@|bold,underline PSK Options|@ %n%n"// + + "@|italic " // + + "By default use non secure connection.%n"// + + "To use CoAP over DTLS with Pre-Shared Key, -i and -p options should be used together." // + + "|@%n%n") + private PskSection psk = new PskSection(); + + public static class PskSection { + @CommandLine.Option(required = true, + names = { "-i", "--psk-identity" }, + description = { // + "Set the server PSK identity in ascii." }) + public String identity; + + @CommandLine.Option(required = true, + names = { "-pk", "--psk-key" }, + description = { // + "Set the server Pre-Shared-Key" }) + public String sharekey; + } + + @Override public Integer call() throws Exception { - CoapCommandParamValidator.validateUri(uri); - String payloadContent = CoapCommandParamValidator.validatePayloadAndFile(payload); - - CoapClient coapClient = coapClientService.getCoapClient(uri); - CoapResponse response = coapClient.put(payloadContent, coapClientService.coapContentType(format)); + var scheme = validateUri(uri); + var protocol = CoAP.getProtocolForScheme(scheme); + var payloadContent = CoapCommandParamValidator.validatePayloadAndFile(payload); + var response = coapClientService.putPayload(uri, protocol, psk.identity, psk.sharekey, payloadContent, format); String requestInfo = coapClientService.requestInfo("put", uri.toString()); String responseStr = coapClientService.prettyPrint(response, requestInfo); diff --git a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/service/CoapClientService.java b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/service/CoapClientService.java index 1fd8f48c..638dc950 100644 --- a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/service/CoapClientService.java +++ b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/service/CoapClientService.java @@ -19,7 +19,6 @@ import com.github.freva.asciitable.AsciiTable; import com.github.freva.asciitable.Column; import com.github.freva.asciitable.HorizontalAlign; -import iot.technology.client.toolkit.coap.command.sub.CoapIdentitySection; import iot.technology.client.toolkit.coap.domain.AvailableResource; import iot.technology.client.toolkit.coap.domain.CoapSupportType; import iot.technology.client.toolkit.common.constants.HttpStatus; @@ -32,21 +31,12 @@ import org.eclipse.californium.core.CoapResponse; import org.eclipse.californium.core.WebLink; import org.eclipse.californium.core.coap.MediaTypeRegistry; -import org.eclipse.californium.core.coap.Request; import org.eclipse.californium.core.coap.Response; -import org.eclipse.californium.core.network.CoapEndpoint; -import org.eclipse.californium.elements.config.Configuration; import org.eclipse.californium.elements.exception.ConnectorException; import org.eclipse.californium.elements.util.StringUtil; -import org.eclipse.californium.scandium.DTLSConnector; -import org.eclipse.californium.scandium.config.DtlsConfig; -import org.eclipse.californium.scandium.config.DtlsConnectorConfig; -import org.eclipse.californium.scandium.dtls.pskstore.AdvancedSinglePskStore; -import org.eclipse.californium.scandium.dtls.x509.SingleCertificateProvider; import org.w3c.dom.Document; import picocli.CommandLine; -import javax.crypto.SecretKey; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; @@ -54,7 +44,6 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.net.URI; @@ -69,7 +58,7 @@ public class CoapClientService { ResourceBundle bundle = ResourceBundle.getBundle(StorageConstants.LANG_MESSAGES); - public int coapContentType(String contentType) { + public static int coapContentType(String contentType) { int coapContentTypeCode = -1; try { coapContentTypeCode = Integer.parseInt(contentType); @@ -78,11 +67,6 @@ public int coapContentType(String contentType) { return (coapContentTypeCode < 0) ? MediaTypeRegistry.parse(contentType) : coapContentTypeCode; } - - public CoapClient getCoapClient(URI uri) { - return new CoapClient(uri); - } - public String requestInfo(String method, String path) { return " " + ColorUtils.colorBold((method.toUpperCase(Locale.ROOT) + ":" + path), "cyan"); } @@ -338,16 +322,17 @@ private static String prettyLink(String text) { } public Response getResponse(URI uri, String protocol, - CoapIdentitySection identity, String accept) { + String identity, String sharekey, + String accept) { try { if (protocol.equals("UDP")) { var client = new CoapClient(uri); var acceptType = coapContentType(accept); return client.get(acceptType).advanced(); } else if (protocol.equals("DTLS")) { - if (identity.hasIdentity()) { - DtlsClient client = DtlsClient.initDtlsClient(identity.getPsk().identity, identity.getPsk().sharekey); - CoapResponse response = client.getResponse(uri); + if (StringUtils.isNotBlank(identity) && StringUtils.isNotBlank(sharekey)) { + var client = DtlsClient.initDtlsClient(identity, sharekey); + CoapResponse response = client.getResponse(uri, accept); return response.advanced(); } throw new IllegalArgumentException("coaps、psk options should be used together."); @@ -357,4 +342,81 @@ public Response getResponse(URI uri, String protocol, throw new RuntimeException(e); } } + + public CoapResponse putPayload(URI uri, String protocol, + String identity, String sharekey, + String payloadContent, String format) { + try { + if (protocol.equals("UDP")) { + var coapClient = new CoapClient(uri); + var response = coapClient.put(payloadContent, this.coapContentType(format)); + return response; + } else if (protocol.equals("DTLS")) { + if (StringUtils.isNotBlank(identity) && StringUtils.isNotBlank(sharekey)) { + var dtlsClient = DtlsClient.initDtlsClient(identity, sharekey); + return dtlsClient.putPayload(uri, payloadContent, format); + } + throw new IllegalArgumentException("coaps、psk options should be used together."); + } + throw new IllegalArgumentException("protocol " + protocol + " not supported!"); + } catch (ConnectorException | IOException e) { + throw new RuntimeException(e); + } + } + + public CoapResponse postPayload(URI uri, String protocol, + String identity, String sharekey, + String payloadContent, + String format, String accept) { + try { + if (protocol.equals("UDP")) { + var client = new CoapClient(uri); + return client.post(payloadContent, coapContentType(format), coapContentType(accept)); + } else if (protocol.equals("DTLS")) { + if (StringUtils.isNotBlank(identity) && StringUtils.isNotBlank(sharekey)) { + var dtlsClient = DtlsClient.initDtlsClient(identity, sharekey); + return dtlsClient.postPayload(uri, payloadContent, format, accept); + } + throw new IllegalArgumentException("coaps、psk options should be used together."); + } + throw new IllegalArgumentException("protocol " + protocol + " not supported!"); + } catch (ConnectorException | IOException e) { + throw new RuntimeException(e); + } + } + + public CoapResponse deletePayload(URI uri, String protocol, + String identity, String sharekey) { + try { + if (protocol.equals("UDP")) { + var client = new CoapClient(uri); + return client.delete(); + } else if (protocol.equals("DTLS")) { + if (StringUtils.isNotBlank(identity) && StringUtils.isNotBlank(sharekey)) { + var dtlsClient = DtlsClient.initDtlsClient(identity, sharekey); + return dtlsClient.deletePayload(uri); + } + throw new IllegalArgumentException("coaps、psk options should be used together."); + } + throw new IllegalArgumentException("protocol " + protocol + " not supported!"); + } catch (ConnectorException | IOException e) { + throw new RuntimeException(e); + } + } + + public static CoapClient getCoapClient(URI uri, String protocol, + String identity, String sharekey) { + if (protocol.equals("UDP")) { + var client = new CoapClient(uri); + return client; + } else if (protocol.equals("DTLS")) { + if (StringUtils.isNotBlank(identity) && StringUtils.isNotBlank(sharekey)) { + var dtlsClient = DtlsClient.initDtlsClient(identity, sharekey); + var client = dtlsClient.initCoapClient(uri); + return client; + } + throw new IllegalArgumentException("coaps、psk options should be used together."); + } + throw new IllegalArgumentException("protocol " + protocol + " not supported!"); + } } diff --git a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/service/DtlsClient.java b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/service/DtlsClient.java index bd04e3cc..ba98d77c 100644 --- a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/service/DtlsClient.java +++ b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/service/DtlsClient.java @@ -3,7 +3,6 @@ import iot.technology.client.toolkit.common.utils.security.CredentialsUtil; import org.eclipse.californium.core.CoapClient; import org.eclipse.californium.core.CoapResponse; -import org.eclipse.californium.core.coap.Response; import org.eclipse.californium.core.config.CoapConfig; import org.eclipse.californium.core.network.CoapEndpoint; import org.eclipse.californium.elements.config.Configuration; @@ -17,7 +16,6 @@ import java.io.File; import java.io.IOException; import java.net.URI; -import java.net.URISyntaxException; import java.util.List; /** @@ -50,17 +48,79 @@ public DtlsClient(DTLSConnector dtlsConnector, Configuration configuration) { config.setTransient(DtlsConfig.DTLS_CIPHER_SUITES); }; - - public CoapResponse getResponse(URI uri) { - CoapResponse response = null; - try { + public CoapClient initCoapClient(URI uri) { CoapClient client = new CoapClient(uri); CoapEndpoint.Builder builder = new CoapEndpoint.Builder() .setConfiguration(configuration) .setConnector(dtlsConnector); client.setEndpoint(builder.build()); - response = client.get(); - client.shutdown(); + return client; + } + + public CoapResponse getResponse(URI uri, String accept) { + CoapResponse response = null; + try { + CoapClient client = new CoapClient(uri); + CoapEndpoint.Builder builder = new CoapEndpoint.Builder() + .setConfiguration(configuration) + .setConnector(dtlsConnector); + client.setEndpoint(builder.build()); + var acceptType = CoapClientService.coapContentType(accept); + response = client.get(acceptType); + client.shutdown(); + } catch (ConnectorException | IOException e) { + System.err.println("Error occurred while sending request: " + e); + System.exit(-1); + } + return response; + } + + public CoapResponse putPayload(URI uri, String payloadContent, String format) { + CoapResponse response = null; + try { + CoapClient client = new CoapClient(uri); + CoapEndpoint.Builder builder = new CoapEndpoint.Builder() + .setConfiguration(configuration) + .setConnector(dtlsConnector); + client.setEndpoint(builder.build()); + var coapResponse = client.put(payloadContent, CoapClientService.coapContentType(format)); + response = coapResponse; + client.shutdown(); + } catch (ConnectorException | IOException e) { + System.err.println("Error occurred while sending request: " + e); + System.exit(-1); + } + return response; + } + + public CoapResponse postPayload(URI uri, String payloadContent, + String format, String accept) { + CoapResponse response = null; + try { + CoapClient client = new CoapClient(uri); + CoapEndpoint.Builder builder = new CoapEndpoint.Builder() + .setConfiguration(configuration) + .setConnector(dtlsConnector); + client.setEndpoint(builder.build()); + response = client.post(payloadContent, CoapClientService.coapContentType(format), CoapClientService.coapContentType(accept)); + client.shutdown(); + } catch (ConnectorException | IOException e) { + System.err.println("Error occurred while sending request: " + e); + System.exit(-1); + } + return response; + } + + public CoapResponse deletePayload(URI uri) { + CoapResponse response = null; + try { + var client = new CoapClient(uri); + CoapEndpoint.Builder builder = new CoapEndpoint.Builder() + .setConfiguration(configuration) + .setConnector(dtlsConnector); + client.setEndpoint(builder.build()); + response = client.delete(); + client.shutdown(); } catch (ConnectorException | IOException e) { System.err.println("Error occurred while sending request: " + e); System.exit(-1);