23 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE) 24 #define INVALID_SOCKET (-1) 25 #include <sys/socket.h> 29 #include <sys/types.h> 30 #include <sys/ioctl.h> 32 #include <arpa/inet.h> 33 #include <netinet/in.h> 36 #ifdef MRPT_OS_WINDOWS 51 const string& url,
string& out_content,
string& out_errormsg,
int port,
52 const string& auth_user,
const string& auth_pass,
58 url,
data, out_errormsg, port, auth_user, auth_pass,
59 out_http_responsecode, extra_headers, out_headers, timeout_ms);
61 out_content.resize(
data.size());
68 const string& http_method,
const string& http_send_content,
69 const string& url,
vector_byte& out_content,
string& out_errormsg,
int port,
70 const string& auth_user,
const string& auth_pass,
76 if (out_http_responsecode) *out_http_responsecode = 0;
77 if (out_headers) out_headers->clear();
82 if (0 != ::strncmp(url.c_str(),
"http://", 7))
84 out_errormsg =
"URL must start with 'http://'";
88 string server_addr = url.substr(7);
89 string get_object =
"/";
92 size_t pos = server_addr.find(
"/");
95 out_errormsg =
"Server name not found in URL";
98 if (pos != string::npos)
100 get_object = server_addr.substr(pos);
101 server_addr.resize(pos);
109 sock.
connect(server_addr, port, timeout_ms);
111 catch (std::exception& e)
113 out_errormsg = e.what();
121 if (extra_headers) headers_to_send = *extra_headers;
123 headers_to_send[
"Connection"] =
"close";
125 if (!headers_to_send.
has(
"User-Agent"))
126 headers_to_send[
"User-Agent"] =
"MRPT Library";
130 if (!auth_user.empty())
132 string auth_str = auth_user +
string(
":") + auth_pass;
134 ::memcpy(&
v[0], &auth_str[0], auth_str.size());
139 headers_to_send[
"Authorization"] =
string(
"Basic ") + encoded_str;
142 if (!http_send_content.empty() &&
143 headers_to_send.find(
"Content-Length") == headers_to_send.end())
145 headers_to_send[
"Content-Length"] =
146 mrpt::format(
"%u", (
unsigned int)http_send_content.size());
154 http_method.c_str(), get_object.c_str(), server_addr.c_str());
158 i != headers_to_send.end(); ++i)
170 req += http_send_content;
177 buf.reserve(1 << 14);
179 size_t total_read = 0;
180 bool content_length_read =
false;
181 bool all_headers_read =
false;
182 size_t content_length = 0;
183 size_t content_offset = 0;
190 while (!content_length_read ||
191 total_read < (content_offset + content_length))
198 if (!content_length_read)
204 to_read_now = (content_length + content_offset) - total_read;
208 buf.resize(total_read + to_read_now + 1);
212 sock.
readAsync(&buf[total_read], to_read_now, timeout_ms, 100);
218 if (all_headers_read)
222 out_errormsg =
"Connection to server was lost";
227 if (watchdog.
Tac() > 1e-3 * timeout_ms)
229 out_errormsg =
"Timeout waiting answer from server";
232 std::this_thread::sleep_for(10ms);
238 buf[total_read] =
'\0';
241 if (!all_headers_read)
243 const char* ptr = ::strstr(
244 reinterpret_cast<const char*>(&buf[0]),
"\r\n\r\n");
247 all_headers_read =
true;
248 const size_t pos_dblret = ((
char*)ptr) - (
char*)(&buf[0]);
252 if (!::strncmp(
"HTTP/", (
const char*)&buf[0], 5))
254 http_code = ::atoi((
const char*)&buf[9]);
261 "SOURCETABLE ", (
const char*)&buf[0], 12))
263 http_code = ::atoi((
const char*)&buf[12]);
268 "Server didn't send an HTTP/1.1 answer.";
274 content_offset = pos_dblret + 4;
277 const char* ptr_len = ::strstr(
278 reinterpret_cast<const char*>(&buf[0]),
282 content_length = ::atol(ptr_len + 15);
283 content_length_read =
true;
288 string aux_all_headers;
289 deque<string> lstLines;
290 aux_all_headers.resize(content_offset);
291 ::memcpy(&aux_all_headers[0], &buf[0], content_offset);
294 aux_all_headers,
"\r\n", lstLines);
297 i != lstLines.end(); ++i)
299 const size_t p = i->find(
":");
300 if (
p == string::npos)
continue;
302 const string key = i->substr(0,
p);
303 const string val = i->substr(
p + 2);
304 rx_headers[key] =
val;
311 if (out_http_responsecode) *out_http_responsecode = http_code;
312 if (out_headers) *out_headers = rx_headers;
315 buf.erase(buf.begin(), buf.begin() + content_offset);
318 if (rx_headers.
has(
"Transfer-Encoding") &&
319 rx_headers[
"Transfer-Encoding"] ==
"chunked")
324 while (
index < buf.size())
326 if (buf[
index] ==
'\r' && buf[
index + 1] ==
'\n')
328 buf.erase(buf.begin() +
index, buf.begin() +
index + 2);
332 const char* pCRLF = ::strstr((
const char*)&buf[
index],
"\r\n");
335 const size_t len_substr = ((
char*)pCRLF) - (
char*)(&buf[
index]);
337 string sLen((
const char*)&buf[
index], len_substr);
338 sLen =
string(
"0x") + sLen;
340 unsigned int lenChunk;
341 int fields = ::sscanf(sLen.c_str(),
"%x", &lenChunk);
346 buf.begin() +
index, buf.begin() +
index + len_substr + 2);
359 out_content.swap(buf);
361 if (http_code == 200)
367 out_errormsg =
format(
"HTTP error %i", http_code);
371 catch (std::exception& e)
373 out_errormsg = e.what();
384 const string& url,
vector_byte& out_content,
string& out_errormsg,
int port,
385 const string& auth_user,
const string& auth_pass,
390 "GET",
"", url, out_content, out_errormsg, port, auth_user, auth_pass,
391 out_http_responsecode, extra_headers, out_headers, timeout_ms);
402 const unsigned int timeout_ms)
405 if (server_name.find_first_not_of(
"0123456789. ") == std::string::npos)
408 out_ip = server_name;
416 std::future<std::string> dns_result =
417 std::async(std::launch::async, [&]() {
419 #ifdef MRPT_OS_WINDOWS 422 WORD wVersionRequested = MAKEWORD(2, 0);
424 if (WSAStartup(wVersionRequested, &wsaData))
427 <<
"thread_DNS_solver_async: Error calling WSAStartup";
436 hostent* he = gethostbyname(server_name.c_str());
448 dns_result =
string(inet_ntoa(ADDR));
451 #ifdef MRPT_OS_WINDOWS 457 auto status = dns_result.wait_for(std::chrono::milliseconds(timeout_ms));
459 if (
status == std::future_status::ready)
462 out_ip = dns_result.get();
463 return !out_ip.empty();
477 #ifdef MRPT_OS_WINDOWS 478 const int errnum = WSAGetLastError();
481 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
482 FORMAT_MESSAGE_IGNORE_INSERTS,
483 nullptr, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&
s,
493 MRPT_TODO(
"Modify ping to run on Windows + Test this");
501 string cmd_str =
"ping";
504 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE) 505 string count_arg_str =
"-c " +
num2str(max_attempts);
509 string count_arg_str =
"-n " +
num2str(max_attempts);
512 string redirection_str =
"2>&1";
516 "%s %s %s %s", cmd_str.c_str(), count_arg_str.c_str(),
address.c_str(),
517 redirection_str.c_str());
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
For usage when passing a dynamic number of (numeric) arguments to a function, by name.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
std::vector< uint8_t > vector_byte
void connect(const std::string &remotePartAddress, unsigned short remotePartTCPPort, unsigned int timeout_ms=0)
Establishes a connection with a remote part.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
bool isConnected()
Returns true if this objects represents a successfully connected socket.
#define THROW_EXCEPTION(msg)
void encodeBase64(const vector_byte &inputData, std::string &outString)
Encode a sequence of bytes as a string in base-64.
ERRORCODE_HTTP http_get(const string &url, vector_byte &out_content, string &out_errormsg, int port=80, const string &auth_user=string(), const string &auth_pass=string(), int *out_http_responsecode=nullptr, mrpt::utils::TParameters< string > *extra_headers=nullptr, mrpt::utils::TParameters< string > *out_headers=nullptr, int timeout_ms=1000)
Perform an HTTP GET operation (version for retrieving the data as a vector_byte)
std::string getLastSocketErrorStr()
Returns a description of the last Sockets error.
const Scalar * const_iterator
void Tic()
Starts the stopwatch.
int executeCommand(const std::string &command, std::string *output=NULL, const std::string &mode="r")
Execute Generic Shell Command.
MRPT_TODO("Modify ping to run on Windows + Test this")
ERRORCODE_HTTP
Possible returns from a HTTP request.
bool DNS_resolve_async(const std::string &server_name, std::string &out_ip, const unsigned int timeout_ms=3000)
Resolve a server address by its name, returning its IP address as a string - This method has a timeou...
This class implements a high-performance stopwatch.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
ERRORCODE_HTTP http_request(const string &http_method, const string &http_send_content, const string &url, vector_byte &out_content, string &out_errormsg, int port=80, const string &auth_user=string(), const string &auth_pass=string(), int *out_http_responsecode=nullptr, mrpt::utils::TParameters< string > *extra_headers=nullptr, mrpt::utils::TParameters< string > *out_headers=nullptr, int timeout_ms=1000)
Generic function for HTTP GET & POST methods.
GLsizei const GLchar ** string
void tokenize(const std::string &inString, const std::string &inDelimiters, std::deque< std::string > &outTokens, bool skipBlankTokens=true) noexcept
Tokenizes a string according to a set of delimiting characters.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A TCP socket that can be connected to a TCP server, implementing MRPT's CStream interface for passing...
std::string num2str(T const &value)
Convert number instance to string.
double Tac()
Stops the stopwatch.
A set of useful routines for networking.
bool Ping(const std::string &address, const int &max_attempts, std::string *output_str=NULL)
Ping an IP address.
Serial and networking devices and utilities.
size_t readAsync(void *Buffer, const size_t Count, const int timeoutStart_ms=-1, const int timeoutBetween_ms=-1)
A method for reading from the socket with an optional timeout.
GLsizei GLsizei GLenum GLenum const GLvoid * data
void sendString(const std::string &str)
Writes a string to the socket.
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
bool has(const std::string &s) const