From 19913087889195b0a2e42d0abbb1a4773aaa08b6 Mon Sep 17 00:00:00 2001 From: Martin Herbst Date: Sat, 25 Apr 2020 21:08:46 +0200 Subject: [PATCH] [homematic] Use async Jetty http request to support larger buffers (#7473) Solves #6963 Signed-off-by: Martin Herbst --- .../communicator/client/RpcClient.java | 1 + .../communicator/client/XmlRpcClient.java | 38 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java index 8a5deeaad214d..5f1b17afc8e5a 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java @@ -52,6 +52,7 @@ public abstract class RpcClient { private final Logger logger = LoggerFactory.getLogger(RpcClient.class); protected static final int MAX_RPC_RETRY = 1; + protected static final int RESP_BUFFER_SIZE = 8192; protected HomematicConfig config; diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java index 4a4ec3b659e6a..5aa5d1cd08793 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java @@ -13,13 +13,17 @@ package org.openhab.binding.homematic.internal.communicator.client; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.util.BytesContentProvider; +import org.eclipse.jetty.client.util.InputStreamResponseListener; import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpStatus; import org.openhab.binding.homematic.internal.common.HomematicConfig; import org.openhab.binding.homematic.internal.communicator.message.RpcRequest; import org.openhab.binding.homematic.internal.communicator.message.XmlRpcRequest; @@ -79,17 +83,31 @@ private synchronized Object[] sendMessage(int port, RpcRequest request, if (port == config.getGroupPort()) { url += "/groups"; } - ContentResponse response = httpClient.POST(url).content(content) - .timeout(config.getTimeout(), TimeUnit.SECONDS) - .header(HttpHeader.CONTENT_TYPE, "text/xml;charset=" + config.getEncoding()).send(); - + InputStreamResponseListener respListener = new InputStreamResponseListener(); + httpClient.POST(url).content(content) + .header(HttpHeader.CONTENT_TYPE, "text/xml;charset=" + config.getEncoding()).send(respListener); + Response resp = respListener.get(config.getTimeout(), TimeUnit.SECONDS); + ByteArrayOutputStream respData = new ByteArrayOutputStream(RESP_BUFFER_SIZE); + int httpStatus = resp.getStatus(); + if (httpStatus == HttpStatus.OK_200) { + byte[] recvBuffer = new byte[RESP_BUFFER_SIZE]; + InputStream input = respListener.getInputStream(); + while (true) { + int read = input.read(recvBuffer); + if (read == -1) { + break; + } + respData.write(recvBuffer, 0, read); + } + } else { + logger.warn("XmlRpcRequest failure, status code: {} / request was: {}", httpStatus, request); + resp.abort(new Exception()); + } if (logger.isTraceEnabled()) { - String result = new String(response.getContent(), config.getEncoding()); - logger.trace("Client XmlRpcResponse (port {}):\n{}", port, result); + logger.trace("Client XmlRpcResponse: (port {}):\n{}", port, respData.toString(config.getEncoding())); } - - Object[] data = new XmlRpcResponse(new ByteArrayInputStream(response.getContent()), - config.getEncoding()).getResponseData(); + Object[] data = new XmlRpcResponse(new ByteArrayInputStream(respData.toByteArray()), config.getEncoding()) + .getResponseData(); return new RpcResponseParser(request).parse(data); } catch (UnknownRpcFailureException | UnknownParameterSetException ex) { throw ex;