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

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

* empty log message *

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