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

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

* empty log message *

File size: 9.1 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// Start Ergaenzung Perlt
94 msleep(100); //sleep 0.1 sec
95//Ende Ergaenzung Perlt
96}
97
98// Destructor
99////////////////////////////////////////////////////////////////////////////
100bncGetThread::~bncGetThread() {
101 delete _socket;
102 delete _decoder;
103}
104
105// Connect to Caster, send the Request (static)
106////////////////////////////////////////////////////////////////////////////
107QTcpSocket* bncGetThread::request(const QUrl& mountPoint, int timeOut,
108 QString& msg) {
109
110 // Connect the Socket
111 // ------------------
112 QSettings settings;
113 QString proxyHost = settings.value("proxyHost").toString();
114 int proxyPort = settings.value("proxyPort").toInt();
115
116 QTcpSocket* socket = new QTcpSocket();
117 if ( proxyHost.isEmpty() ) {
118 socket->connectToHost(mountPoint.host(), mountPoint.port());
119 }
120 else {
121 socket->connectToHost(proxyHost, proxyPort);
122 }
123 if (!socket->waitForConnected(timeOut)) {
124 msg += "Connect timeout\n";
125 delete socket;
126 return 0;
127 }
128
129 // Send Request
130 // ------------
131 QByteArray userAndPwd = mountPoint.userName().toAscii() + ":" +
132 mountPoint.password().toAscii();
133
134 QUrl hlp;
135 hlp.setScheme("http");
136 hlp.setHost(mountPoint.host());
137 hlp.setPort(mountPoint.port());
138 hlp.setPath(mountPoint.path());
139
140 QByteArray reqStr;
141 if ( proxyHost.isEmpty() ) {
142 if (hlp.path().indexOf("/") != 0) hlp.setPath("/");
143 reqStr = "GET " + hlp.path().toAscii() +
144 " HTTP/1.0\r\n"
145 "User-Agent: NTRIP BNC 1.0b\r\n"
146 "Authorization: Basic " +
147 userAndPwd.toBase64() + "\r\n\r\n";
148 } else {
149 reqStr = "GET " + hlp.toEncoded() +
150 " HTTP/1.0\r\n"
151 "User-Agent: NTRIP BNC 1.0b\r\n"
152 "Authorization: Basic " +
153 userAndPwd.toBase64() + "\r\n\r\n";
154 }
155
156 msg += reqStr;
157
158 socket->write(reqStr, reqStr.length());
159
160 if (!socket->waitForBytesWritten(timeOut)) {
161 msg += "Write timeout\n";
162 delete socket;
163 return 0;
164 }
165
166 return socket;
167}
168
169// Init Run
170////////////////////////////////////////////////////////////////////////////
171t_irc bncGetThread::initRun() {
172
173 // Send the Request
174 // ----------------
175 QString msg;
176
177 _socket = bncGetThread::request(_mountPoint, _timeOut, msg);
178
179 //// emit(newMessage(msg.toAscii()));
180
181 if (!_socket) {
182 return failure;
183 }
184
185 // Read Caster Response
186 // --------------------
187 _socket->waitForReadyRead(_timeOut);
188 if (_socket->canReadLine()) {
189 QString line = _socket->readLine();
190 if (line.indexOf("Unauthorized") != -1) {
191 QStringList table;
192 bncTableDlg::getFullTable(_mountPoint.host(), _mountPoint.port(), table);
193 QString net;
194 QStringListIterator it(table);
195 while (it.hasNext()) {
196 QString line = it.next();
197 if (line.indexOf("STR") == 0) {
198 QStringList tags = line.split(";");
199 if (tags.at(1) == _staID_orig) {
200 net = tags.at(7);
201 break;
202 }
203 }
204 }
205
206 QString reg;
207 it.toFront();
208 while (it.hasNext()) {
209 QString line = it.next();
210 if (line.indexOf("NET") == 0) {
211 QStringList tags = line.split(";");
212 if (tags.at(1) == net) {
213 reg = tags.at(7);
214 break;
215 }
216 }
217 }
218 emit(newMessage((_staID + ": Caster Response: " + line +
219 " Adjust User-ID and Password Register, see"
220 "\n " + reg).toAscii()));
221 return fatal;
222 }
223 if (line.indexOf("ICY 200 OK") != 0) {
224 emit(newMessage((_staID + ": Wrong Caster Response:\n" + line).toAscii()));
225 return failure;
226 }
227 }
228 else {
229 emit(newMessage(_staID + ": Response Timeout"));
230 return failure;
231 }
232
233 // Instantiate the filter
234 // ----------------------
235 if (!_decoder) {
236 if (_format.indexOf("RTCM_2") != -1) {
237 emit(newMessage("Get Data: " + _staID + " in RTCM 2.x format"));
238 _decoder = new RTCM2Decoder();
239 }
240 else if (_format.indexOf("RTCM_3") != -1) {
241 emit(newMessage("Get Data: " + _staID + " in RTCM 3.0 format"));
242 _decoder = new RTCM3Decoder();
243 }
244 else if (_format.indexOf("RTIGS") != -1) {
245 emit(newMessage("Get Data: " + _staID + " in RTIGS format"));
246 _decoder = new RTIGSDecoder();
247 }
248 else {
249 emit(newMessage(_staID + ": Unknown data format " + _format));
250 return fatal;
251 }
252 }
253 return success;
254}
255
256// Run
257////////////////////////////////////////////////////////////////////////////
258void bncGetThread::run() {
259
260 t_irc irc = initRun();
261
262 if (irc == fatal) {
263 QThread::exit(1);
264 return;
265 }
266 else if (irc != success) {
267 emit(newMessage(_staID + ": initRun failed, reconnecting"));
268 tryReconnect();
269 }
270
271 // Read Incoming Data
272 // ------------------
273 while (true) {
274 try {
275 if (_socket->state() != QAbstractSocket::ConnectedState) {
276 emit(newMessage(_staID + ": Socket not connected, reconnecting"));
277 tryReconnect();
278 }
279
280
281 _socket->waitForReadyRead(_timeOut);
282 qint64 nBytes = _socket->bytesAvailable();
283 if (nBytes > 0) {
284 char* data = new char[nBytes];
285 _socket->read(data, nBytes);
286 _decoder->Decode(data, nBytes);
287 delete data[];
288 for (list<Observation*>::iterator it = _decoder->_obsList.begin();
289 it != _decoder->_obsList.end(); it++) {
290 emit newObs(_staID, *it);
291 bool firstObs = (it == _decoder->_obsList.begin());
292 _global_caster->newObs(_staID, _mountPoint, firstObs, *it);
293 }
294 _decoder->_obsList.clear();
295 }
296 else {
297 emit(newMessage(_staID + ": Data Timeout, reconnecting"));
298 tryReconnect();
299 }
300 }
301 catch (const char* msg) {
302 emit(newMessage(_staID + msg));
303 tryReconnect();
304 }
305 }
306}
307
308// Exit
309////////////////////////////////////////////////////////////////////////////
310void bncGetThread::exit(int exitCode) {
311 if (exitCode!= 0) {
312 emit error(_staID);
313 }
314 QThread::exit(exitCode);
315 terminate();
316}
317
318// Try Re-Connect
319////////////////////////////////////////////////////////////////////////////
320void bncGetThread::tryReconnect() {
321 while (1) {
322 delete _socket; _socket = 0;
323 sleep(_nextSleep);
324 if ( initRun() == success ) {
325 break;
326 }
327 else {
328 _nextSleep *= 2;
329 if (_nextSleep > 128) {
330 _nextSleep = 128;
331 }
332 _nextSleep += rand() % 6;
333 }
334 }
335 _nextSleep = 1;
336}
Note: See TracBrowser for help on using the repository browser.