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

Last change on this file since 281 was 280, checked in by mervart, 19 years ago

* empty log message *

File size: 9.0 KB
RevLine 
[280]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.
[35]25
26/* -------------------------------------------------------------------------
[93]27 * BKG NTRIP Client
[35]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
[277]42#include <stdlib.h>
43
[35]44#include <QFile>
45#include <QTextStream>
46#include <QtNetwork>
47
48#include "bncgetthread.h"
[192]49#include "bnctabledlg.h"
[243]50#include "bncapp.h"
[65]51
[243]52#include "RTCM/RTCM2Decoder.h"
[65]53#include "RTCM3/rtcm3.h"
[61]54#include "RTIGS/rtigs.h"
[35]55
56using namespace std;
57
58// Constructor
59////////////////////////////////////////////////////////////////////////////
[278]60bncGetThread::bncGetThread(const QUrl& mountPoint,
61 const QByteArray& format, int iMount) {
[136]62 _decoder = 0;
[35]63 _mountPoint = mountPoint;
[89]64 _staID = mountPoint.path().mid(1).toAscii();
[255]65 _staID_orig = _staID;
[59]66 _format = format;
[35]67 _socket = 0;
[181]68 _timeOut = 20*1000; // 20 seconds
[138]69 _nextSleep = 1; // 1 second
[278]70 _iMount = iMount; // index in mountpoints array
[255]71
72 // Check name conflict
73 // -------------------
74 QSettings settings;
75 QListIterator<QString> it(settings.value("mountPoints").toStringList());
76 int num = 0;
[278]77 int ind = -1;
[255]78 while (it.hasNext()) {
[278]79 ++ind;
[255]80 QStringList hlp = it.next().split(" ");
81 if (hlp.size() <= 1) continue;
82 QUrl url(hlp[0]);
83 if (_mountPoint.path() == url.path()) {
[278]84 if (_iMount > ind) {
85 ++num;
[255]86 }
87 }
88 }
[278]89
90 if (num > 0) {
91 _staID = _staID.left(_staID.length()-1) + QString("%1").arg(num).toAscii();
[255]92 }
[35]93}
94
95// Destructor
96////////////////////////////////////////////////////////////////////////////
97bncGetThread::~bncGetThread() {
98 delete _socket;
[136]99 delete _decoder;
[35]100}
101
102// Connect to Caster, send the Request (static)
103////////////////////////////////////////////////////////////////////////////
[136]104QTcpSocket* bncGetThread::request(const QUrl& mountPoint, int timeOut,
105 QString& msg) {
[35]106
[88]107 // Connect the Socket
108 // ------------------
109 QSettings settings;
110 QString proxyHost = settings.value("proxyHost").toString();
111 int proxyPort = settings.value("proxyPort").toInt();
112
[35]113 QTcpSocket* socket = new QTcpSocket();
114 if ( proxyHost.isEmpty() ) {
[88]115 socket->connectToHost(mountPoint.host(), mountPoint.port());
[35]116 }
117 else {
118 socket->connectToHost(proxyHost, proxyPort);
119 }
120 if (!socket->waitForConnected(timeOut)) {
[82]121 msg += "Connect timeout\n";
[35]122 delete socket;
123 return 0;
124 }
125
126 // Send Request
127 // ------------
[88]128 QByteArray userAndPwd = mountPoint.userName().toAscii() + ":" +
129 mountPoint.password().toAscii();
[92]130
131 QUrl hlp;
132 hlp.setScheme("http");
133 hlp.setHost(mountPoint.host());
134 hlp.setPort(mountPoint.port());
135 hlp.setPath(mountPoint.path());
136
[214]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"
[237]142 "User-Agent: NTRIP BNC 1.0b\r\n"
[214]143 "Authorization: Basic " +
144 userAndPwd.toBase64() + "\r\n\r\n";
145 } else {
146 reqStr = "GET " + hlp.toEncoded() +
147 " HTTP/1.0\r\n"
[237]148 "User-Agent: NTRIP BNC 1.0b\r\n"
[214]149 "Authorization: Basic " +
150 userAndPwd.toBase64() + "\r\n\r\n";
[205]151 }
152
[82]153 msg += reqStr;
[35]154
155 socket->write(reqStr, reqStr.length());
156
157 if (!socket->waitForBytesWritten(timeOut)) {
[82]158 msg += "Write timeout\n";
[35]159 delete socket;
160 return 0;
161 }
162
163 return socket;
164}
165
[136]166// Init Run
[35]167////////////////////////////////////////////////////////////////////////////
[138]168t_irc bncGetThread::initRun() {
[35]169
170 // Send the Request
171 // ----------------
[82]172 QString msg;
[88]173
[136]174 _socket = bncGetThread::request(_mountPoint, _timeOut, msg);
[88]175
[193]176 //// emit(newMessage(msg.toAscii()));
[82]177
[35]178 if (!_socket) {
[138]179 return failure;
[35]180 }
181
182 // Read Caster Response
183 // --------------------
[136]184 _socket->waitForReadyRead(_timeOut);
[35]185 if (_socket->canReadLine()) {
186 QString line = _socket->readLine();
[146]187 if (line.indexOf("Unauthorized") != -1) {
[192]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(";");
[255]196 if (tags.at(1) == _staID_orig) {
[192]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 }
[194]215 emit(newMessage((_staID + ": Caster Response: " + line +
[200]216 " Adjust User-ID and Password Register, see"
[194]217 "\n " + reg).toAscii()));
[192]218 return fatal;
[146]219 }
[35]220 if (line.indexOf("ICY 200 OK") != 0) {
[190]221 emit(newMessage((_staID + ": Wrong Caster Response:\n" + line).toAscii()));
[144]222 return failure;
[35]223 }
224 }
225 else {
[190]226 emit(newMessage(_staID + ": Response Timeout"));
[138]227 return failure;
[35]228 }
229
230 // Instantiate the filter
231 // ----------------------
[136]232 if (!_decoder) {
233 if (_format.indexOf("RTCM_2") != -1) {
234 emit(newMessage("Get Data: " + _staID + " in RTCM 2.x format"));
[243]235 _decoder = new RTCM2Decoder();
[136]236 }
237 else if (_format.indexOf("RTCM_3") != -1) {
238 emit(newMessage("Get Data: " + _staID + " in RTCM 3.0 format"));
239 _decoder = new rtcm3();
240 }
241 else if (_format.indexOf("RTIGS") != -1) {
242 emit(newMessage("Get Data: " + _staID + " in RTIGS format"));
243 _decoder = new rtigs();
244 }
245 else {
[190]246 emit(newMessage(_staID + ": Unknown data format " + _format));
[250]247 return fatal;
[136]248 }
[60]249 }
[138]250 return success;
[136]251}
[59]252
[136]253// Run
254////////////////////////////////////////////////////////////////////////////
255void bncGetThread::run() {
256
[229]257 t_irc irc = initRun();
258
259 if (irc == fatal) {
[192]260 QThread::exit(1);
261 return;
262 }
[229]263 else if (irc != success) {
[190]264 emit(newMessage(_staID + ": initRun failed, reconnecting"));
[138]265 tryReconnect();
266 }
[136]267
[35]268 // Read Incoming Data
269 // ------------------
270 while (true) {
[249]271 try {
272 if (_socket->state() != QAbstractSocket::ConnectedState) {
273 emit(newMessage(_staID + ": Socket not connected, reconnecting"));
274 tryReconnect();
[35]275 }
[249]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);
[258]288 bool firstObs = (it == _decoder->_obsList.begin());
289 _global_caster->newObs(_staID, _mountPoint, firstObs, *it);
[249]290 }
291 _decoder->_obsList.clear();
292 }
293 else {
294 emit(newMessage(_staID + ": Data Timeout, reconnecting"));
295 tryReconnect();
296 }
[35]297 }
[249]298 catch (const char* msg) {
299 emit(newMessage(_staID + msg));
[136]300 tryReconnect();
[35]301 }
302 }
303}
304
305// Exit
306////////////////////////////////////////////////////////////////////////////
307void bncGetThread::exit(int exitCode) {
308 if (exitCode!= 0) {
[88]309 emit error(_staID);
[35]310 }
311 QThread::exit(exitCode);
[148]312 terminate();
[35]313}
[82]314
[136]315// Try Re-Connect
316////////////////////////////////////////////////////////////////////////////
317void bncGetThread::tryReconnect() {
[138]318 while (1) {
319 delete _socket; _socket = 0;
320 sleep(_nextSleep);
321 if ( initRun() == success ) {
322 break;
323 }
324 else {
325 _nextSleep *= 2;
[181]326 if (_nextSleep > 128) {
327 _nextSleep = 128;
[152]328 }
[277]329 _nextSleep += rand() % 6;
[138]330 }
331 }
332 _nextSleep = 1;
[136]333}
Note: See TracBrowser for help on using the repository browser.