From fa5682f1d274a03fb98ad4c1f8178bb4853e6bc4 Mon Sep 17 00:00:00 2001 From: slaff Date: Mon, 19 Oct 2020 19:25:07 +0200 Subject: [PATCH] Small updates to Http response/request and Udp (#2117) * Made toString method for HttpRequest and HttpResponse to be available also in release mode. Useful for building Http request/response strings. * Added UDP multicast methods (when the used LWIP version supports it). * Added join/leave to/from multicast groups in IpConnection class. Co-authored-by: mikee47 --- Sming/Core/Network/Http/HttpRequest.cpp | 21 ++++---- Sming/Core/Network/Http/HttpRequest.h | 15 ++++-- Sming/Core/Network/Http/HttpResponse.cpp | 21 ++++++++ Sming/Core/Network/Http/HttpResponse.h | 17 +++++++ Sming/Core/Network/IpConnection.cpp | 22 ++++++++ Sming/Core/Network/IpConnection.h | 65 ++++++++++++++++++++++++ Sming/Core/Network/TcpConnection.h | 4 +- Sming/Core/Network/UdpConnection.cpp | 20 ++++++++ Sming/Core/Network/UdpConnection.h | 31 +++++++++-- 9 files changed, 197 insertions(+), 19 deletions(-) create mode 100644 Sming/Core/Network/IpConnection.cpp create mode 100644 Sming/Core/Network/IpConnection.h diff --git a/Sming/Core/Network/Http/HttpRequest.cpp b/Sming/Core/Network/Http/HttpRequest.cpp index 165d2c70cd..0fc74778ef 100644 --- a/Sming/Core/Network/Http/HttpRequest.cpp +++ b/Sming/Core/Network/Http/HttpRequest.cpp @@ -83,20 +83,23 @@ void HttpRequest::reset() files.clear(); } -#ifndef SMING_RELEASE -String HttpRequest::toString() +String HttpRequest::toString(const HttpRequest& req) { String content; - content += String(http_method_str(method)) + ' ' + uri.getPathWithQuery() + _F(" HTTP/1.1\n"); - content += headers.toString(HTTP_HEADER_HOST, uri.getHostWithPort()); - for(unsigned i = 0; i < headers.count(); i++) { - content += headers[i]; + content += http_method_str(req.method); + content += ' '; + content += req.uri.getPathWithQuery(); + content += _F(" HTTP/1.1\r\n"); + content += req.headers.toString(HTTP_HEADER_HOST, uri.getHostWithPort()); + for(unsigned i = 0; i < req.headers.count(); i++) { + content += req.headers[i]; } - if(bodyStream != nullptr && bodyStream->available() >= 0) { - content += headers.toString(HTTP_HEADER_CONTENT_LENGTH, String(bodyStream->available())); + if(req.bodyStream != nullptr && req.bodyStream->available() >= 0) { + content += req.headers.toString(HTTP_HEADER_CONTENT_LENGTH, String(req.bodyStream->available())); + } else { + content += "\r\n"; } return content; } -#endif diff --git a/Sming/Core/Network/Http/HttpRequest.h b/Sming/Core/Network/Http/HttpRequest.h index 9db8a4f782..4a582062bf 100644 --- a/Sming/Core/Network/Http/HttpRequest.h +++ b/Sming/Core/Network/Http/HttpRequest.h @@ -255,13 +255,22 @@ class HttpRequest return this; } -#ifndef SMING_RELEASE /** * @brief Tries to present a readable version of the current request values * @retval String */ - String toString(); -#endif + String toString() + { + return toString(*this); + } + + /** + * @brief Tries to present a readable version of the request + * @param req + * + * @retval String + */ + String toString(const HttpRequest& req); public: Url uri; diff --git a/Sming/Core/Network/Http/HttpResponse.cpp b/Sming/Core/Network/Http/HttpResponse.cpp index fce812f60b..a937c73436 100644 --- a/Sming/Core/Network/Http/HttpResponse.cpp +++ b/Sming/Core/Network/Http/HttpResponse.cpp @@ -140,6 +140,27 @@ void HttpResponse::reset() freeStreams(); } +String HttpResponse::toString(const HttpResponse& res) +{ + String content; + content += F("HTTP/1.1 "); + content += res.code; + content += ' '; + content += httpGetStatusText(res.code); + content += " \r\n"; + for(unsigned i = 0; i < res.headers.count(); i++) { + content += res.headers[i]; + } + + if(res.stream != nullptr && res.stream->available() >= 0) { + content += res.headers.toString(HTTP_HEADER_CONTENT_LENGTH, String(res.stream->available())); + } else { + content += "\r\n"; + } + + return content; +} + void HttpResponse::freeStreams() { // Consistency check diff --git a/Sming/Core/Network/Http/HttpResponse.h b/Sming/Core/Network/Http/HttpResponse.h index 818ee20c1d..c4131d7a2a 100644 --- a/Sming/Core/Network/Http/HttpResponse.h +++ b/Sming/Core/Network/Http/HttpResponse.h @@ -145,6 +145,23 @@ class HttpResponse return (code >= HTTP_STATUS_OK && code <= 399); } + /** + * @brief Tries to present a readable version of the current response values + * @retval String + */ + String toString() + { + return toString(*this); + } + + /** + * @brief Tries to present a readable version of the response + * @param res + * + * @retval String + */ + String toString(const HttpResponse& res); + private: void setStream(IDataSourceStream* stream); diff --git a/Sming/Core/Network/IpConnection.cpp b/Sming/Core/Network/IpConnection.cpp new file mode 100644 index 0000000000..2154056caf --- /dev/null +++ b/Sming/Core/Network/IpConnection.cpp @@ -0,0 +1,22 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * IpConnection.cpp + * + ****/ + +#include "IpConnection.h" +#include + +bool IpConnection::joinMulticastGroup(IpAddress localIp, IpAddress multicastIp) +{ + return (igmp_joingroup(localIp, multicastIp) == ERR_OK); +} + +bool IpConnection::leaveMulticastGroup(IpAddress localIp, IpAddress multicastIp) +{ + return (igmp_leavegroup(localIp, multicastIp) == ERR_OK); +} diff --git a/Sming/Core/Network/IpConnection.h b/Sming/Core/Network/IpConnection.h new file mode 100644 index 0000000000..e49cfc1c0e --- /dev/null +++ b/Sming/Core/Network/IpConnection.h @@ -0,0 +1,65 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * IpConnection.h + * + ****/ + +#pragma once + +#include + +/** @defgroup ip IP + * @brief Provides common IP functions + * @ingroup networking + * @{ + */ + +class IpConnection +{ +public: + /** + * @brief Uses IGMP to add a local network interface to multicast group + * @param localIp Address identifying network interface + * @param multicastIp The multicast group address + * + * @retval true on success + */ + bool joinMulticastGroup(IpAddress localIp, IpAddress multicastIp); + + /** + * @brief Uses IGMP to add all local network interfaces to multicast group + * @param multicastIp The multicast group address + * + * @retval true on success + */ + bool joinMulticastGroup(IpAddress multicastIp) + { + return joinMulticastGroup(INADDR_NONE, multicastIp); + } + + /** + * @brief Uses IGMP to remove a local network interface from multicast group + * @param localIp Address identifying network interface + * @param multicastIp The multicast group address + * + * @retval true on success + */ + bool leaveMulticastGroup(IpAddress localIp, IpAddress multicastIp); + + /** + * @brief Uses IGMP to remove all local network interfaces from multicast group + * @param multicastIp The multicast group address + * + * @retval true on success + */ + bool leaveMulticastGroup(IpAddress multicastIp) + { + return leaveMulticastGroup(INADDR_NONE, multicastIp); + } +}; + +/** @} */ diff --git a/Sming/Core/Network/TcpConnection.h b/Sming/Core/Network/TcpConnection.h index bccb42c27c..20223ecd8d 100644 --- a/Sming/Core/Network/TcpConnection.h +++ b/Sming/Core/Network/TcpConnection.h @@ -15,8 +15,8 @@ #pragma once +#include #include -#include #define NETWORK_DEBUG @@ -36,7 +36,7 @@ class TcpConnection; typedef Delegate TcpConnectionDestroyedDelegate; -class TcpConnection +class TcpConnection : public IpConnection { public: TcpConnection(bool autoDestruct) : autoSelfDestruct(autoDestruct) diff --git a/Sming/Core/Network/UdpConnection.cpp b/Sming/Core/Network/UdpConnection.cpp index 4e81085066..d0daf7d29b 100644 --- a/Sming/Core/Network/UdpConnection.cpp +++ b/Sming/Core/Network/UdpConnection.cpp @@ -115,3 +115,23 @@ void UdpConnection::staticOnReceive(void* arg, struct udp_pcb* pcb, struct pbuf* } pbuf_free(p); } + +bool UdpConnection::setMulticast(IpAddress ip) +{ +#if LWIP_MULTICAST_TX_OPTIONS + udp_set_multicast_netif_addr(udp, (ip4_addr_t*)ip); + return true; +#else + return false; +#endif +} + +bool UdpConnection::setMulticastTtl(size_t ttl) +{ +#if LWIP_MULTICAST_TX_OPTIONS + udp_set_multicast_ttl(udp, ttl); + return true; +#else + return false; +#endif +} diff --git a/Sming/Core/Network/UdpConnection.h b/Sming/Core/Network/UdpConnection.h index fb63291c80..f22e687c06 100644 --- a/Sming/Core/Network/UdpConnection.h +++ b/Sming/Core/Network/UdpConnection.h @@ -8,22 +8,22 @@ * ****/ +#pragma once + +#include + /** @defgroup udp UDP * @brief Provides base for UDP clients or services * @ingroup networking * @{ */ -#pragma once - -#include - class UdpConnection; typedef Delegate UdpConnectionDataDelegate; -class UdpConnection +class UdpConnection : public IpConnection { public: UdpConnection() @@ -70,6 +70,27 @@ class UdpConnection return sendTo(remoteIP, remotePort, data.c_str(), data.length()); } + /** + * @brief Sets the UDP multicast IP. + * @param ip + * + * @retval true when LWIP supports this operation, false otherwise + * + * @note This method works only when LWIP is compiled with LWIP_MULTICAST_TX_OPTIONS + */ + bool setMulticast(IpAddress ip); + + /** + * @brief Sets the UDP multicast Time-To-Live(TTL). + * @param ttl - time to live in hops. + * For example if a milticast UDP packet needs to pass through two routes to reach the receiver then the TTL should be set to 2 + * + * @retval true when LWIP supports this operation, false otherwise + * + * @note This method works only when LWIP is compiled with LWIP_MULTICAST_TX_OPTIONS + */ + bool setMulticastTtl(size_t ttl); + protected: virtual void onReceive(pbuf* buf, IpAddress remoteIP, uint16_t remotePort);