Main MRPT website > C++ reference for MRPT 1.5.6
CNTRIPClient.cpp
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+ */
9 
10 #include "hwdrivers-precomp.h" // Precompiled headers
11 
14 #include <mrpt/utils/net_utils.h>
15 #include <mrpt/utils/CStringList.h>
16 #include <mrpt/math/wrap2pi.h>
17 
19 
20 
21 using namespace mrpt;
22 using namespace mrpt::utils;
23 using namespace mrpt::system;
24 using namespace mrpt::synch;
25 using namespace mrpt::hwdrivers;
26 using namespace mrpt::math;
27 using namespace std;
28 
29 
30 /* --------------------------------------------------------
31  CNTRIPClient
32  -------------------------------------------------------- */
33 CNTRIPClient::CNTRIPClient() :
34  m_thread(),
35  m_sem_sock_closed(0,1),
36  m_sem_first_connect_done(0,1),
37  m_thread_exit (false),
38  m_thread_do_process(false),
39  m_waiting_answer_connection(false),
40  m_answer_connection(connError),
41  m_args ( )
42 {
44 }
45 
46 /* --------------------------------------------------------
47  ~CNTRIPClient
48  -------------------------------------------------------- */
50 {
51  this->close();
52  if (!m_thread.isClear())
53  {
54  m_thread_exit = true;
56  m_thread.clear();
57  }
58 }
59 
60 
61 /* --------------------------------------------------------
62  close
63  -------------------------------------------------------- */
65 {
67  if (!m_thread_do_process) return;
68  m_thread_do_process = false;
70 }
71 
72 /* --------------------------------------------------------
73  open
74  -------------------------------------------------------- */
75 bool CNTRIPClient::open(const NTRIPArgs &params, string &out_errmsg)
76 {
77  this->close();
78 
79  if (params.mountpoint.empty())
80  {
81  out_errmsg="MOUNTPOINT cannot be empty.";
82  return false;
83  }
84  if (params.server.empty())
85  {
86  out_errmsg="Server address cannot be empty.";
87  return false;
88  }
89 
90  // Try to open it:
93  out_errmsg.clear();
94 
95  m_args = params;
96  m_thread_do_process = true;
97 
98  // Wait until the thread tell us the initial result...
100  {
101  out_errmsg = "Timeout waiting thread response";
102  return false;
103  }
104 
105  switch (m_answer_connection)
106  {
107  case connOk:
108  return true;
109  case connError:
110  out_errmsg = format("Error trying to connect to server '%s'",params.server.c_str());
111  return false;
112  case connUnauthorized:
113  out_errmsg = format("Authentication failed for server '%s'",params.server.c_str());
114  return false;
115 
116  default:
117  out_errmsg = "UNKNOWN m_answer_connection!!";
118  return false;
119  }
120 }
121 
122 
123 /* --------------------------------------------------------
124  THE WORKING THREAD
125  -------------------------------------------------------- */
127 {
128  try
129  {
130  CClientTCPSocket my_sock;
131 
132  bool last_thread_do_process = m_thread_do_process;
133 
134  while (!m_thread_exit)
135  {
136  if (!m_thread_do_process)
137  {
138  if ( my_sock.isConnected() )
139  {
140  // Close connection:
141  try {
142  my_sock.close();
143  } catch (...) {}
144  }
145  else
146  {
147  // Nothing to be done... just wait
148  }
149 
150  if (last_thread_do_process) // Let the waiting caller continue now.
152 
153  last_thread_do_process = m_thread_do_process;
154  mrpt::system::sleep(100);
155  continue;
156  }
157 
158  last_thread_do_process = m_thread_do_process;
159 
160  // We have a mission to do here... is the channel already open??
161 
162  if ( !my_sock.isConnected() )
163  {
164  TConnResult connect_res = connError;
165 
166  vector_byte buf;
167  try
168  {
169  // Nope, it's the first time: get params and try open the connection:
170  stream_data.clear();
171 
172  cout << format("[CNTRIPClient] Trying to connect to %s:%i\n",m_args.server.c_str(),m_args.port);
173 
174  my_sock.connect(m_args.server, m_args.port );
175  if (m_thread_exit) break;
176 
177 
178  // Prepare HTTP request:
179  // -------------------------------------------
180  string req = format("GET /%s HTTP/1.0\r\n",m_args.mountpoint.c_str());
181 
182  if (isalpha(m_args.server[0]))
183  req+=format("Host: %s\r\n",m_args.server.c_str());
184 
185  req+="User-Agent: NTRIP MRPT Library\r\n";
186  req+="Accept: */*\r\n";
187  req+="Connection: close\r\n";
188 
189  // Implement HTTP Basic authentication:
190  // See: http://en.wikipedia.org/wiki/Basic_access_authentication
191  if (!m_args.user.empty())
192  {
193  string auth_str = m_args.user +string(":")+m_args.password;
194  vector_byte v(auth_str.size());
195  ::memcpy(&v[0],&auth_str [0],auth_str .size());
196 
197  string encoded_str;
198  mrpt::system::encodeBase64(v,encoded_str);
199 
200  req+="Authorization: Basic ";
201  req+=encoded_str;
202  req+="\r\n";
203  }
204 
205  // End:
206  req+="\r\n";
207  //cout << req;
208 
209  // Send:
210  my_sock.sendString(req);
211 
212  // Try to read the header of the response:
213  size_t to_read_now = 30;
214  buf.resize(to_read_now);
215  size_t len = my_sock.readAsync(&buf[0],to_read_now, 4000,200);
216 
217  buf.resize(len);
218 
219  if ((len!=0) && my_sock.isConnected())
220  connect_res = connOk;
221  }
222  catch(std::exception &)
223  {
224  //cout << e.what() << endl;
225  connect_res=connError;
226  }
227 
228  // We are not disconnected yet, it's a good thing... anyway, check the answer code:
229  if (!buf.empty())
230  {
231  string resp;
232  resp.resize(buf.size());
233  ::memcpy(&resp[0],&buf[0],buf.size());
234 
235  if (resp.find(" 200 ")==string::npos)
236  {
237  // It's NOT a good response...
238  connect_res = connError;
239 
240  // 401?
241  if (resp.find(" 401 ")!=string::npos)
242  connect_res = connUnauthorized;
243  }
244  }
245 
246 
247  // Signal my caller that the connection is established:
248  // ---------------------------------------------------------------
250  {
252 
253  m_answer_connection = connect_res;
255  }
256 
257  if (connect_res!=connOk)
258  my_sock.close();
259  }
260 
261  // Retry if it was a failed connection.
262  if ( !my_sock.isConnected() )
263  {
264  mrpt::system::sleep(500);
265  continue;
266  }
267 
268  // Read data from the stream and accumulate it in a buffer:
269  // ----------------------------------------------------------------------
270  vector_byte buf;
271  size_t to_read_now = 1000;
272  buf.resize(to_read_now);
273  size_t len = my_sock.readAsync(&buf[0],to_read_now,10,5);
274 
275  buf.resize(len);
276 
277  if (my_sock.isConnected())
278  {
279  // Send data to main buffer:
280  if (stream_data.size()>1024*8)
281  stream_data.clear(); // It seems nobody's reading it...
282 
283  stream_data.appendData( buf );
284  buf.clear();
285  }
286 
287  // Send back data to the server, if so requested:
288  // ------------------------------------------
289  mrpt::vector_byte upload_data;
290  m_upload_data.readAndClear(upload_data);
291  if (!upload_data.empty())
292  {
293  const size_t N = upload_data.size();
294  const size_t nWritten = my_sock.writeAsync( &upload_data[0],N, 1000);
295  if (nWritten!=N)
296  cerr << "*ERROR*: Couldn't write back " << N << " bytes to NTRIP server!.\n";
297  }
298 
300  } // end while
301 
302 
303  } // end try
304  catch(exception &e)
305  {
306  cerr << "[CNTRIPClient] Exception in working thread: " << endl << e.what() << endl;
307  }
308  catch(...)
309  {
310  cerr << "[CNTRIPClient] Runtime exception in working thread." << endl;
311  }
312 
313 } // end working thread
314 
315 
316 /* --------------------------------------------------------
317  retrieveListOfMountpoints
318  -------------------------------------------------------- */
320  TListMountPoints &out_list,
321  string &out_errmsg,
322  const string &server,
323  int port,
324  const string &auth_user,
325  const string &auth_pass)
326 {
327  string content;
328  int http_code;
329  TParameters<string> my_headers;
330 
331  out_list.clear();
332 
334  string("http://")+server,
335  content,
336  out_errmsg,
337  port,
338  auth_user,auth_pass,
339  &http_code,&my_headers,NULL,
340  6000
341  );
342 
343  // Parse contents:
344  if (ret!=net::erOk) return false;
345 
346  CStringList lstLines(content);
347 
348  for (size_t i=0;i<lstLines.size();i++)
349  {
350  const string &lin = lstLines(i);
351  if (lin.size()<5) continue;
352  if (0!=::strncmp("STR;",lin.c_str(),4)) continue;
353 
354  // ok, it's a stream:
355  deque<string> fields;
356  mrpt::system::tokenize(lin,";",fields);
357 
358  if (fields.size()<13)
359  continue;
360 
361  TMountPoint mnt;
362 
363  mnt.mountpoint_name = fields[1];
364  mnt.id = fields[2];
365  mnt.format = fields[3];
366  mnt.format_details = fields[4];
367  mnt.carrier = atoi(fields[5].c_str());
368  mnt.nav_system = fields[6];
369  mnt.network = fields[7];
370  mnt.country_code = fields[8];
371  mnt.latitude = atof(fields[9].c_str());
372  mnt.longitude = atof(fields[10].c_str());
373 
374  // Longitude in range: -180,180
376 
377  mnt.needs_nmea = atoi(fields[11].c_str())!=0;
378  mnt.net_ref_stations = atoi(fields[12].c_str())!=0;
379 
380  if (fields.size()>=19)
381  mnt.extra_info = fields[18];
382 
383  out_list.push_back(mnt);
384  }
385 
386  return true;
387 }
388 
389 
390 /** Enqueues a string to be sent back to the NTRIP server (e.g. GGA frames) */
392 {
393  if (data.empty()) return;
394 
395  mrpt::vector_byte d(data.size());
396  ::memcpy(&d[0],&data[0],data.size());
398 }
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".
Definition: os.cpp:358
const GLdouble * v
Definition: glew.h:1296
bool open(const NTRIPArgs &params, std::string &out_errmsg)
Tries to open a given NTRIP stream and, if successful, launches a thread for continuously reading fro...
ERRORCODE_HTTP
Possible returns from a HTTP request.
Definition: net_utils.h:31
For usage when passing a dynamic number of (numeric) arguments to a function, by name.
Definition: TParameters.h:51
std::vector< uint8_t > vector_byte
Definition: types_simple.h:26
std::list< TMountPoint > TListMountPoints
Used in CNTRIPClient::retrieveListOfMountpoints.
Definition: CNTRIPClient.h:76
void private_ntrip_thread()
The working thread.
static bool retrieveListOfMountpoints(TListMountPoints &out_list, std::string &out_errmsg, const std::string &server, int port=2101, const std::string &auth_user=std::string(), const std::string &auth_pass=std::string())
Connect to a given NTRIP caster and get the list of all available mountpoints and their parameters...
void BASE_IMPEXP encodeBase64(const vector_byte &inputData, std::string &outString)
Encode a sequence of bytes as a string in base-64.
Definition: base64.cpp:27
void close()
Closes the connection.
void sendString(const std::string &str)
Writes a string to the socket.
void readAndClear(vector_byte &d)
Definition: MT_buffer.h:58
A descriptor of one stream in an NTRIP Caster - See CNTRIPClient::retrieveListOfMountpoints.
Definition: CNTRIPClient.h:43
virtual ~CNTRIPClient()
Default destructor.
size_t writeAsync(const void *Buffer, const size_t Count, const int timeout_ms=-1)
A method for writing to the socket with optional timeouts.
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.
mrpt::synch::MT_buffer m_upload_data
Buffer for data to be sent back to the server.
Definition: CNTRIPClient.h:119
void close()
Closes the connection.
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)
Definition: net_utils.cpp:388
mrpt::system::TThreadHandle m_thread
Definition: CNTRIPClient.h:102
A class for storing a list of text lines.
Definition: CStringList.h:32
std::string format
RTCM 2.3, RTCM 3, CMR+, etc...
Definition: CNTRIPClient.h:47
NTRIPArgs m_args
All the parameters for the NTRIP connection.
Definition: CNTRIPClient.h:117
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...
Definition: threads.cpp:57
bool isConnected()
Returns true if this objects represents a successfully connected socket.
std::string country_code
ITA, ESP, DEU,...
Definition: CNTRIPClient.h:52
GLenum GLsizei len
Definition: glew.h:3955
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:21
void release(unsigned int increaseCount=1)
Increments the count of the semaphore by a given amount.
int carrier
0: No carrier phase, 1: L1, 2: L1+L2
Definition: CNTRIPClient.h:49
bool m_thread_do_process
Will be "true" between "open" and "close".
Definition: CNTRIPClient.h:107
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1284
#define DEG2RAD
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:51
TThreadHandle createThreadFromObjectMethod(CLASS *obj, void(CLASS::*func)(PARAM), PARAM param)
Creates a new thread running a non-static method (so it will have access to "this") from another meth...
Definition: threads.h:216
GLsizeiptr size
Definition: glew.h:1586
#define RAD2DEG
void connect(const std::string &remotePartAddress, unsigned short remotePartTCPPort, unsigned int timeout_ms=0)
Establishes a connection with a remote part.
GLsizei const GLcharARB ** string
Definition: glew.h:3293
void appendData(const vector_byte &d)
Definition: MT_buffer.h:51
bool waitForSignal(unsigned int timeout_ms=0)
Blocks until the count of the semaphore to be non-zero.
GLfloat * params
Definition: glew.h:1436
mrpt::synch::CSemaphore m_sem_first_connect_done
Definition: CNTRIPClient.h:104
A TCP socket that can be connected to a TCP server, implementing MRPT's CStream interface for passing...
std::vector< uint8_t > vector_byte
mrpt::synch::MT_buffer stream_data
The buffer with all the bytes so-far read from the NTRIP server stream.
Definition: CNTRIPClient.h:141
mrpt::synch::CSemaphore m_sem_sock_closed
Definition: CNTRIPClient.h:103
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.
The arguments for connecting to a NTRIP stream, used in CNTRIPClient::open.
Definition: CNTRIPClient.h:80
size_t size() const
Returns the number of text lines in the list.
bool isClear() const
Returns true if the handle is uninitialized.
Definition: threads.h:64
void BASE_IMPEXP joinThread(const TThreadHandle &threadHandle)
Waits until the given thread ends.
Definition: threads.cpp:190
void sendBackToServer(const std::string &data)
Enqueues a string to be sent back to the NTRIP server (e.g.



Page generated by Doxygen 1.8.6 for MRPT 1.5.6 Git: 4c65e84 Tue Apr 24 08:18:17 2018 +0200 at mar abr 24 08:26:17 CEST 2018