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 57 const string &auth_user,
58 const string &auth_pass,
59 int *out_http_responsecode,
66 ERRORCODE_HTTP ret =
http_get(url,
data,out_errormsg,port,auth_user,auth_pass,out_http_responsecode,extra_headers,out_headers,timeout_ms);
69 out_content.resize(
data.size());
79 const string & http_method,
80 const string & http_send_content,
85 const string &auth_user,
86 const string &auth_pass,
87 int *out_http_responsecode,
95 if (out_http_responsecode) *out_http_responsecode=0;
96 if (out_headers) out_headers->clear();
101 if (0!=::strncmp(url.c_str(),
"http://",7))
103 out_errormsg=
"URL must start with 'http://'";
107 string server_addr = url.substr(7);
108 string get_object =
"/";
111 size_t pos = server_addr.find(
"/");
114 out_errormsg=
"Server name not found in URL";
117 if (pos!=string::npos)
119 get_object = server_addr.substr(pos);
120 server_addr.resize(pos);
127 sock.
connect(server_addr,port, timeout_ms);
129 catch (std::exception &e) {
130 out_errormsg = e.what();
138 headers_to_send=*extra_headers;
140 headers_to_send[
"Connection"]=
"close";
142 if (!headers_to_send.
has(
"User-Agent"))
143 headers_to_send[
"User-Agent"]=
"MRPT Library";
147 if (!auth_user.empty())
149 string auth_str = auth_user+
string(
":")+auth_pass;
156 headers_to_send[
"Authorization"]=
string(
"Basic ")+encoded_str;
159 if (!http_send_content.empty() && headers_to_send.find(
"Content-Length") == headers_to_send.end())
161 headers_to_send[
"Content-Length"] =
mrpt::format(
"%u", (
unsigned int)http_send_content.size());
170 get_object.c_str(),server_addr.c_str());
185 req += http_send_content;
194 size_t total_read = 0;
195 bool content_length_read =
false;
196 bool all_headers_read =
false;
197 size_t content_length = 0;
198 size_t content_offset = 0;
205 while (!content_length_read || total_read<(content_offset+content_length))
211 if (!content_length_read)
217 to_read_now = (content_length+content_offset) -total_read;
221 buf.resize(total_read+to_read_now+1);
224 size_t len = sock.
readAsync(&buf[total_read],to_read_now, timeout_ms,100);
230 if (all_headers_read)
234 out_errormsg =
"Connection to server was lost";
239 if ( watchdog.
Tac()>1e-3*timeout_ms)
241 out_errormsg =
"Timeout waiting answer from server";
250 buf[total_read]=
'\0';
253 if (!all_headers_read)
255 const char *ptr = ::strstr(reinterpret_cast<const char*>(&buf[0]),
"\r\n\r\n");
258 all_headers_read =
true;
259 const size_t pos_dblret = ((
char*)ptr)-(
char*)(&buf[0]);
263 if (!::strncmp(
"HTTP/",(
const char*)&buf[0], 5))
265 http_code = ::atoi( (
const char*)&buf[9] );
270 if (!::strncmp(
"SOURCETABLE ",(
const char*)&buf[0], 12))
272 http_code = ::atoi( (
const char*)&buf[12] );
276 out_errormsg =
"Server didn't send an HTTP/1.1 answer.";
282 content_offset = pos_dblret + 4;
285 const char *ptr_len = ::strstr(reinterpret_cast<const char*>(&buf[0]),
"Content-Length:");
288 content_length = ::atol( ptr_len+15 );
289 content_length_read =
true;
294 string aux_all_headers;
295 deque<string> lstLines;
296 aux_all_headers.resize(content_offset);
297 ::memcpy( &aux_all_headers[0],&buf[0],content_offset);
303 const size_t p = i->find(
":");
304 if (
p==string::npos)
continue;
306 const string key = i->substr(0,
p);
307 const string val = i->substr(
p+2);
308 rx_headers[key] =
val;
317 if (out_http_responsecode) *out_http_responsecode=http_code;
318 if (out_headers) *out_headers = rx_headers;
321 buf.erase(buf.begin(),buf.begin()+content_offset);
324 if (rx_headers.
has(
"Transfer-Encoding") && rx_headers[
"Transfer-Encoding"]==
"chunked" )
329 while (
index<buf.size())
333 buf.erase(buf.begin()+
index,buf.begin()+
index+2);
337 const char *pCRLF = ::strstr((
const char*)&buf[
index],
"\r\n");
340 const size_t len_substr = ((
char*)pCRLF)-(
char*)(&buf[
index]);
342 string sLen((
const char*)&buf[
index], len_substr);
345 unsigned int lenChunk;
346 int fields = ::sscanf(sLen.c_str(),
"%x",&lenChunk);
350 buf.erase(buf.begin()+
index,buf.begin()+
index+len_substr+2);
363 out_content.swap(buf);
371 out_errormsg =
format(
"HTTP error %i",http_code);
375 catch (std::exception &e) {
376 out_errormsg = e.what();
391 string &out_errormsg,
393 const string &auth_user,
394 const string &auth_pass,
395 int *out_http_responsecode,
401 return http_request(
"GET",
"", url, out_content, out_errormsg, port, auth_user, auth_pass, out_http_responsecode, extra_headers, out_headers, timeout_ms);
411 sem_caller_quitted(0,1),
433 const unsigned int timeout_ms
437 if (server_name.find_first_not_of(
"0123456789. ")==std::string::npos)
440 out_ip = server_name;
447 param.in_servername = server_name;
452 bool res =(
param.sem_solved.waitForSignal(timeout_ms));
454 param.sem_caller_quitted.release();
460 out_ip =
param.out_solved_ip;
461 return !out_ip.empty();
475 #ifdef MRPT_OS_WINDOWS 478 WORD wVersionRequested = MAKEWORD( 2, 0 );
480 if (WSAStartup( wVersionRequested, &wsaData ) )
482 std::cerr <<
"thread_DNS_solver_async: Error calling WSAStartup";
491 hostent *he = gethostbyname(
param.in_servername.c_str() );
499 ::memcpy(&ADDR, he->h_addr,
sizeof(ADDR));
501 dns_result =
string( inet_ntoa(ADDR) );
505 param.out_solved_ip.set( dns_result );
508 param.sem_solved.release();
511 param.sem_caller_quitted.waitForSignal();
513 #ifdef MRPT_OS_WINDOWS 521 #ifdef MRPT_OS_WINDOWS 522 const int errnum = WSAGetLastError();
524 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
526 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
537 MRPT_TODO(
"Modify ping to run on Windows + Test this");
540 const int& max_attempts,
546 string cmd_str =
"ping";
549 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE) 550 string count_arg_str =
"-c " +
num2str(max_attempts);
554 string count_arg_str =
"-n " +
num2str(max_attempts);
557 string redirection_str =
"2>&1";
562 count_arg_str.c_str(),
564 redirection_str.c_str());
synch::CSemaphore sem_caller_quitted
void BASE_IMPEXP memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) MRPT_NO_THROWS
An OS and compiler independent version of "memcpy".
ERRORCODE_HTTP
Possible returns from a HTTP request.
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::vector< uint8_t > vector_byte
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
#define THROW_EXCEPTION(msg)
void BASE_IMPEXP encodeBase64(const vector_byte &inputData, std::string &outString)
Encode a sequence of bytes as a string in base-64.
const Scalar * const_iterator
void sendString(const std::string &str)
Writes a string to the socket.
void Tic()
Starts the stopwatch.
TThreadHandle createThreadRef(void(*func)(T &), T ¶m)
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.
ERRORCODE_HTTP BASE_IMPEXP 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=NULL, mrpt::utils::TParameters< string > *extra_headers=NULL, mrpt::utils::TParameters< string > *out_headers=NULL, int timeout_ms=1000)
Perform an HTTP GET operation (version for retrieving the data as a vector_byte)
int BASE_IMPEXP 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")
void BASE_IMPEXP sleep(int time_ms) MRPT_NO_THROWS
An OS-independent method for sending the current thread to "sleep" for a given period of time...
bool isConnected()
Returns true if this objects represents a successfully connected socket.
std::string BASE_IMPEXP getLastSocketErrorStr()
Returns a description of the last Sockets error.
This class implements a high-performance stopwatch.
A set of useful routines for networking.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
This namespace provides multitask, synchronization utilities.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
GLsizei const GLchar ** string
synch::CSemaphore sem_solved
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string in_servername
void connect(const std::string &remotePartAddress, unsigned short remotePartTCPPort, unsigned int timeout_ms=0)
Establishes a connection with a remote part.
CThreadSafeVariable< std::string > out_solved_ip
This structure contains the information needed to interface the threads API on each platform: ...
bool BASE_IMPEXP Ping(const std::string &address, const int &max_attempts, std::string *output_str=NULL)
Ping an IP address.
bool BASE_IMPEXP 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...
std::string num2str(T const &value)
Convert number instance to string.
double Tac()
Stops the stopwatch.
ERRORCODE_HTTP BASE_IMPEXP 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=NULL, mrpt::utils::TParameters< string > *extra_headers=NULL, mrpt::utils::TParameters< string > *out_headers=NULL, int timeout_ms=1000)
Generic function for HTTP GET & POST methods.
A TCP socket that can be connected to a TCP server, implementing MRPT's CStream interface for passing...
GLsizei GLsizei GLenum GLenum const GLvoid * data
void BASE_IMPEXP tokenize(const std::string &inString, const std::string &inDelimiters, std::deque< std::string > &outTokens, bool skipBlankTokens=true) MRPT_NO_THROWS
Tokenizes a string according to a set of delimiting characters.
A semaphore for inter-thread synchronization.
void thread_DNS_solver_async(TDNSThreadData &dat)
bool has(const std::string &s) const
void BASE_IMPEXP joinThread(const TThreadHandle &threadHandle)
Waits until the given thread ends.