Commit f9a1f7440777556e1ee6106ff0e1172aef3d4ed7

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent bd30ad58

Use system_error instead of runtime_error where error codes exist.

hueplusplus/LinHttpHandler.cpp
1 1 /**
2   - \file LinHttpHandler.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
  2 + \file LinHttpHandler.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 18 **/
19 19  
20 20 #include "include/LinHttpHandler.h"
... ... @@ -31,173 +31,185 @@
31 31 #include <stdio.h> // printf, sprintf
32 32 #include <stdlib.h> // exit
33 33 #include <string.h> // functions for C style null-terminated strings
  34 +#include <system_error>
34 35 #include <unistd.h> // read, write, close
35 36  
36 37 class SocketCloser {
37   - public: SocketCloser(int sockFd) :s(sockFd) {}
38   - ~SocketCloser() { close(s); }
39   - private: int s;
  38 +public:
  39 + SocketCloser(int sockFd) : s(sockFd) {}
  40 + ~SocketCloser() { close(s); }
  41 +private:
  42 + int s;
40 43 };
41 44  
42 45 std::string LinHttpHandler::send(const std::string & msg, const std::string & adr, int port) const
43 46 {
44   - // create socket
45   - int socketFD = socket(AF_INET, SOCK_STREAM, 0);
46   -
47   - SocketCloser closeMySocket(socketFD);
48   - if (socketFD < 0)
49   - {
50   - std::cerr << "linHttpHandler: Failed to open socket: " << std::strerror(errno) << "\n";
51   - throw(std::runtime_error("linHttpHandler: Failed to open socket"));
52   - }
53   -
54   - // lookup ip address
55   - hostent *server;
56   - server = gethostbyname(adr.c_str());
57   - if (server == NULL)
58   - {
59   - std::cerr << "linHttpHandler: Failed to find host with address " << adr << ": " << std::strerror(errno) << "\n";
60   - throw(std::runtime_error("linHttpHandler: Failed to find host"));
61   - }
62   -
63   - // fill in the structure
64   - sockaddr_in server_addr;
65   - memset(&server_addr, 0, sizeof(server_addr));
66   - server_addr.sin_family = AF_INET;
67   - server_addr.sin_port = htons(port);
68   - memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length);
69   -
70   - // connect the socket
71   - if (connect(socketFD, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
72   - {
73   - std::cerr << "linHttpHandler: Failed to connect socket: " << std::strerror(errno) << "\n";
74   - throw(std::runtime_error("linHttpHandler: Failed to connect socket"));
75   - }
76   -
77   - // send the request
78   - size_t total = msg.length();
79   - ssize_t sent = 0;
80   - do
81   - {
82   - ssize_t bytes = write(socketFD, msg.c_str() + sent, total - sent);
83   - if (bytes < 0)
84   - {
85   - std::cerr << "linHttpHandler: Failed to write message to socket: " << std::strerror(errno) << "\n";
86   - throw(std::runtime_error("linHttpHandler: Failed to write message to socket"));
87   - }
88   - if (bytes == 0)
89   - {
90   - break;
91   - }
92   - if (bytes)
93   - {
94   - sent += bytes;
95   - }
96   - } while (sent < total);
97   -
98   - // receive the response
99   - std::string response;
100   - total = sizeof(response) - 1;
101   - int received = 0;
102   - char buffer[128] = {};
103   - do
104   - {
105   - ssize_t bytes = read(socketFD, buffer, 127);
106   - if (bytes < 0)
107   - {
108   - std::cerr << "linHttpHandler: Failed to read response from socket: " << std::strerror(errno) << std::endl;
109   - throw(std::runtime_error("linHttpHandler: Failed to read response from socket"));
110   - }
111   - if (bytes == 0)
112   - {
113   - break;
114   - }
115   - if (bytes)
116   - {
117   - received += bytes;
118   - response.append(buffer, bytes);
119   - }
120   - } while (true);
121   -
122   - if (received == total)
123   - {
124   - std::cerr << "LinHttpHandler: Failed to store complete response from socket\n";
125   - throw(std::runtime_error("LinHttpHandler: Failed to store complete response from socket"));
126   - }
127   -
128   - return response;
  47 + // create socket
  48 + int socketFD = socket(AF_INET, SOCK_STREAM, 0);
  49 +
  50 + SocketCloser closeMySocket(socketFD);
  51 + if (socketFD < 0)
  52 + {
  53 + int errCode = errno;
  54 + std::cerr << "LinHttpHandler: Failed to open socket: " << std::strerror(errCode) << "\n";
  55 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: Failed to open socket"));
  56 + }
  57 +
  58 + // lookup ip address
  59 + hostent *server;
  60 + server = gethostbyname(adr.c_str());
  61 + if (server == NULL)
  62 + {
  63 + int errCode = errno;
  64 + std::cerr << "LinHttpHandler: Failed to find host with address " << adr << ": " << std::strerror(errCode) << "\n";
  65 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: gethostbyname"));
  66 + }
  67 +
  68 + // fill in the structure
  69 + sockaddr_in server_addr;
  70 + memset(&server_addr, 0, sizeof(server_addr));
  71 + server_addr.sin_family = AF_INET;
  72 + server_addr.sin_port = htons(port);
  73 + memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length);
  74 +
  75 + // connect the socket
  76 + if (connect(socketFD, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
  77 + {
  78 + int errCode = errno;
  79 + std::cerr << "LinHttpHandler: Failed to connect socket: " << std::strerror(errCode) << "\n";
  80 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: Failed to connect socket"));
  81 + }
  82 +
  83 + // send the request
  84 + size_t total = msg.length();
  85 + ssize_t sent = 0;
  86 + do
  87 + {
  88 + ssize_t bytes = write(socketFD, msg.c_str() + sent, total - sent);
  89 + if (bytes < 0)
  90 + {
  91 + int errCode = errno;
  92 + std::cerr << "LinHttpHandler: Failed to write message to socket: " << std::strerror(errCode) << "\n";
  93 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: Failed to write message to socket"));
  94 + }
  95 + if (bytes == 0)
  96 + {
  97 + break;
  98 + }
  99 + if (bytes)
  100 + {
  101 + sent += bytes;
  102 + }
  103 + } while (sent < total);
  104 +
  105 + // receive the response
  106 + std::string response;
  107 + total = sizeof(response) - 1;
  108 + int received = 0;
  109 + char buffer[128] = {};
  110 + do
  111 + {
  112 + ssize_t bytes = read(socketFD, buffer, 127);
  113 + if (bytes < 0)
  114 + {
  115 + int errCode = errno;
  116 + std::cerr << "LinHttpHandler: Failed to read response from socket: " << std::strerror(errCode) << std::endl;
  117 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: Failed to read response from socket"));
  118 + }
  119 + if (bytes == 0)
  120 + {
  121 + break;
  122 + }
  123 + if (bytes)
  124 + {
  125 + received += bytes;
  126 + response.append(buffer, bytes);
  127 + }
  128 + } while (true);
  129 +
  130 + if (received == total)
  131 + {
  132 + std::cerr << "LinHttpHandler: Failed to store complete response from socket\n";
  133 + throw(std::runtime_error("LinHttpHandler: Failed to store complete response from socket"));
  134 + }
  135 +
  136 + return response;
129 137 }
130 138  
131 139 std::vector<std::string> LinHttpHandler::sendMulticast(const std::string & msg, const std::string & adr, int port, int timeout) const
132 140 {
133   - hostent *server; // host information
134   - sockaddr_in server_addr; // server address
135   -
136   - //fill in the server's address and data
137   - memset((char*)&server_addr, 0, sizeof(server_addr));
138   - server_addr.sin_family = AF_INET;
139   - server_addr.sin_port = htons(port);
140   -
141   - // look up the address of the server given its name
142   - server = gethostbyname(adr.c_str());
143   - if (!server)
144   - {
145   - std::cerr << "linHttpHandler: sendMulticast: Failed to obtain address of " << msg << ": " << std::strerror(errno) << "\n";
146   - throw(std::runtime_error("linHttpHandler: sendMulticast: Failed to obtain address of host"));
147   - }
148   -
149   - // put the host's address into the server address structure
150   - memcpy( (void *)&server_addr.sin_addr, server->h_addr_list[0], server->h_length );
151   -
152   - // create the socket
153   - int socketFD = socket(AF_INET, SOCK_DGRAM, 0);
154   - SocketCloser closeMySendSocket(socketFD);
155   - if (socketFD < 0)
156   - {
157   - std::cerr << "linHttpHandler: sendMulticast: Failed to open socket: " << std::strerror(errno) << "\n";
158   - throw(std::runtime_error("linHttpHandler: sendMulticast: Failed to open socket"));
159   - }
160   -
161   - // send a message to the server
162   - if (sendto(socketFD, msg.c_str(), strlen(msg.c_str()), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
163   - {
164   - std::cerr << "linHttpHandler: sendMulticast: Failed to send message: " << std::strerror(errno) << "\n";
165   - throw(std::runtime_error("linHttpHandler: sendMulticast: Failed to send message"));
166   - }
167   -
168   - std::string response;
169   - char buffer[2048] = {}; // receive buffer
170   - ssize_t bytesReceived = 0;
171   -
172   - std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
173   - while (std::chrono::steady_clock::now() - start < std::chrono::seconds(timeout))
174   - {
175   - bytesReceived = recv(socketFD, &buffer, 2048, MSG_DONTWAIT);
176   - if (bytesReceived < 0)
177   - {
178   - if (errno != EAGAIN && errno != EWOULDBLOCK)
179   - {
180   - std::cerr << "linHttpHandler: sendMulticast: Failed to read response from socket: " << std::strerror(errno) << "\n";
181   - throw(std::runtime_error("linHttpHandler: sendMulticast: Failed to read response from socket"));
182   - }
183   - continue;
184   - }
185   - if (bytesReceived)
186   - {
187   - response.append(buffer, bytesReceived);
188   - }
189   - }
190   -
191   - // construct return vector
192   - std::vector<std::string> returnString;
193   - size_t pos = response.find("\r\n\r\n");
194   - size_t prevpos = 0;
195   - while (pos != std::string::npos)
196   - {
197   - returnString.push_back(response.substr(prevpos, pos-prevpos));
198   - pos += 4;
199   - prevpos = pos;
200   - pos = response.find("\r\n\r\n", pos);
201   - }
202   - return returnString;
  141 + hostent *server; // host information
  142 + sockaddr_in server_addr; // server address
  143 +
  144 + //fill in the server's address and data
  145 + memset((char*)&server_addr, 0, sizeof(server_addr));
  146 + server_addr.sin_family = AF_INET;
  147 + server_addr.sin_port = htons(port);
  148 +
  149 + // look up the address of the server given its name
  150 + server = gethostbyname(adr.c_str());
  151 + if (!server)
  152 + {
  153 + int errCode = errno;
  154 + std::cerr << "LinHttpHandler: sendMulticast: Failed to obtain address of " << msg << ": " << std::strerror(errCode) << "\n";
  155 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: sendMulticast: Failed to obtain address of host"));
  156 + }
  157 +
  158 + // put the host's address into the server address structure
  159 + memcpy((void *)&server_addr.sin_addr, server->h_addr_list[0], server->h_length);
  160 +
  161 + // create the socket
  162 + int socketFD = socket(AF_INET, SOCK_DGRAM, 0);
  163 + SocketCloser closeMySendSocket(socketFD);
  164 + if (socketFD < 0)
  165 + {
  166 + int errCode = errno;
  167 + std::cerr << "LinHttpHandler: sendMulticast: Failed to open socket: " << std::strerror(errCode) << "\n";
  168 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: sendMulticast: Failed to open socket"));
  169 + }
  170 +
  171 + // send a message to the server
  172 + if (sendto(socketFD, msg.c_str(), strlen(msg.c_str()), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
  173 + {
  174 + int errCode = errno;
  175 + std::cerr << "LinHttpHandler: sendMulticast: Failed to send message: " << std::strerror(errCode) << "\n";
  176 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: sendMulticast: Failed to send message"));
  177 + }
  178 +
  179 + std::string response;
  180 + char buffer[2048] = {}; // receive buffer
  181 + ssize_t bytesReceived = 0;
  182 +
  183 + std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
  184 + while (std::chrono::steady_clock::now() - start < std::chrono::seconds(timeout))
  185 + {
  186 + bytesReceived = recv(socketFD, &buffer, 2048, MSG_DONTWAIT);
  187 + if (bytesReceived < 0)
  188 + {
  189 + int errCode = errno;
  190 + if (errCode != EAGAIN && errCode != EWOULDBLOCK)
  191 + {
  192 + std::cerr << "LinHttpHandler: sendMulticast: Failed to read response from socket: " << std::strerror(errCode) << "\n";
  193 + throw(std::system_error(errCode, std::generic_category(), "LinHttpHandler: sendMulticast: Failed to read response from socket"));
  194 + }
  195 + continue;
  196 + }
  197 + if (bytesReceived)
  198 + {
  199 + response.append(buffer, bytesReceived);
  200 + }
  201 + }
  202 +
  203 + // construct return vector
  204 + std::vector<std::string> returnString;
  205 + size_t pos = response.find("\r\n\r\n");
  206 + size_t prevpos = 0;
  207 + while (pos != std::string::npos)
  208 + {
  209 + returnString.push_back(response.substr(prevpos, pos - prevpos));
  210 + pos += 4;
  211 + prevpos = pos;
  212 + pos = response.find("\r\n\r\n", pos);
  213 + }
  214 + return returnString;
203 215 }
... ...
hueplusplus/WinHttpHandler.cpp
... ... @@ -23,239 +23,273 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 23 #include <iostream>
24 24 #include <memory>
25 25 #include <stdio.h>
  26 +#include <system_error>
26 27 #include <ws2tcpip.h>
27 28  
28 29 #pragma comment(lib, "Ws2_32.lib")
29 30  
  31 +namespace
  32 +{
  33 + class AddrInfoFreer
  34 + {
  35 + public:
  36 + explicit AddrInfoFreer(addrinfo* p) : p(p)
  37 + {}
  38 + ~AddrInfoFreer()
  39 + {
  40 + freeaddrinfo(p);
  41 + }
  42 + private:
  43 + addrinfo * p;
  44 + };
  45 + class SocketCloser
  46 + {
  47 + public:
  48 + explicit SocketCloser(SOCKET s) : s(s)
  49 + {}
  50 + ~SocketCloser()
  51 + {
  52 + closesocket(s);
  53 + }
  54 + private:
  55 + SOCKET s;
  56 + };
  57 +}
  58 +
30 59 WinHttpHandler::WinHttpHandler()
31 60 {
32   - // Initialize Winsock
33   - int return_code = WSAStartup(MAKEWORD(2, 2), &wsaData);
34   - if (return_code != 0)
35   - {
36   - std::cerr << "WinHttpHandler: Failed to open socket: " << return_code << std::endl;
37   - throw(std::runtime_error("WinHttpHandler: Failed to open socket"));
38   - }
  61 + // Initialize Winsock
  62 + int return_code = WSAStartup(MAKEWORD(2, 2), &wsaData);
  63 + if (return_code != 0)
  64 + {
  65 + std::cerr << "WinHttpHandler: Failed to open socket: " << return_code << std::endl;
  66 + throw(std::system_error(return_code, std::system_category(), "WinHttpHandler: Failed to open socket"));
  67 + }
39 68 }
40 69  
41 70 WinHttpHandler::~WinHttpHandler()
42 71 {
43   - WSACleanup();
  72 + WSACleanup();
44 73 }
45 74  
46 75 std::string WinHttpHandler::send(const std::string & msg, const std::string & adr, int port) const
47 76 {
48   - struct addrinfo hints = {};
49   - hints.ai_family = AF_INET;
50   - hints.ai_socktype = SOCK_STREAM;
51   - hints.ai_protocol = IPPROTO_TCP;
52   -
53   - // Resolve the server address and port
54   - struct addrinfo *result = nullptr;
55   - if (getaddrinfo(adr.c_str(), std::to_string(port).c_str(), &hints, &result) != 0)
56   - {
57   - std::cerr << "WinHttpHandler: getaddrinfo failed: " << WSAGetLastError() << std::endl;
58   - throw(std::runtime_error("WinHttpHandler: getaddrinfo failed"));
59   - }
60   -
61   - // Attempt to connect to the first address returned by
62   - // the call to getaddrinfo
63   - struct addrinfo *ptr = result;
64   -
65   - // Create a SOCKET for connecting to server
66   - SOCKET connect_socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
67   -
68   - if (connect_socket == INVALID_SOCKET)
69   - {
70   - freeaddrinfo(result);
71   - std::cerr << "WinHttpHandler: Error at socket(): " << WSAGetLastError() << std::endl;
72   - throw(std::runtime_error("WinHttpHandler: Error at socket()"));
73   - }
74   -
75   - // Connect to server.
76   - if (connect(connect_socket, ptr->ai_addr, (int)ptr->ai_addrlen) == SOCKET_ERROR)
77   - {
78   - closesocket(connect_socket);
79   - connect_socket = INVALID_SOCKET;
80   - }
81   -
82   - // Should really try the next address returned by getaddrinfo
83   - // if the connect call failed
84   - // But for this simple example we just free the resources
85   - // returned by getaddrinfo and print an error message
86   -
87   - freeaddrinfo(result);
88   -
89   - if (connect_socket == INVALID_SOCKET)
90   - {
91   - std::cerr << "WinHttpHandler: Unable to connect to server!" << std::endl;
92   - throw(std::runtime_error("WinHttpHandler: Unable to connect to server!"));
93   - }
94   -
95   - // Send an initial buffer
96   - if (::send(connect_socket, msg.c_str(), msg.size(), 0) == SOCKET_ERROR)
97   - {
98   - closesocket(connect_socket);
99   - std::cerr << "WinHttpHandler: send failed: " << WSAGetLastError() << std::endl;
100   - throw(std::runtime_error("WinHttpHandler: send failed"));
101   - }
102   -
103   - // shutdown the connection for sending since no more data will be sent
104   - // the client can still use the ConnectSocket for receiving data
105   - if (shutdown(connect_socket, SD_SEND) == SOCKET_ERROR)
106   - {
107   - closesocket(connect_socket);
108   - std::cerr << "WinHttpHandler: shutdown failed: " << WSAGetLastError() << std::endl;
109   - throw(std::runtime_error("WinHttpHandler: shutdown failed"));
110   - }
111   -
112   - const int recvbuflen = 128;
113   - char recvbuf[recvbuflen];
114   -
115   - // Receive data until the server closes the connection
116   - std::string response;
117   - int res;
118   - do
119   - {
120   - res = recv(connect_socket, recvbuf, recvbuflen, 0);
121   - if (res > 0)
122   - {
123   - //std::cout << "WinHttpHandler: Bytes received: " << res << std::endl;
124   - response.append(recvbuf, res);
125   - }
126   - else if (res == 0)
127   - {
128   - //std::cout << "WinHttpHandler: Connection closed " << std::endl;
129   - }
130   - else
131   - {
132   - closesocket(connect_socket);
133   - std::cerr << "WinHttpHandler: recv failed: " << WSAGetLastError() << std::endl;
134   - throw(std::runtime_error("WinHttpHandler: recv failed"));
135   - }
136   - } while (res > 0);
137   - closesocket(connect_socket);
138   -
139   - return response;
  77 + struct addrinfo hints = {};
  78 + hints.ai_family = AF_INET;
  79 + hints.ai_socktype = SOCK_STREAM;
  80 + hints.ai_protocol = IPPROTO_TCP;
  81 +
  82 + // Resolve the server address and port
  83 + struct addrinfo *result = nullptr;
  84 + if (getaddrinfo(adr.c_str(), std::to_string(port).c_str(), &hints, &result) != 0)
  85 + {
  86 + int err = WSAGetLastError();
  87 + std::cerr << "WinHttpHandler: getaddrinfo failed: " << err << std::endl;
  88 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: getaddrinfo failed"));
  89 + }
  90 + SOCKET connect_socket = INVALID_SOCKET;
  91 + {
  92 + AddrInfoFreer freeResult(result);
  93 +
  94 + // Attempt to connect to the first address returned by
  95 + // the call to getaddrinfo
  96 + struct addrinfo *ptr = result;
  97 +
  98 + // Create a SOCKET for connecting to server
  99 + connect_socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
  100 +
  101 + if (connect_socket == INVALID_SOCKET)
  102 + {
  103 + int err = WSAGetLastError();
  104 + std::cerr << "WinHttpHandler: Error at socket(): " << err << std::endl;
  105 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: Error at socket()"));
  106 + }
  107 +
  108 + // Connect to server.
  109 + if (connect(connect_socket, ptr->ai_addr, (int)ptr->ai_addrlen) == SOCKET_ERROR)
  110 + {
  111 + closesocket(connect_socket);
  112 + connect_socket = INVALID_SOCKET;
  113 + }
  114 +
  115 + // Should really try the next address returned by getaddrinfo
  116 + // if the connect call failed
  117 + // But for this simple example we just free the resources
  118 + // returned by getaddrinfo and print an error message
  119 + }
  120 +
  121 + if (connect_socket == INVALID_SOCKET)
  122 + {
  123 + std::cerr << "WinHttpHandler: Unable to connect to server!" << std::endl;
  124 + throw(std::runtime_error("WinHttpHandler: Unable to connect to server!"));
  125 + }
  126 + SocketCloser closeSocket(connect_socket);
  127 +
  128 + // Send an initial buffer
  129 + if (::send(connect_socket, msg.c_str(), msg.size(), 0) == SOCKET_ERROR)
  130 + {
  131 + int err = WSAGetLastError();
  132 + std::cerr << "WinHttpHandler: send failed: " << err << std::endl;
  133 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: send failed"));
  134 + }
  135 +
  136 + // shutdown the connection for sending since no more data will be sent
  137 + // the client can still use the ConnectSocket for receiving data
  138 + if (shutdown(connect_socket, SD_SEND) == SOCKET_ERROR)
  139 + {
  140 + int err = WSAGetLastError();
  141 + std::cerr << "WinHttpHandler: shutdown failed: " << err << std::endl;
  142 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: shutdown failed"));
  143 + }
  144 +
  145 + const int recvbuflen = 128;
  146 + char recvbuf[recvbuflen];
  147 +
  148 + // Receive data until the server closes the connection
  149 + std::string response;
  150 + int res;
  151 + do
  152 + {
  153 + res = recv(connect_socket, recvbuf, recvbuflen, 0);
  154 + if (res > 0)
  155 + {
  156 + //std::cout << "WinHttpHandler: Bytes received: " << res << std::endl;
  157 + response.append(recvbuf, res);
  158 + }
  159 + else if (res == 0)
  160 + {
  161 + //std::cout << "WinHttpHandler: Connection closed " << std::endl;
  162 + }
  163 + else
  164 + {
  165 + int err = WSAGetLastError();
  166 + std::cerr << "WinHttpHandler: recv failed: " << err << std::endl;
  167 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: recv failed"));
  168 + }
  169 + } while (res > 0);
  170 +
  171 + return response;
140 172 }
141 173  
142 174 std::vector<std::string> WinHttpHandler::sendMulticast(const std::string & msg, const std::string & adr, int port, int timeout) const
143 175 {
144   - struct addrinfo hints = {};
145   - hints.ai_family = AF_INET;
146   - hints.ai_socktype = SOCK_DGRAM;
147   - hints.ai_protocol = IPPROTO_TCP;
148   -
149   - // Resolve the server address and port
150   - struct addrinfo *result = nullptr;
151   - if (getaddrinfo(adr.c_str(), std::to_string(port).c_str(), &hints, &result) != 0)
152   - {
153   - std::cerr << "WinHttpHandler: sendMulticast: getaddrinfo failed: " << WSAGetLastError() << std::endl;
154   - throw(std::runtime_error("WinHttpHandler: sendMulticast: getaddrinfo failed"));
155   - }
156   -
157   - // Attempt to connect to the first address returned by
158   - // the call to getaddrinfo
159   - struct addrinfo *ptr = result;
160   -
161   - // Create a SOCKET for connecting to server
162   - SOCKET connect_socket;
163   - if ((connect_socket = socket(ptr->ai_family, ptr->ai_socktype, 0)) == INVALID_SOCKET)
164   - {
165   - freeaddrinfo(result);
166   - std::cerr << "WinHttpHandler: sendMulticast: Error at socket(): " << WSAGetLastError() << std::endl;
167   - throw(std::runtime_error("WinHttpHandler: sendMulticast: Error at socket()"));
168   - }
169   -
170   - // Fill out source socket's address information.
171   - SOCKADDR_IN source_sin;
172   - source_sin.sin_family = AF_INET;
173   - source_sin.sin_port = htons(0);
174   - source_sin.sin_addr.s_addr = htonl(INADDR_ANY);
175   -
176   - // Associate the source socket's address with the socket, Sock.
177   - if (bind(connect_socket, (struct sockaddr FAR *) &source_sin, sizeof(source_sin)) == SOCKET_ERROR)
178   - {
179   - closesocket(connect_socket);
180   - std::cerr << "WinHttpHandler: sendMulticast: Binding socket failed: " << WSAGetLastError() << std::endl;
181   - throw(std::runtime_error("WinHttpHandler: sendMulticast: Binding socket failed"));
182   - }
183   -
184   - u_long sock_mode = 1;
185   - ioctlsocket(connect_socket, FIONBIO, &sock_mode);
186   -
187   - BOOL bOptVal = TRUE;
188   - setsockopt(connect_socket, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal, sizeof(bOptVal));
189   -
190   - // Set the Time-to-Live of the multicast.
191   - int iOptVal = 1; // for same subnet, but might be increased to 16
192   - if (setsockopt(connect_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char FAR *)&iOptVal, sizeof(int)) == SOCKET_ERROR)
193   - {
194   - closesocket(connect_socket);
195   - std::cerr << "WinHttpHandler: sendMulticast: setsockopt failed: " << WSAGetLastError() << std::endl;
196   - throw(std::runtime_error("WinHttpHandler: sendMulticast: setsockopt failed"));
197   - }
198   -
199   - // Fill out the desination socket's address information.
200   - SOCKADDR_IN dest_sin;
201   - dest_sin.sin_family = AF_INET;
202   - dest_sin.sin_port = htons(port);
203   - dest_sin.sin_addr.s_addr = inet_addr((const char*)ptr->ai_addr);
204   -
205   - // Send a message to the multicasting address.
206   - if (sendto(connect_socket, msg.c_str(), msg.size(), 0, (struct sockaddr FAR *) &dest_sin, sizeof(dest_sin)) == SOCKET_ERROR)
207   - {
208   - closesocket(connect_socket);
209   - std::cerr << "WinHttpHandler: sendMulticast: sendto failed: " << WSAGetLastError() << std::endl;
210   - throw(std::runtime_error("WinHttpHandler: sendMulticast: sendto failed"));
211   - }
212   -
213   - // shutdown the connection for sending since no more data will be sent
214   - // the client can still use the ConnectSocket for receiving data
215   - if (shutdown(connect_socket, SD_SEND) == SOCKET_ERROR)
216   - {
217   - closesocket(connect_socket);
218   - std::cerr << "WinHttpHandler: sendMulticast: shutdown failed: " << WSAGetLastError() << std::endl;
219   - throw(std::runtime_error("WinHttpHandler: sendMulticast: shutdown failed"));
220   - }
221   -
222   - std::string response;
223   - const int recvbuflen = 2048;
224   - char recvbuf[recvbuflen] = {};
225   - int res;
226   - std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
227   - while (std::chrono::steady_clock::now() - start < std::chrono::seconds(timeout))
228   - {
229   - res = recv(connect_socket, recvbuf, recvbuflen, 0);
230   - if (res > 0)
231   - {
232   - //std::cout << "WinHttpHandler: sendMulticast: Bytes received: " << res << std::endl;
233   - response.append(recvbuf, res);
234   - }
235   - else if (res == 0)
236   - {
237   - //std::cout << "WinHttpHandler: sendMulticast: Connection closed " << std::endl;
238   - }
239   - else
240   - {
241   - // No exception here due to non blocking socket
242   - //std::cerr << "sendMulticast: recv failed: " << WSAGetLastError() << std::endl;
243   - //throw(std::runtime_error("recv failed"));
244   - }
245   - }
246   - closesocket(connect_socket); // Is this needed?
247   -
248   - // construct return vector
249   - std::vector<std::string> returnString;
250   - size_t pos = response.find("\r\n\r\n");
251   - size_t prevpos = 0;
252   - while (pos != std::string::npos)
253   - {
254   - returnString.push_back(response.substr(prevpos, pos - prevpos));
255   - pos += 4;
256   - prevpos = pos;
257   - pos = response.find("\r\n\r\n", pos);
258   - }
259   -
260   - return returnString;
  176 + struct addrinfo hints = {};
  177 + hints.ai_family = AF_INET;
  178 + hints.ai_socktype = SOCK_DGRAM;
  179 + hints.ai_protocol = IPPROTO_TCP;
  180 +
  181 + // Resolve the server address and port
  182 + struct addrinfo *result = nullptr;
  183 + if (getaddrinfo(adr.c_str(), std::to_string(port).c_str(), &hints, &result) != 0)
  184 + {
  185 + int err = WSAGetLastError();
  186 + std::cerr << "WinHttpHandler: sendMulticast: getaddrinfo failed: " << err << std::endl;
  187 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: sendMulticast: getaddrinfo failed"));
  188 + }
  189 + AddrInfoFreer freeResult(result);
  190 +
  191 + // Attempt to connect to the first address returned by
  192 + // the call to getaddrinfo
  193 + struct addrinfo *ptr = result;
  194 +
  195 + // Create a SOCKET for connecting to server
  196 + SOCKET connect_socket = socket(ptr->ai_family, ptr->ai_socktype, 0);
  197 + if (connect_socket == INVALID_SOCKET)
  198 + {
  199 + int err = WSAGetLastError();
  200 + std::cerr << "WinHttpHandler: sendMulticast: Error at socket(): " << err << std::endl;
  201 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: sendMulticast: Error at socket()"));
  202 + }
  203 + SocketCloser closeSocket(connect_socket);
  204 +
  205 + // Fill out source socket's address information.
  206 + SOCKADDR_IN source_sin;
  207 + source_sin.sin_family = AF_INET;
  208 + source_sin.sin_port = htons(0);
  209 + source_sin.sin_addr.s_addr = htonl(INADDR_ANY);
  210 +
  211 + // Associate the source socket's address with the socket, Sock.
  212 + if (bind(connect_socket, (struct sockaddr FAR *) &source_sin, sizeof(source_sin)) == SOCKET_ERROR)
  213 + {
  214 + int err = WSAGetLastError();
  215 + std::cerr << "WinHttpHandler: sendMulticast: Binding socket failed: " << err << std::endl;
  216 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: sendMulticast: Binding socket failed"));
  217 + }
  218 +
  219 + u_long sock_mode = 1;
  220 + ioctlsocket(connect_socket, FIONBIO, &sock_mode);
  221 +
  222 + BOOL bOptVal = TRUE;
  223 + setsockopt(connect_socket, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal, sizeof(bOptVal));
  224 +
  225 + // Set the Time-to-Live of the multicast.
  226 + int iOptVal = 1; // for same subnet, but might be increased to 16
  227 + if (setsockopt(connect_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char FAR *)&iOptVal, sizeof(int)) == SOCKET_ERROR)
  228 + {
  229 + int err = WSAGetLastError();
  230 + std::cerr << "WinHttpHandler: sendMulticast: setsockopt failed: " << err << std::endl;
  231 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: sendMulticast: setsockopt failed"));
  232 + }
  233 +
  234 + // Fill out the desination socket's address information.
  235 + SOCKADDR_IN dest_sin;
  236 + dest_sin.sin_family = AF_INET;
  237 + dest_sin.sin_port = htons(port);
  238 + dest_sin.sin_addr.s_addr = inet_addr((const char*)ptr->ai_addr);
  239 +
  240 + // Send a message to the multicasting address.
  241 + if (sendto(connect_socket, msg.c_str(), msg.size(), 0, (struct sockaddr FAR *) &dest_sin, sizeof(dest_sin)) == SOCKET_ERROR)
  242 + {
  243 + int err = WSAGetLastError();
  244 + std::cerr << "WinHttpHandler: sendMulticast: sendto failed: " << WSAGetLastError() << std::endl;
  245 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: sendMulticast: sendto failed"));
  246 + }
  247 +
  248 + // shutdown the connection for sending since no more data will be sent
  249 + // the client can still use the ConnectSocket for receiving data
  250 + if (shutdown(connect_socket, SD_SEND) == SOCKET_ERROR)
  251 + {
  252 + int err = WSAGetLastError();
  253 + std::cerr << "WinHttpHandler: sendMulticast: shutdown failed: " << err << std::endl;
  254 + throw(std::system_error(err, std::system_category(), "WinHttpHandler: sendMulticast: shutdown failed"));
  255 + }
  256 +
  257 + std::string response;
  258 + const int recvbuflen = 2048;
  259 + char recvbuf[recvbuflen] = {};
  260 + int res;
  261 + std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
  262 + while (std::chrono::steady_clock::now() - start < std::chrono::seconds(timeout))
  263 + {
  264 + res = recv(connect_socket, recvbuf, recvbuflen, 0);
  265 + if (res > 0)
  266 + {
  267 + //std::cout << "WinHttpHandler: sendMulticast: Bytes received: " << res << std::endl;
  268 + response.append(recvbuf, res);
  269 + }
  270 + else if (res == 0)
  271 + {
  272 + //std::cout << "WinHttpHandler: sendMulticast: Connection closed " << std::endl;
  273 + }
  274 + else
  275 + {
  276 + // No exception here due to non blocking socket
  277 + //std::cerr << "sendMulticast: recv failed: " << WSAGetLastError() << std::endl;
  278 + //throw(std::runtime_error("recv failed"));
  279 + }
  280 + }
  281 +
  282 + // construct return vector
  283 + std::vector<std::string> returnString;
  284 + size_t pos = response.find("\r\n\r\n");
  285 + size_t prevpos = 0;
  286 + while (pos != std::string::npos)
  287 + {
  288 + returnString.push_back(response.substr(prevpos, pos - prevpos));
  289 + pos += 4;
  290 + prevpos = pos;
  291 + pos = response.find("\r\n\r\n", pos);
  292 + }
  293 +
  294 + return returnString;
261 295 }
... ...