Commit 9e554815917bfd7671363baec1d88950498b45ea

Authored by Nodeduino
Committed by Moritz Wirger
1 parent f0b19d95

Add crude windows compatability,

- Rename HttpHandler to linHttpHandler
- Add new winHttpHandler for windows
- Export duplicate functions from win/lin-HttpHandler into IHttpHandler
hueplusplus/include/HttpHandler.h deleted
1 -/**  
2 - \file HttpHandler.h  
3 - Copyright Notice\n  
4 - Copyright (C) 2017 Jan Rogall - developer\n  
5 - Copyright (C) 2017 Moritz Wirger - developer\n  
6 -  
7 - This program is free software; you can redistribute it and/or modify  
8 - it under the terms of the GNU General Public License as published by  
9 - the Free Software Foundation; either version 3 of the License, or  
10 - (at your option) any later version.  
11 - This program is distributed in the hope that it will be useful,  
12 - but WITHOUT ANY WARRANTY; without even the implied warranty of  
13 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
14 - GNU General Public License for more details.  
15 - You should have received a copy of the GNU General Public License  
16 - along with this program; if not, write to the Free Software Foundation,  
17 - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA  
18 -**/  
19 -  
20 -#ifndef _HTTPHANDLER_H  
21 -#define _HTTPHANDLER_H  
22 -  
23 -#include <string>  
24 -#include <vector>  
25 -  
26 -#include "IHttpHandler.h"  
27 -  
28 -#include "json/json.h"  
29 -#include "IHttpHandler.h"  
30 -  
31 -//! Class to handle http requests and multicast requests  
32 -class HttpHandler : public IHttpHandler  
33 -{  
34 -public:  
35 - //! \brief Function that sends a given message to the specified host and returns the response.  
36 - //!  
37 - //! \param msg String that contains the message that is sent to the specified address  
38 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
39 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
40 - //! \return String containing the response of the host  
41 - std::string send(const std::string &msg, const std::string &adr, int port=80) const;  
42 -  
43 - //! \brief Function that sends a given message to the specified host and returns the body of the response.  
44 - //!  
45 - //! Note if no body is found a runtime error is thrown!  
46 - //! \param msg String that contains the message that is sent to the specified address  
47 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
48 - //! \param port Optional integer that specifies the port to which the request is sent. Default is 80  
49 - //! \return String containing the body of the response of the host  
50 - std::string sendGetHTTPBody(const std::string &msg, const std::string &adr, int port = 80) const;  
51 -  
52 - //! \brief Function that sends a multicast request with the specified message.  
53 - //!  
54 - //! \param msg String that contains the request that is sent to the specified address  
55 - //! \param adr Optional String that contains an ip or hostname in dotted decimal notation, default is "239.255.255.250"  
56 - //! \param port Optional integer that specifies the port to which the request is sent. Default is 1900  
57 - //! \param timeout Optional Integer that specifies the timeout of the request in seconds. Default is 5  
58 - //! \return Vector containing strings of each answer received  
59 - std::vector<std::string> sendMulticast(const std::string &msg, const std::string &adr = "239.255.255.250", int port = 1900, int timeout = 5) const;  
60 -  
61 - //! \brief Function that sends a HTTP request with the given method to the specified host and returns the body of the response.  
62 - //!  
63 - //! Note body can also be left empty!  
64 - //! \param method String that contains the HTTP method type e.g. GET, HEAD, POST, PUT, DELETE, ...  
65 - //! \param uri String that contains the uniform resource identifier  
66 - //! \param content_type String that contains the type(MIME) of the body data e.g. "text/html", "application/json", ...  
67 - //! \param body String that contains the data of the request  
68 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
69 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
70 - //! \return String containing the body of the response of the host  
71 - std::string sendHTTPRequest(std::string method, std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const;  
72 -  
73 - //! \brief Function that sends a HTTP GET request to the specified host and returns the body of the response.  
74 - //!  
75 - //! Note body can also be left empty!  
76 - //! \param uri String that contains the uniform resource identifier  
77 - //! \param content_type String that contains the type(MIME) of the body data e.g. "text/html", "application/json", ...  
78 - //! \param body String that contains the data of the request  
79 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
80 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
81 - //! \return String containing the body of the response of the host  
82 - std::string GETString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const;  
83 -  
84 - //! \brief Function that sends a HTTP POST request to the specified host and returns the body of the response.  
85 - //!  
86 - //! Note body can also be left empty!  
87 - //! \param uri String that contains the uniform resource identifier  
88 - //! \param content_type String that contains the type(MIME) of the body data e.g. "text/html", "application/json", ...  
89 - //! \param body String that contains the data of the request  
90 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
91 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
92 - //! \return String containing the body of the response of the host  
93 - std::string POSTString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const;  
94 -  
95 - //! \brief Function that sends a HTTP PUT request to the specified host and returns the body of the response.  
96 - //!  
97 - //! Note body can also be left empty!  
98 - //! \param uri String that contains the uniform resource identifier  
99 - //! \param content_type String that contains the type(MIME) of the body data e.g. "text/html", "application/json", ...  
100 - //! \param body String that contains the data of the request  
101 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
102 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
103 - //! \return String containing the body of the response of the host  
104 - std::string PUTString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const;  
105 -  
106 - //! \brief Function that sends a HTTP DELETE request to the specified host and returns the body of the response.  
107 - //!  
108 - //! Note body can also be left empty!  
109 - //! \param uri String that contains the uniform resource identifier  
110 - //! \param content_type String that contains the type(MIME) of the body data e.g. "text/html", "application/json", ...  
111 - //! \param body String that contains the data of the request  
112 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
113 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
114 - //! \return String containing the body of the response of the host  
115 - std::string DELETEString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const;  
116 -  
117 - //! \brief Function that sends a HTTP GET request to the specified host and returns the body of the response.  
118 - //!  
119 - //! Note body can also be left empty!  
120 - //! \param uri String that contains the uniform resource identifier  
121 - //! \param body Json::Value that contains the data of the request  
122 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
123 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
124 - //! \return Json::Value containing the parsed body of the response of the host  
125 - Json::Value GETJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const;  
126 -  
127 - //! \brief Function that sends a HTTP POST request to the specified host and returns the body of the response.  
128 - //!  
129 - //! Note body can also be left empty!  
130 - //! \param uri String that contains the uniform resource identifier  
131 - //! \param body Json::Value that contains the data of the request  
132 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
133 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
134 - //! \return Json::Value containing the parsed body of the response of the host  
135 - Json::Value POSTJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const;  
136 -  
137 - //! \brief Function that sends a HTTP PUT request to the specified host and returns the body of the response.  
138 - //!  
139 - //! Note body can also be left empty!  
140 - //! \param uri String that contains the uniform resource identifier  
141 - //! \param body Json::Value that contains the data of the request  
142 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
143 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
144 - //! \return Json::Value containing the parsed body of the response of the host  
145 - Json::Value PUTJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const;  
146 -  
147 - //! \brief Function that sends a HTTP DELETE request to the specified host and returns the body of the response.  
148 - //!  
149 - //! Note body can also be left empty!  
150 - //! \param uri String that contains the uniform resource identifier  
151 - //! \param body Json::Value that contains the data of the request  
152 - //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"  
153 - //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80  
154 - //! \return Json::Value containing the parsed body of the response of the host  
155 - Json::Value DELETEJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const;  
156 -};  
157 -  
158 -#endif  
hueplusplus/include/IHttpHandler.h
@@ -20,6 +20,8 @@ @@ -20,6 +20,8 @@
20 #ifndef _IHTTPHANDLER_H 20 #ifndef _IHTTPHANDLER_H
21 #define _IHTTPHANDLER_H 21 #define _IHTTPHANDLER_H
22 22
  23 +#include <iostream>
  24 +#include <memory>
23 #include <string> 25 #include <string>
24 #include <vector> 26 #include <vector>
25 27
@@ -48,7 +50,18 @@ public: @@ -48,7 +50,18 @@ public:
48 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 50 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
49 //! \param port Optional integer that specifies the port to which the request should be sent. Default is 80 51 //! \param port Optional integer that specifies the port to which the request should be sent. Default is 80
50 //! \return String containing the body of the response of the host 52 //! \return String containing the body of the response of the host
51 - virtual std::string sendGetHTTPBody(const std::string &msg, const std::string &adr, int port = 80) const = 0; 53 + virtual std::string sendGetHTTPBody(const std::string &msg, const std::string &adr, int port = 80) const
  54 + {
  55 + std::string response = send(msg, adr, port);
  56 + size_t start = response.find("\r\n\r\n");
  57 + if (start == std::string::npos)
  58 + {
  59 + std::cerr << "Failed to find body in response\n";
  60 + throw(std::runtime_error("Failed to find body in response"));
  61 + }
  62 + response.erase(0, start + 4);
  63 + return response;
  64 + };
52 65
53 //! \brief Virtual function that should send a multicast request with a specified message. 66 //! \brief Virtual function that should send a multicast request with a specified message.
54 //! 67 //!
@@ -69,7 +82,31 @@ public: @@ -69,7 +82,31 @@ public:
69 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 82 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
70 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 83 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
71 //! \return String containing the body of the response of the host 84 //! \return String containing the body of the response of the host
72 - virtual std::string sendHTTPRequest(std::string method, std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const = 0; 85 + virtual std::string sendHTTPRequest(std::string method, std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const
  86 + {
  87 + std::string request;
  88 + // Protocol reference: https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
  89 + // Request-Line
  90 + request.append(method); // Method
  91 + request.append(" "); // Separation
  92 + request.append(uri); // Request-URI
  93 + request.append(" "); // Separation
  94 + request.append("HTTP/1.0"); // HTTP-Version
  95 + request.append("\r\n"); // Ending
  96 + // Entities
  97 + request.append("Content-Type:"); // entity-header
  98 + request.append(" "); // Separation
  99 + request.append(content_type); // media-type
  100 + request.append("\r\n"); // Entity ending
  101 + request.append("Content-Length:"); // entity-header
  102 + request.append(" "); // Separation
  103 + request.append(std::to_string(body.size())); // length
  104 + request.append("\r\n\r\n"); // Entity ending & Request-Line ending
  105 + request.append(body); // message-body
  106 + request.append("\r\n\r\n"); // Ending
  107 +
  108 + return sendGetHTTPBody(request.c_str(), adr, port);
  109 + };
73 110
74 //! \brief Virtual function that should send a HTTP GET request to the specified host and return the body of the response. 111 //! \brief Virtual function that should send a HTTP GET request to the specified host and return the body of the response.
75 //! 112 //!
@@ -80,7 +117,10 @@ public: @@ -80,7 +117,10 @@ public:
80 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 117 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
81 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 118 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
82 //! \return String containing the body of the response of the host 119 //! \return String containing the body of the response of the host
83 - virtual std::string GETString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const = 0; 120 + virtual std::string GETString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const
  121 + {
  122 + return sendHTTPRequest("GET", uri, content_type, body, adr, port);
  123 + };
84 124
85 //! \brief Virtual function that should send a HTTP POST request to the specified host and returns the body of the response. 125 //! \brief Virtual function that should send a HTTP POST request to the specified host and returns the body of the response.
86 //! 126 //!
@@ -91,7 +131,10 @@ public: @@ -91,7 +131,10 @@ public:
91 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 131 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
92 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 132 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
93 //! \return String containing the body of the response of the host 133 //! \return String containing the body of the response of the host
94 - virtual std::string POSTString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const = 0; 134 + virtual std::string POSTString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const
  135 + {
  136 + return sendHTTPRequest("POST", uri, content_type, body, adr, port);
  137 + };
95 138
96 //! \brief Virtual function that should send a HTTP PUT request to the specified host and return the body of the response. 139 //! \brief Virtual function that should send a HTTP PUT request to the specified host and return the body of the response.
97 //! 140 //!
@@ -102,7 +145,10 @@ public: @@ -102,7 +145,10 @@ public:
102 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 145 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
103 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 146 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
104 //! \return String containing the body of the response of the host 147 //! \return String containing the body of the response of the host
105 - virtual std::string PUTString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const = 0; 148 + virtual std::string PUTString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const
  149 + {
  150 + return sendHTTPRequest("PUT", uri, content_type, body, adr, port);
  151 + };
106 152
107 //! \brief Virtual function that should send a HTTP DELETE request to the specified host and return the body of the response. 153 //! \brief Virtual function that should send a HTTP DELETE request to the specified host and return the body of the response.
108 //! 154 //!
@@ -113,7 +159,10 @@ public: @@ -113,7 +159,10 @@ public:
113 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 159 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
114 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 160 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
115 //! \return String containing the body of the response of the host 161 //! \return String containing the body of the response of the host
116 - virtual std::string DELETEString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const = 0; 162 + virtual std::string DELETEString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port=80) const
  163 + {
  164 + return sendHTTPRequest("DELETE", uri, content_type, body, adr, port);
  165 + };
117 166
118 //! \brief Virtual function that should send a HTTP GET request to the specified host and return the body of the response. 167 //! \brief Virtual function that should send a HTTP GET request to the specified host and return the body of the response.
119 //! 168 //!
@@ -123,7 +172,22 @@ public: @@ -123,7 +172,22 @@ public:
123 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 172 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
124 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 173 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
125 //! \return Json::Value containing the parsed body of the response of the host 174 //! \return Json::Value containing the parsed body of the response of the host
126 - virtual Json::Value GETJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const = 0; 175 + virtual Json::Value GETJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const
  176 + {
  177 + std::string response = GETString(uri, "application/json", body.toStyledString(), adr, port);
  178 +
  179 + std::string error;
  180 + Json::Value result;
  181 + Json::CharReaderBuilder builder;
  182 + builder["collectComments"] = false;
  183 + std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(builder.newCharReader());
  184 + if (!reader->parse(response.c_str(), response.c_str() + response.length(), &result, &error))
  185 + {
  186 + std::cout << "Error while parsing JSON in function GETJson() of linHttpHandler: " << error << std::endl;
  187 + throw(std::runtime_error("Error while parsing JSON in function GETJson() of linHttpHandler"));
  188 + }
  189 + return result;
  190 + };
127 191
128 //! \brief Virtual function that should send a HTTP POST request to the specified host and return the body of the response. 192 //! \brief Virtual function that should send a HTTP POST request to the specified host and return the body of the response.
129 //! 193 //!
@@ -133,7 +197,22 @@ public: @@ -133,7 +197,22 @@ public:
133 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 197 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
134 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 198 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
135 //! \return Json::Value containing the parsed body of the response of the host 199 //! \return Json::Value containing the parsed body of the response of the host
136 - virtual Json::Value POSTJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const = 0; 200 + virtual Json::Value POSTJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const
  201 + {
  202 + std::string response = POSTString(uri, "application/json", body.toStyledString(), adr, port);
  203 +
  204 + std::string error;
  205 + Json::Value result;
  206 + Json::CharReaderBuilder builder;
  207 + builder["collectComments"] = false;
  208 + std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(builder.newCharReader());
  209 + if (!reader->parse(response.c_str(), response.c_str() + response.length(), &result, &error))
  210 + {
  211 + std::cout << "Error while parsing JSON in function POSTJson() of linHttpHandler: " << error << std::endl;
  212 + throw(std::runtime_error("Error while parsing JSON in function POSTJson() of linHttpHandler"));
  213 + }
  214 + return result;
  215 + }
137 216
138 //! \brief Virtual function that should send a HTTP PUT request to the specified host and return the body of the response. 217 //! \brief Virtual function that should send a HTTP PUT request to the specified host and return the body of the response.
139 //! 218 //!
@@ -143,7 +222,22 @@ public: @@ -143,7 +222,22 @@ public:
143 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 222 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
144 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 223 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
145 //! \return Json::Value containing the parsed body of the response of the host 224 //! \return Json::Value containing the parsed body of the response of the host
146 - virtual Json::Value PUTJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const = 0; 225 + virtual Json::Value PUTJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const
  226 + {
  227 + std::string response = PUTString(uri, "application/json", body.toStyledString(), adr, port);
  228 +
  229 + std::string error;
  230 + Json::Value result;
  231 + Json::CharReaderBuilder builder;
  232 + builder["collectComments"] = false;
  233 + std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(builder.newCharReader());
  234 + if (!reader->parse(response.c_str(), response.c_str() + response.length(), &result, &error))
  235 + {
  236 + std::cout << "Error while parsing JSON in function PUTJson() of linHttpHandler: " << error << std::endl;
  237 + throw(std::runtime_error("Error while parsing JSON in function PUTJson() of linHttpHandler"));
  238 + }
  239 + return result;
  240 + };
147 241
148 //! \brief Virtual function that should send a HTTP DELETE request to the specified host and return the body of the response. 242 //! \brief Virtual function that should send a HTTP DELETE request to the specified host and return the body of the response.
149 //! 243 //!
@@ -153,7 +247,22 @@ public: @@ -153,7 +247,22 @@ public:
153 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1" 247 //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
154 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80 248 //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
155 //! \return Json::Value containing the parsed body of the response of the host 249 //! \return Json::Value containing the parsed body of the response of the host
156 - virtual Json::Value DELETEJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const = 0; 250 + virtual Json::Value DELETEJson(std::string uri, const Json::Value& body, const std::string &adr, int port=80) const
  251 + {
  252 + std::string response = DELETEString(uri, "application/json", body.toStyledString(), adr, port);
  253 +
  254 + std::string error;
  255 + Json::Value result;
  256 + Json::CharReaderBuilder builder;
  257 + builder["collectComments"] = false;
  258 + std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(builder.newCharReader());
  259 + if (!reader->parse(response.c_str(), response.c_str() + response.length(), &result, &error))
  260 + {
  261 + std::cout << "Error while parsing JSON in function PUTJson() of linHttpHandler: " << error << std::endl;
  262 + throw(std::runtime_error("Error while parsing JSON in function PUTJson() of linHttpHandler"));
  263 + }
  264 + return result;
  265 + };
157 }; 266 };
158 267
159 #endif 268 #endif
hueplusplus/include/linHttpHandler.h 0 โ†’ 100644
  1 +/**
  2 + \file linHttpHandler.h
  3 + Copyright Notice\n
  4 + Copyright (C) 2017 Jan Rogall - developer\n
  5 + Copyright (C) 2017 Moritz Wirger - developer\n
  6 +
  7 + This program is free software; you can redistribute it and/or modify
  8 + it under the terms of the GNU General Public License as published by
  9 + the Free Software Foundation; either version 3 of the License, or
  10 + (at your option) any later version.
  11 + This program is distributed in the hope that it will be useful,
  12 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + GNU General Public License for more details.
  15 + You should have received a copy of the GNU General Public License
  16 + along with this program; if not, write to the Free Software Foundation,
  17 + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18 +**/
  19 +
  20 +#ifndef _LINHTTPHANDLER_H
  21 +#define _LINHTTPHANDLER_H
  22 +
  23 +#include <string>
  24 +#include <vector>
  25 +
  26 +#include "IHttpHandler.h"
  27 +
  28 +#include "json/json.h"
  29 +
  30 +//! Class to handle http requests and multicast requests on linux systems
  31 +class linHttpHandler : public IHttpHandler
  32 +{
  33 +public:
  34 + //! \brief Function that sends a given message to the specified host and returns the response.
  35 + //!
  36 + //! \param msg String that contains the message that is sent to the specified address
  37 + //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
  38 + //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
  39 + //! \return String containing the response of the host
  40 + std::string send(const std::string &msg, const std::string &adr, int port=80) const;
  41 +
  42 + //! \brief Function that sends a multicast request with the specified message.
  43 + //!
  44 + //! \param msg String that contains the request that is sent to the specified address
  45 + //! \param adr Optional String that contains an ip or hostname in dotted decimal notation, default is "239.255.255.250"
  46 + //! \param port Optional integer that specifies the port to which the request is sent. Default is 1900
  47 + //! \param timeout Optional Integer that specifies the timeout of the request in seconds. Default is 5
  48 + //! \return Vector containing strings of each answer received
  49 + std::vector<std::string> sendMulticast(const std::string &msg, const std::string &adr = "239.255.255.250", int port = 1900, int timeout = 5) const;
  50 +};
  51 +
  52 +#endif
hueplusplus/include/winHttpHandler.h 0 โ†’ 100644
  1 +/**
  2 +\file winHttpHandler.h
  3 +Copyright Notice\n
  4 +Copyright (C) 2017 Jan Rogall - developer\n
  5 +Copyright (C) 2017 Moritz Wirger - developer\n
  6 +
  7 +This program is free software; you can redistribute it and/or modify
  8 +it under the terms of the GNU General Public License as published by
  9 +the Free Software Foundation; either version 3 of the License, or
  10 +(at your option) any later version.
  11 +This program is distributed in the hope that it will be useful,
  12 +but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 +GNU General Public License for more details.
  15 +You should have received a copy of the GNU General Public License
  16 +along with this program; if not, write to the Free Software Foundation,
  17 +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18 +**/
  19 +
  20 +#ifndef _WINHTTPHANDLER_H
  21 +#define _WINHTTPHANDLER_H
  22 +
  23 +#include <string>
  24 +#include <vector>
  25 +#include <winsock2.h>
  26 +
  27 +#include "IHttpHandler.h"
  28 +
  29 +#include "json/json.h"
  30 +
  31 +//! Class to handle http requests and multicast requests on windows systems
  32 +class winHttpHandler : public IHttpHandler
  33 +{
  34 +public:
  35 + //! \brief Ctor needed for initializing wsaData
  36 + winHttpHandler();
  37 +
  38 + //! \brief Dtor needed for wsaData cleanup
  39 + ~winHttpHandler();
  40 +
  41 + //! \brief Function that sends a given message to the specified host and returns the response.
  42 + //!
  43 + //! \param msg String that contains the message that is sent to the specified address
  44 + //! \param adr String that contains an ip or hostname in dotted decimal notation like "192.168.2.1"
  45 + //! \param port Optional integer that specifies the port to which the request is sent to. Default is 80
  46 + //! \return String containing the response of the host
  47 + std::string send(const std::string &msg, const std::string &adr, int port = 80) const;
  48 +
  49 + //! \brief Function that sends a multicast request with the specified message.
  50 + //!
  51 + //! \param msg String that contains the request that is sent to the specified address
  52 + //! \param adr Optional String that contains an ip or hostname in dotted decimal notation, default is "239.255.255.250"
  53 + //! \param port Optional integer that specifies the port to which the request is sent. Default is 1900
  54 + //! \param timeout Optional Integer that specifies the timeout of the request in seconds. Default is 5
  55 + //! \return Vector containing strings of each answer received
  56 + std::vector<std::string> sendMulticast(const std::string &msg, const std::string &adr = "239.255.255.250", int port = 1900, int timeout = 5) const;
  57 +
  58 +private:
  59 + WSADATA wsaData;
  60 +};
  61 +
  62 +#endif
hueplusplus/HttpHandler.cpp renamed to hueplusplus/linHttpHandler.cpp 100755 โ†’ 100644
1 /** 1 /**
2 - \file HttpHandler.cpp 2 + \file linHttpHandler.cpp
3 Copyright Notice\n 3 Copyright Notice\n
4 Copyright (C) 2017 Jan Rogall - developer\n 4 Copyright (C) 2017 Jan Rogall - developer\n
5 Copyright (C) 2017 Moritz Wirger - developer\n 5 Copyright (C) 2017 Moritz Wirger - developer\n
@@ -17,7 +17,9 @@ @@ -17,7 +17,9 @@
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 **/ 18 **/
19 19
20 -#include "include/HttpHandler.h" 20 +#include "include/linHttpHandler.h"
  21 +
  22 +#ifndef _MSC_VER
21 23
22 #include <chrono> 24 #include <chrono>
23 #include <netinet/in.h> // struct sockaddr_in, struct sockaddr 25 #include <netinet/in.h> // struct sockaddr_in, struct sockaddr
@@ -38,7 +40,7 @@ class SocketCloser { @@ -38,7 +40,7 @@ class SocketCloser {
38 private: int s; 40 private: int s;
39 }; 41 };
40 42
41 -std::string HttpHandler::send(const std::string & msg, const std::string & adr, int port) const 43 +std::string linHttpHandler::send(const std::string & msg, const std::string & adr, int port) const
42 { 44 {
43 // create socket 45 // create socket
44 int socketFD = socket(AF_INET, SOCK_STREAM, 0); 46 int socketFD = socket(AF_INET, SOCK_STREAM, 0);
@@ -127,20 +129,7 @@ std::string HttpHandler::send(const std::string &amp; msg, const std::string &amp; adr, @@ -127,20 +129,7 @@ std::string HttpHandler::send(const std::string &amp; msg, const std::string &amp; adr,
127 return response; 129 return response;
128 } 130 }
129 131
130 -std::string HttpHandler::sendGetHTTPBody(const std::string & msg, const std::string & adr, int port) const  
131 -{  
132 - std::string response = send(msg, adr, port);  
133 - size_t start = response.find("\r\n\r\n");  
134 - if (start == std::string::npos)  
135 - {  
136 - std::cerr << "Failed to find body in response\n";  
137 - throw(std::runtime_error("Failed to find body in response"));  
138 - }  
139 - response.erase(0, start + 4);  
140 - return response;  
141 -}  
142 -  
143 -std::vector<std::string> HttpHandler::sendMulticast(const std::string & msg, const std::string & adr, int port, int timeout) const 132 +std::vector<std::string> linHttpHandler::sendMulticast(const std::string & msg, const std::string & adr, int port, int timeout) const
144 { 133 {
145 hostent *server; // host information 134 hostent *server; // host information
146 sockaddr_in server_addr; // server address 135 sockaddr_in server_addr; // server address
@@ -219,116 +208,4 @@ std::vector&lt;std::string&gt; HttpHandler::sendMulticast(const std::string &amp; msg, con @@ -219,116 +208,4 @@ std::vector&lt;std::string&gt; HttpHandler::sendMulticast(const std::string &amp; msg, con
219 return returnString; 208 return returnString;
220 } 209 }
221 210
222 -std::string HttpHandler::sendHTTPRequest(std::string method, std::string uri, std::string content_type, std::string body, const std::string &adr, int port) const  
223 -{  
224 - std::string request;  
225 - // Protocol reference: https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html  
226 - // Request-Line  
227 - request.append(method); // Method  
228 - request.append(" "); // Separation  
229 - request.append(uri); // Request-URI  
230 - request.append(" "); // Separation  
231 - request.append("HTTP/1.0"); // HTTP-Version  
232 - request.append("\r\n"); // Ending  
233 - // Entities  
234 - request.append("Content-Type:"); // entity-header  
235 - request.append(" "); // Separation  
236 - request.append(content_type); // media-type  
237 - request.append("\r\n"); // Entity ending  
238 - request.append("Content-Length:"); // entity-header  
239 - request.append(" "); // Separation  
240 - request.append(std::to_string(body.size())); // length  
241 - request.append("\r\n\r\n"); // Entity ending & Request-Line ending  
242 - request.append(body); // message-body  
243 - request.append("\r\n\r\n"); // Ending  
244 -  
245 - return sendGetHTTPBody(request.c_str(), adr, port);  
246 -}  
247 -  
248 -std::string HttpHandler::GETString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port) const  
249 -{  
250 - return sendHTTPRequest("GET", uri, content_type, body, adr, port);  
251 -}  
252 -  
253 -std::string HttpHandler::POSTString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port) const  
254 -{  
255 - return sendHTTPRequest("POST", uri, content_type, body, adr, port);  
256 -}  
257 -  
258 -std::string HttpHandler::PUTString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port) const  
259 -{  
260 - return sendHTTPRequest("PUT", uri, content_type, body, adr, port);  
261 -}  
262 -  
263 -std::string HttpHandler::DELETEString(std::string uri, std::string content_type, std::string body, const std::string &adr, int port) const  
264 -{  
265 - return sendHTTPRequest("DELETE", uri, content_type, body, adr, port);  
266 -}  
267 -  
268 -Json::Value HttpHandler::GETJson(std::string uri, const Json::Value& body, const std::string &adr, int port) const  
269 -{  
270 - std::string response = GETString(uri, "application/json", body.toStyledString(), adr, port);  
271 -  
272 - std::string error;  
273 - Json::Value result;  
274 - Json::CharReaderBuilder builder;  
275 - builder["collectComments"] = false;  
276 - std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(builder.newCharReader());  
277 - if (!reader->parse(response.c_str(), response.c_str() + response.length(), &result, &error))  
278 - {  
279 - std::cout << "Error while parsing JSON in function GETJson() of HttpHandler: " << error << std::endl;  
280 - throw(std::runtime_error("Error while parsing JSON in function GETJson() of HttpHandler"));  
281 - }  
282 - return result;  
283 -}  
284 -  
285 -Json::Value HttpHandler::POSTJson(std::string uri, const Json::Value& body, const std::string &adr, int port) const  
286 -{  
287 - std::string response = POSTString(uri, "application/json", body.toStyledString(), adr, port);  
288 -  
289 - std::string error;  
290 - Json::Value result;  
291 - Json::CharReaderBuilder builder;  
292 - builder["collectComments"] = false;  
293 - std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(builder.newCharReader());  
294 - if (!reader->parse(response.c_str(), response.c_str() + response.length(), &result, &error))  
295 - {  
296 - std::cout << "Error while parsing JSON in function POSTJson() of HttpHandler: " << error << std::endl;  
297 - throw(std::runtime_error("Error while parsing JSON in function POSTJson() of HttpHandler"));  
298 - }  
299 - return result;  
300 -}  
301 -  
302 -Json::Value HttpHandler::PUTJson(std::string uri, const Json::Value& body, const std::string &adr, int port) const  
303 -{  
304 - std::string response = PUTString(uri, "application/json", body.toStyledString(), adr, port);  
305 -  
306 - std::string error;  
307 - Json::Value result;  
308 - Json::CharReaderBuilder builder;  
309 - builder["collectComments"] = false;  
310 - std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(builder.newCharReader());  
311 - if (!reader->parse(response.c_str(), response.c_str() + response.length(), &result, &error))  
312 - {  
313 - std::cout << "Error while parsing JSON in function PUTJson() of HttpHandler: " << error << std::endl;  
314 - throw(std::runtime_error("Error while parsing JSON in function PUTJson() of HttpHandler"));  
315 - }  
316 - return result;  
317 -}  
318 -  
319 -Json::Value HttpHandler::DELETEJson(std::string uri, const Json::Value& body, const std::string &adr, int port) const  
320 -{  
321 - std::string response = DELETEString(uri, "application/json", body.toStyledString(), adr, port);  
322 -  
323 - std::string error;  
324 - Json::Value result;  
325 - Json::CharReaderBuilder builder;  
326 - builder["collectComments"] = false;  
327 - std::unique_ptr<Json::CharReader> reader = std::unique_ptr<Json::CharReader>(builder.newCharReader());  
328 - if (!reader->parse(response.c_str(), response.c_str() + response.length(), &result, &error))  
329 - {  
330 - std::cout << "Error while parsing JSON in function PUTJson() of HttpHandler: " << error << std::endl;  
331 - throw(std::runtime_error("Error while parsing JSON in function PUTJson() of HttpHandler"));  
332 - }  
333 - return result;  
334 -} 211 +#endif
hueplusplus/winHttpHandler.cpp 0 โ†’ 100644
  1 +/**
  2 +\file winHttpHandler.cpp
  3 +Copyright Notice\n
  4 +Copyright (C) 2017 Jan Rogall - developer\n
  5 +Copyright (C) 2017 Moritz Wirger - developer\n
  6 +
  7 +This program is free software; you can redistribute it and/or modify
  8 +it under the terms of the GNU General Public License as published by
  9 +the Free Software Foundation; either version 3 of the License, or
  10 +(at your option) any later version.
  11 +This program is distributed in the hope that it will be useful,
  12 +but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 +GNU General Public License for more details.
  15 +You should have received a copy of the GNU General Public License
  16 +along with this program; if not, write to the Free Software Foundation,
  17 +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18 +**/
  19 +
  20 +#include "include/winHttpHandler.h"
  21 +
  22 +#ifdef _MSC_VER
  23 +
  24 +#include <chrono>
  25 +#include <iostream>
  26 +#include <memory>
  27 +#include <stdio.h>
  28 +#include <ws2tcpip.h>
  29 +
  30 +#pragma comment(lib, "Ws2_32.lib")
  31 +
  32 +winHttpHandler::winHttpHandler()
  33 +{
  34 + // Initialize Winsock
  35 + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
  36 + {
  37 + std::cerr << "Failed to open socket: " << WSAGetLastError() << std::endl;
  38 + throw(std::runtime_error("Failed to open socket"));
  39 + }
  40 +}
  41 +
  42 +winHttpHandler::~winHttpHandler()
  43 +{
  44 + WSACleanup();
  45 +}
  46 +
  47 +std::string winHttpHandler::send(const std::string & msg, const std::string & adr, int port) const
  48 +{
  49 + struct addrinfo *result = nullptr, *ptr = nullptr, hints;
  50 +
  51 + ZeroMemory(&hints, sizeof(hints));
  52 + hints.ai_family = AF_INET;
  53 + hints.ai_socktype = SOCK_STREAM;
  54 + hints.ai_protocol = IPPROTO_TCP;
  55 +
  56 + // Resolve the server address and port
  57 + int res = getaddrinfo(adr.c_str(), std::to_string(port).c_str(), &hints, &result);
  58 + if (res != 0)
  59 + {
  60 + std::cerr << "getaddrinfo failed: " << res << std::endl;
  61 + throw(std::runtime_error("getaddrinfo failed"));
  62 + }
  63 +
  64 + SOCKET connect_socket = INVALID_SOCKET;
  65 +
  66 +
  67 + // Attempt to connect to the first address returned by
  68 + // the call to getaddrinfo
  69 + ptr = result;
  70 +
  71 + // Create a SOCKET for connecting to server
  72 + connect_socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
  73 +
  74 + if (connect_socket == INVALID_SOCKET)
  75 + {
  76 + freeaddrinfo(result);
  77 + std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl;
  78 + throw(std::runtime_error("Error at socket()"));
  79 + }
  80 +
  81 + // Connect to server.
  82 + res = connect(connect_socket, ptr->ai_addr, (int)ptr->ai_addrlen);
  83 + if (res == SOCKET_ERROR)
  84 + {
  85 + closesocket(connect_socket);
  86 + connect_socket = INVALID_SOCKET;
  87 + }
  88 +
  89 + // Should really try the next address returned by getaddrinfo
  90 + // if the connect call failed
  91 + // But for this simple example we just free the resources
  92 + // returned by getaddrinfo and print an error message
  93 +
  94 + freeaddrinfo(result);
  95 +
  96 + if (connect_socket == INVALID_SOCKET)
  97 + {
  98 + std::cerr << "Unable to connect to server!" << std::endl;
  99 + throw(std::runtime_error("Unable to connect to server!"));
  100 + }
  101 +
  102 + // Send an initial buffer
  103 + res = ::send(connect_socket, msg.c_str(), msg.size(), 0);
  104 + if (res == SOCKET_ERROR)
  105 + {
  106 + std::cerr << "send failed: " << WSAGetLastError() << std::endl;
  107 + throw(std::runtime_error("send failed"));
  108 + }
  109 +
  110 + // shutdown the connection for sending since no more data will be sent
  111 + // the client can still use the ConnectSocket for receiving data
  112 + res = shutdown(connect_socket, SD_SEND);
  113 + if (res == SOCKET_ERROR)
  114 + {
  115 + closesocket(connect_socket);
  116 + std::cerr << "shutdown failed: " << WSAGetLastError() << std::endl;
  117 + throw(std::runtime_error("shutdown failed"));
  118 + }
  119 +
  120 + const int recvbuflen = 128;
  121 + char recvbuf[recvbuflen];
  122 +
  123 + // Receive data until the server closes the connection
  124 + std::string response;
  125 + int received = 0;
  126 + do
  127 + {
  128 + res = recv(connect_socket, recvbuf, recvbuflen, 0);
  129 + if (res > 0)
  130 + {
  131 + std::cout << "Bytes received: " << res << std::endl;
  132 + response.append(recvbuf, res);
  133 + }
  134 + else if (res == 0)
  135 + {
  136 + std::cout << "Connection closed " << std::endl;
  137 + }
  138 + else
  139 + {
  140 + std::cerr << "recv failed: " << WSAGetLastError() << std::endl;
  141 + throw(std::runtime_error("recv failed"));
  142 + }
  143 + } while (res > 0);
  144 +
  145 + return response;
  146 +}
  147 +
  148 +std::vector<std::string> winHttpHandler::sendMulticast(const std::string & msg, const std::string & adr, int port, int timeout) const
  149 +{
  150 + struct addrinfo *result = nullptr, *ptr = nullptr, hints;
  151 + SOCKADDR_IN source_sin, dest_sin;
  152 +
  153 + ZeroMemory(&hints, sizeof(hints));
  154 + hints.ai_family = AF_INET;
  155 + hints.ai_socktype = SOCK_DGRAM;
  156 + hints.ai_protocol = IPPROTO_TCP;
  157 +
  158 + // Resolve the server address and port
  159 + int res = getaddrinfo(adr.c_str(), std::to_string(port).c_str(), &hints, &result);
  160 + if (res != 0)
  161 + {
  162 + std::cerr << "sendMulticast: getaddrinfo failed: " << res << std::endl;
  163 + throw(std::runtime_error("getaddrinfo failed"));
  164 + }
  165 +
  166 + SOCKET connect_socket = INVALID_SOCKET;
  167 +
  168 +
  169 + // Attempt to connect to the first address returned by
  170 + // the call to getaddrinfo
  171 + ptr = result;
  172 +
  173 + // Create a SOCKET for connecting to server
  174 + if ((connect_socket = socket(ptr->ai_family, ptr->ai_socktype, 0)) == INVALID_SOCKET)
  175 + {
  176 + freeaddrinfo(result);
  177 + std::cerr << "sendMulticast: Error at socket(): " << WSAGetLastError() << std::endl;
  178 + throw(std::runtime_error("Error at socket()"));
  179 + }
  180 +
  181 + // Fill out source socket's address information.
  182 + source_sin.sin_family = AF_INET;
  183 + source_sin.sin_port = htons(0);
  184 + source_sin.sin_addr.s_addr = htonl(INADDR_ANY);
  185 +
  186 + // Associate the source socket's address with the socket, Sock.
  187 + if (bind(connect_socket, (struct sockaddr FAR *) &source_sin, sizeof(source_sin)) == SOCKET_ERROR)
  188 + {
  189 + closesocket(connect_socket);
  190 + std::cerr << "sendMulticast: Binding socket failed: " << WSAGetLastError() << std::endl;
  191 + throw(std::runtime_error("Binding socket failed"));
  192 + }
  193 +
  194 + u_long sock_mode = 1;
  195 + ioctlsocket(connect_socket, FIONBIO, &sock_mode);
  196 +
  197 + BOOL bOptVal = TRUE;
  198 + setsockopt(connect_socket, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal, sizeof(bOptVal));
  199 +
  200 + // Set the Time-to-Live of the multicast.
  201 + int iOptVal = 64;
  202 + if (setsockopt(connect_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char FAR *)&iOptVal, sizeof(int)) == SOCKET_ERROR)
  203 + {
  204 + closesocket(connect_socket);
  205 + std::cerr << "sendMulticast: setsockopt failed: " << WSAGetLastError() << std::endl;
  206 + throw(std::runtime_error("setsockopt failed"));
  207 + }
  208 +
  209 + // Fill out the desination socket's address information.
  210 + dest_sin.sin_family = AF_INET;
  211 + dest_sin.sin_port = htons(port);
  212 + dest_sin.sin_addr.s_addr = inet_addr((const char*)ptr->ai_addr);
  213 +
  214 + // Send a message to the multicasting address.
  215 + if (sendto(connect_socket, msg.c_str(), msg.size(), 0, (struct sockaddr FAR *) &dest_sin, sizeof(dest_sin)) == SOCKET_ERROR)
  216 + {
  217 + std::cerr << "sendMulticast: sendto failed: " << WSAGetLastError() << std::endl;
  218 + closesocket(connect_socket);
  219 + throw(std::runtime_error("sendto failed"));
  220 + }
  221 +
  222 + // shutdown the connection for sending since no more data will be sent
  223 + // the client can still use the ConnectSocket for receiving data
  224 + res = shutdown(connect_socket, SD_SEND);
  225 + if (res == SOCKET_ERROR)
  226 + {
  227 + closesocket(connect_socket);
  228 + std::cerr << "sendMulticast: shutdown failed: " << WSAGetLastError() << std::endl;
  229 + throw(std::runtime_error("shutdown failed"));
  230 + }
  231 +
  232 + std::string response;
  233 + const int recvbuflen = 2048;
  234 + char recvbuf[recvbuflen] = {};
  235 + std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
  236 + while (std::chrono::steady_clock::now() - start < std::chrono::seconds(timeout))
  237 + {
  238 + res = recv(connect_socket, recvbuf, recvbuflen, 0);
  239 + if (res > 0)
  240 + {
  241 + std::cout << "sendMulticast: Bytes received: " << res << std::endl;
  242 + response.append(recvbuf, res);
  243 + }
  244 + else if (res == 0)
  245 + {
  246 + std::cout << "sendMulticast: Connection closed " << std::endl;
  247 + }
  248 + else
  249 + {
  250 + // No exception here due to non blocking socket
  251 + //std::cerr << "sendMulticast: recv failed: " << WSAGetLastError() << std::endl;
  252 + //throw(std::runtime_error("recv failed"));
  253 + }
  254 + }
  255 + closesocket(connect_socket); // Is this needed?
  256 +
  257 + // construct return vector
  258 + std::vector<std::string> returnString;
  259 + size_t pos = response.find("\r\n\r\n");
  260 + size_t prevpos = 0;
  261 + while (pos != std::string::npos)
  262 + {
  263 + returnString.push_back(response.substr(prevpos, pos - prevpos));
  264 + pos += 4;
  265 + prevpos = pos;
  266 + pos = response.find("\r\n\r\n", pos);
  267 + }
  268 +
  269 + return returnString;
  270 +}
  271 +
  272 +#endif