source: ntrip/trunk/BNC/bncgetthread.cpp@ 297

Last change on this file since 297 was 297, checked in by mervart, 17 years ago

* empty log message *

File size: 9.0 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters,
3// written by Leos Mervart.
4//
5// Copyright (C) 2006
6// German Federal Agency for Cartography and Geodesy (BKG)
7// http://www.bkg.bund.de
8// Czech Technical University Prague, Department of Advanced Geodesy
9// http://www.fsv.cvut.cz
10//
11// Email: euref-ip@bkg.bund.de
12//
13// This program is free software; you can redistribute it and/or
14// modify it under the terms of the GNU General Public License
15// as published by the Free Software Foundation, version 2.
16//
17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU General Public License for more details.
21//
22// You should have received a copy of the GNU General Public License
23// along with this program; if not, write to the Free Software
24// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26/* -------------------------------------------------------------------------
27 * BKG NTRIP Client
28 * -------------------------------------------------------------------------
29 *
30 * Class: bncGetThread
31 *
32 * Purpose: Thread that retrieves data from NTRIP caster
33 *
34 * Author: L. Mervart
35 *
36 * Created: 24-Dec-2005
37 *
38 * Changes:
39 *
40 * -----------------------------------------------------------------------*/
41
42#include <stdlib.h>
43
44#include <QFile>
45#include <QTextStream>
46#include <QtNetwork>
47
48#include "bncgetthread.h"
49#include "bnctabledlg.h"
50#include "bncapp.h"
51
52#include "RTCM/RTCM2Decoder.h"
53#include "RTCM3/RTCM3Decoder.h"
54#include "RTIGS/RTIGSDecoder.h"
55
56using namespace std;
57
58// Constructor
59////////////////////////////////////////////////////////////////////////////
60bncGetThread::bncGetThread(const QUrl& mountPoint,
61 const QByteArray& format, int iMount) {
62 _decoder = 0;
63 _mountPoint = mountPoint;
64 _staID = mountPoint.path().mid(1).toAscii();
65 _staID_orig = _staID;
66 _format = format;
67 _socket = 0;
68 _timeOut = 20*1000; // 20 seconds
69 _nextSleep = 1; // 1 second
70 _iMount = iMount; // index in mountpoints array
71
72 // Check name conflict
73 // -------------------
74 QSettings settings;
75 QListIterator<QString> it(settings.value("mountPoints").toStringList());
76 int num = 0;
77 int ind = -1;
78 while (it.hasNext()) {
79 ++ind;
80 QStringList hlp = it.next().split(" ");
81 if (hlp.size() <= 1) continue;
82 QUrl url(hlp[0]);
83 if (_mountPoint.path() == url.path()) {
84 if (_iMount > ind) {
85 ++num;
86 }
87 }
88 }
89
90 if (num > 0) {
91 _staID = _staID.left(_staID.length()-1) + QString("%1").arg(num).toAscii();
92 }
93}
94
95// Destructor
96////////////////////////////////////////////////////////////////////////////
97bncGetThread::~bncGetThread() {
98 delete _socket;
99 delete _decoder;
100}
101
102// Connect to Caster, send the Request (static)
103////////////////////////////////////////////////////////////////////////////
104QTcpSocket* bncGetThread::request(const QUrl& mountPoint, int timeOut,
105 QString& msg) {
106
107 // Connect the Socket
108 // ------------------
109 QSettings settings;
110 QString proxyHost = settings.value("proxyHost").toString();
111 int proxyPort = settings.value("proxyPort").toInt();
112
113 QTcpSocket* socket = new QTcpSocket();
114 if ( proxyHost.isEmpty() ) {
115 socket->connectToHost(mountPoint.host(), mountPoint.port());
116 }
117 else {
118 socket->connectToHost(proxyHost, proxyPort);
119 }
120 if (!socket->waitForConnected(timeOut)) {
121 msg += "Connect timeout\n";
122 delete socket;
123 return 0;
124 }
125
126 // Send Request
127 // ------------
128 QByteArray userAndPwd = mountPoint.userName().toAscii() + ":" +
129 mountPoint.password().toAscii();
130
131 QUrl hlp;
132 hlp.setScheme("http");
133 hlp.setHost(mountPoint.host());
134 hlp.setPort(mountPoint.port());
135 hlp.setPath(mountPoint.path());
136
137 QByteArray reqStr;
138 if ( proxyHost.isEmpty() ) {
139 if (hlp.path().indexOf("/") != 0) hlp.setPath("/");
140 reqStr = "GET " + hlp.path().toAscii() +
141 " HTTP/1.0\r\n"
142 "User-Agent: NTRIP BNC 1.0b\r\n"
143 "Authorization: Basic " +
144 userAndPwd.toBase64() + "\r\n\r\n";
145 } else {
146 reqStr = "GET " + hlp.toEncoded() +
147 " HTTP/1.0\r\n"
148 "User-Agent: NTRIP BNC 1.0b\r\n"
149 "Authorization: Basic " +
150 userAndPwd.toBase64() + "\r\n\r\n";
151 }
152
153 msg += reqStr;
154
155 socket->write(reqStr, reqStr.length());
156
157 if (!socket->waitForBytesWritten(timeOut)) {
158 msg += "Write timeout\n";
159 delete socket;
160 return 0;
161 }
162
163 return socket;
164}
165
166// Init Run
167////////////////////////////////////////////////////////////////////////////
168t_irc bncGetThread::initRun() {
169
170 // Send the Request
171 // ----------------
172 QString msg;
173
174 _socket = bncGetThread::request(_mountPoint, _timeOut, msg);
175
176 //// emit(newMessage(msg.toAscii()));
177
178 if (!_socket) {
179 return failure;
180 }
181
182 // Read Caster Response
183 // --------------------
184 _socket->waitForReadyRead(_timeOut);
185 if (_socket->canReadLine()) {
186 QString line = _socket->readLine();
187 if (line.indexOf("Unauthorized") != -1) {
188 QStringList table;
189 bncTableDlg::getFullTable(_mountPoint.host(), _mountPoint.port(), table);
190 QString net;
191 QStringListIterator it(table);
192 while (it.hasNext()) {
193 QString line = it.next();
194 if (line.indexOf("STR") == 0) {
195 QStringList tags = line.split(";");
196 if (tags.at(1) == _staID_orig) {
197 net = tags.at(7);
198 break;
199 }
200 }
201 }
202
203 QString reg;
204 it.toFront();
205 while (it.hasNext()) {
206 QString line = it.next();
207 if (line.indexOf("NET") == 0) {
208 QStringList tags = line.split(";");
209 if (tags.at(1) == net) {
210 reg = tags.at(7);
211 break;
212 }
213 }
214 }
215 emit(newMessage((_staID + ": Caster Response: " + line +
216 " Adjust User-ID and Password Register, see"
217 "\n " + reg).toAscii()));
218 return fatal;
219 }
220 if (line.indexOf("ICY 200 OK") != 0) {
221 emit(newMessage((_staID + ": Wrong Caster Response:\n" + line).toAscii()));
222 return failure;
223 }
224 }
225 else {
226 emit(newMessage(_staID + ": Response Timeout"));
227 return failure;
228 }
229
230 // Instantiate the filter
231 // ----------------------
232 if (!_decoder) {
233 if (_format.indexOf("RTCM_2") != -1) {
234 emit(newMessage("Get Data: " + _staID + " in RTCM 2.x format"));
235 _decoder = new RTCM2Decoder();
236 }
237 else if (_format.indexOf("RTCM_3") != -1) {
238 emit(newMessage("Get Data: " + _staID + " in RTCM 3.0 format"));
239 _decoder = new RTCM3Decoder();
240 }
241 else if (_format.indexOf("RTIGS") != -1) {
242 emit(newMessage("Get Data: " + _staID + " in RTIGS format"));
243 _decoder = new RTIGSDecoder();
244 }
245 else {
246 emit(newMessage(_staID + ": Unknown data format " + _format));
247 return fatal;
248 }
249 }
250 return success;
251}
252
253// Run
254////////////////////////////////////////////////////////////////////////////
255void bncGetThread::run() {
256
257 t_irc irc = initRun();
258
259 if (irc == fatal) {
260 QThread::exit(1);
261 return;
262 }
263 else if (irc != success) {
264 emit(newMessage(_staID + ": initRun failed, reconnecting"));
265 tryReconnect();
266 }
267
268 // Read Incoming Data
269 // ------------------
270 while (true) {
271 try {
272 if (_socket->state() != QAbstractSocket::ConnectedState) {
273 emit(newMessage(_staID + ": Socket not connected, reconnecting"));
274 tryReconnect();
275 }
276
277
278 _socket->waitForReadyRead(_timeOut);
279 qint64 nBytes = _socket->bytesAvailable();
280 if (nBytes > 0) {
281 char* data = new char[nBytes];
282 _socket->read(data, nBytes);
283 _decoder->Decode(data, nBytes);
284 delete data;
285 for (list<Observation*>::iterator it = _decoder->_obsList.begin();
286 it != _decoder->_obsList.end(); it++) {
287 emit newObs(_staID, *it);
288 bool firstObs = (it == _decoder->_obsList.begin());
289 _global_caster->newObs(_staID, _mountPoint, firstObs, *it);
290 }
291 _decoder->_obsList.clear();
292 }
293 else {
294 emit(newMessage(_staID + ": Data Timeout, reconnecting"));
295 tryReconnect();
296 }
297 }
298 catch (const char* msg) {
299 emit(newMessage(_staID + msg));
300 tryReconnect();
301 }
302 }
303}
304
305// Exit
306////////////////////////////////////////////////////////////////////////////
307void bncGetThread::exit(int exitCode) {
308 if (exitCode!= 0) {
309 emit error(_staID);
310 }
311 QThread::exit(exitCode);
312 terminate();
313}
314
315// Try Re-Connect
316////////////////////////////////////////////////////////////////////////////
317void bncGetThread::tryReconnect() {
318 while (1) {
319 delete _socket; _socket = 0;
320 sleep(_nextSleep);
321 if ( initRun() == success ) {
322 break;
323 }
324 else {
325 _nextSleep *= 2;
326 if (_nextSleep > 128) {
327 _nextSleep = 128;
328 }
329 _nextSleep += rand() % 6;
330 }
331 }
332 _nextSleep = 1;
333}
Note: See TracBrowser for help on using the repository browser.