source: ntrip/trunk/BNC/src/upload/bncuploadcaster.cpp@ 9720

Last change on this file since 9720 was 9720, checked in by stuerze, 2 years ago

minor changes

File size: 11.3 KB
RevLine 
[3172]1/* -------------------------------------------------------------------------
2 * BKG NTRIP Server
3 * -------------------------------------------------------------------------
4 *
5 * Class: bncUploadCaster
6 *
7 * Purpose: Connection to NTRIP Caster
8 *
9 * Author: L. Mervart
10 *
11 * Created: 29-Mar-2011
12 *
[7661]13 * Changes:
[3172]14 *
15 * -----------------------------------------------------------------------*/
16
17#include <math.h>
[7661]18#include "bncuploadcaster.h"
[3172]19#include "bncversion.h"
[5070]20#include "bnccore.h"
[3235]21#include "bnctableitem.h"
[9707]22#include "bncsettings.h"
[9715]23#include "bncsslconfig.h"
[3172]24
25using namespace std;
26
27// Constructor
28////////////////////////////////////////////////////////////////////////////
[9715]29bncUploadCaster::bncUploadCaster(const QString &mountpoint,
30 const QString &outHost, int outPort, const QString &ntripVersion,
31 const QString &userName, const QString &password, int iRow, int rate) {
32 bncSettings settings;
33
34 _mountpoint = mountpoint;
[9707]35 _casterOutHost = outHost;
36 _casterOutPort = outPort;
[9715]37 _ntripVersion = ntripVersion;
38 _userName = userName;
39 _password = password;
40 _outSocket = 0;
41 _sOpenTrial = 0;
42 _iRow = iRow;
43 _rate = rate;
[9707]44
[9715]45 if (_rate < 0) {
[4809]46 _rate = 0;
[9715]47 } else if (_rate > 60) {
[3273]48 _rate = 60;
49 }
[3207]50 _isToBeDeleted = false;
[3235]51
[7661]52 connect(this, SIGNAL(newMessage(QByteArray,bool)),
[9715]53 BNC_CORE, SLOT(slotMessage(const QByteArray,bool)));
[3235]54
[9715]55 if (BNC_CORE->_uploadTableItems.find(_iRow)
56 != BNC_CORE->_uploadTableItems.end()) {
[7661]57 connect(this, SIGNAL(newBytes(QByteArray,double)),
[9715]58 BNC_CORE->_uploadTableItems.value(iRow),
59 SLOT(slotNewBytes(const QByteArray,double)));
[3235]60 }
[9715]61 if (BNC_CORE->_uploadEphTableItems.find(_iRow)
62 != BNC_CORE->_uploadEphTableItems.end()) {
[8733]63 connect(this, SIGNAL(newBytes(QByteArray,double)),
[9715]64 BNC_CORE->_uploadEphTableItems.value(iRow),
65 SLOT(slotNewBytes(const QByteArray,double)));
[8733]66 }
[9714]67
[9715]68 _sslIgnoreErrors = (Qt::CheckState(settings.value("sslIgnoreErrors").toInt())
69 == Qt::Checked);
[9714]70
[9715]71 _proxyOutHost = settings.value("proxyHost").toString();
72 _proxyOutPort = settings.value("proxyPort").toInt();
73 (_proxyOutHost.isEmpty()) ? _proxy = false : _proxy = true;
74
75 _secure = false;
[9714]76 if (_ntripVersion == "2s") {
77 if (!QSslSocket::supportsSsl()) {
[9715]78 emit(newMessage(
79 "For SSL support please install OpenSSL run-time libraries: Ntrip Version 2 is tried",
80 true));
[9714]81 _ntripVersion == "2";
[9715]82 } else {
83 _secure = true;
84 _casterOutPort = 443;
[9714]85 }
86 }
87
[9715]88 if (!_secure && _proxy) {
89 _postExtension = QString("http://%1:%2").arg(_casterOutHost).arg(_casterOutPort);
90 } else {
91 _postExtension = "";
[9714]92 }
[3172]93}
94
[3207]95// Safe Desctructor
96////////////////////////////////////////////////////////////////////////////
97void bncUploadCaster::deleteSafely() {
98 _isToBeDeleted = true;
[3208]99 if (!isRunning()) {
100 delete this;
101 }
[3207]102}
103
[3172]104// Destructor
105////////////////////////////////////////////////////////////////////////////
106bncUploadCaster::~bncUploadCaster() {
[3208]107 if (isRunning()) {
108 wait();
109 }
[7661]110 if (_outSocket) {
111 delete _outSocket;
112 }
[3172]113}
114
[9707]115//
116////////////////////////////////////////////////////////////////////////////
117void bncUploadCaster::slotProxyAuthenticationRequired(const QNetworkProxy&,
[9715]118 QAuthenticator*) {
[9707]119 emit newMessage("slotProxyAuthenticationRequired", true);
120}
121
[9715]122// TSL/SSL
123 ////////////////////////////////////////////////////////////////////////////
124 void bncUploadCaster::slotSslErrors(QList<QSslError> errors) {
[9707]125
[9715]126 QString msg = "SSL Error\n";
127 QSslCertificate cert = _outSocket->sslConfiguration().peerCertificate();
128 if (!cert.isNull() &&
129 cert.issuerInfo(QSslCertificate::OrganizationalUnitName).count() &&
130 cert.issuerInfo(QSslCertificate::Organization).count()) {
[9720]131
[9715]132 msg += QString("Server Certificate Issued by:\n"
133 "%1\n%2\nCannot be verified\n")
[9707]134#if QT_VERSION >= 0x050000
[9715]135 .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName).at(0))
136 .arg(cert.issuerInfo(QSslCertificate::Organization).at(0));
[9707]137#else
[9715]138 .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName))
139 .arg(cert.issuerInfo(QSslCertificate::Organization));
[9707]140#endif
141 }
[9715]142
[9707]143 QListIterator<QSslError> it(errors);
144 while (it.hasNext()) {
145 const QSslError& err = it.next();
146 msg += "\n" + err.errorString();
147 }
[9717]148 emit(newMessage(msg.toLatin1(), true));
[9707]149
[9718]150 if (_sslIgnoreErrors) { cout << "_sslIgnoreErrors" << endl;
151 if (_outSocket) {cout << "no Socket" << endl;
[9717]152 _outSocket->ignoreSslErrors();
[9718]153 } else {
154 cout << "no Socket" << endl;
[9717]155 }
[9715]156 } else {
[9718]157 delete _outSocket;
158 _outSocket = 0;
[9707]159 }
160}
161
[9715]162
[3226]163// Endless Loop
164////////////////////////////////////////////////////////////////////////////
165void bncUploadCaster::run() {
166 while (true) {
167 if (_isToBeDeleted) {
168 QThread::quit();
169 deleteLater();
170 return;
171 }
172 open();
173 if (_outSocket && _outSocket->state() == QAbstractSocket::ConnectedState) {
174 QMutexLocker locker(&_mutex);
[4808]175 if (_outBuffer.size() > 0) {
[9707]176 if (_ntripVersion == "1") {
177 _outSocket->write(_outBuffer);
178 _outSocket->flush();
[9715]179 } else {
180 QString chunkSize = QString("%1").arg(_outBuffer.size(), 0, 16,
181 QLatin1Char('0'));
182 QByteArray chunkedData = chunkSize.toLatin1() + "\r\n" + _outBuffer
183 + "\r\n";
[9707]184 _outSocket->write(chunkedData);
185 _outSocket->flush();
186 }
[8204]187 emit newBytes(_mountpoint.toLatin1(), _outBuffer.size());
[4808]188 }
[3226]189 }
[4809]190 if (_rate == 0) {
[4985]191 {
192 QMutexLocker locker(&_mutex);
193 _outBuffer.clear();
194 }
[8708]195 msleep(100); //sleep 0.1 sec
[9715]196 } else {
[4809]197 sleep(_rate);
198 }
[3226]199 }
200}
201
[3172]202// Start the Communication with NTRIP Caster
203////////////////////////////////////////////////////////////////////////////
204void bncUploadCaster::open() {
[9715]205 const int timeOut = 5000; // 5 seconds
[9717]206 bncSslConfig sslConfig;
[9715]207 QByteArray msg;
[3172]208
[9717]209
[3172]210 if (_mountpoint.isEmpty()) {
211 return;
212 }
213
[9712]214 if (_outSocket != 0) {
215 if (_outSocket->state() == QAbstractSocket::ConnectedState) {
216 return;
[9715]217 } else {
218 emit(newMessage(
219 "Broadcaster: No connection for " + _mountpoint.toLatin1(), true));
[9712]220 }
[3172]221 }
[9715]222 delete _outSocket;
223 _outSocket = 0;
[9712]224
[9715]225 double minDt = pow(2.0, _sOpenTrial);
[3172]226 if (++_sOpenTrial > 4) {
227 _sOpenTrial = 4;
228 }
[9715]229 if (_outSocketOpenTime.isValid()
230 && _outSocketOpenTime.secsTo(QDateTime::currentDateTime()) < minDt) {
[3172]231 return;
[9715]232 } else {
[3172]233 _outSocketOpenTime = QDateTime::currentDateTime();
234 }
235
[9707]236 _outSocket = new QSslSocket();
[9717]237
[9715]238 _outSocket->setSslConfiguration(sslConfig);
[9714]239 _outSocket->setProxy(QNetworkProxy::NoProxy);
[9715]240
[9714]241 if (_proxy) {
[9715]242 if (_ntripVersion == "1") {
243 emit(newMessage("No proxy support in Ntrip Version 1 upload!", true));
[9713]244 delete _outSocket;
245 _outSocket = 0;
246 return;
247 }
[9715]248 connect(_outSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
249 this,SLOT(slotProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
250
251 if (!connectToHost(_proxyOutHost, _proxyOutPort, false)) {
252 return;
253 }
254
255 if (_secure) {
256 msg = "CONNECT " + _casterOutHost.toLatin1() + ":"
257 + QString("%1").arg(_casterOutPort).toLatin1() + " HTTP/1.1\r\n"
258 + "Proxy-Connection: Keep-Alive\r\n"
259 + "Host: " + _casterOutHost.toLatin1() + "\r\n"
260 + "User-Agent: NTRIP BNC/" BNCVERSION " (" + BNC_OS + ")\r\n"
261 + "\r\n"; cout << msg.toStdString().c_str();
262 _outSocket->write(msg);
263 _outSocket->waitForBytesWritten();
264 _outSocket->waitForReadyRead();
265 QByteArray ans = _outSocket->readLine(); cout << ans.toStdString().c_str() << endl;
266 if (ans.indexOf("200") == -1) {
267 emit(newMessage(
268 "Proxy: Connection broken for " + _mountpoint.toLatin1()
269 + ": " + ans.left(ans.length() - 2), true));
270 delete _outSocket;
271 _outSocket = 0;
272 return;
273 } else {
274 emit(newMessage(
275 "Proxy: Connection opened for " + _mountpoint.toLatin1()
276 + ": " + ans.left(ans.length() - 2), true));
277 _sOpenTrial = 0;
278 _outSocket->setPeerVerifyName(_casterOutHost);
279 _outSocket->startClientEncryption();
280 if (!_outSocket->waitForEncrypted(timeOut)) {
281 emit(newMessage(
282 "Proxy: Encrypt timeout for " + _mountpoint.toLatin1() + " ("
283 + _casterOutHost.toLatin1() + ":"
284 + QString("%1) ").arg(_casterOutPort).toLatin1()
285 + _outSocket->errorString().toLatin1(), true));
286 delete _outSocket;
287 _outSocket = 0;
288 return;
289 } else {
290 emit(newMessage("Proxy: SSL handshake completed for " + _mountpoint.toLatin1(), true));
291 }
292 }
293 }
294 } else {
295 if (!connectToHost(_casterOutHost, _casterOutPort, _secure)) {
296 return;
297 }
[9707]298 }
299
[9717]300 connect(_outSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>)));
301
[9707]302 if (_ntripVersion == "1") {
[9715]303 msg = "SOURCE " + _password.toLatin1() + " /" + _mountpoint.toLatin1()
304 + "\r\n" + "Source-Agent: NTRIP BNC/" BNCVERSION "\r\n\r\n";
305 } else {
306 msg = "POST " + _postExtension.toLatin1() + "/" + _mountpoint.toLatin1()
307 + " HTTP/1.1\r\n" + "Host: " + _casterOutHost.toLatin1() + "\r\n"
308 + "Ntrip-Version: Ntrip/2.0\r\n" + "Authorization: Basic "
309 + (_userName + ":" + _password).toLatin1().toBase64() + "\r\n"
310 + "User-Agent: NTRIP BNC/" BNCVERSION " (" + BNC_OS + ")\r\n"
311 + "Connection: close\r\n" + "Transfer-Encoding: chunked\r\n\r\n";
[9707]312 }
313 cout << msg.toStdString().c_str();
[3172]314 _outSocket->write(msg);
315 _outSocket->waitForBytesWritten();
316 _outSocket->waitForReadyRead();
317
[9716]318 QByteArray ans = _outSocket->readLine(); cout << "ans: " << ans.toStdString().c_str() << endl;
[9715]319
320 if (ans.indexOf("200") == -1) {
[3172]321 delete _outSocket;
322 _outSocket = 0;
[9715]323 emit(newMessage(
324 "Broadcaster: Connection broken for " + _mountpoint.toLatin1() + ": "
325 + ans.left(ans.length() - 2), true));
326 } else {
327 emit(newMessage(
328 "Broadcaster: Connection opened for " + _mountpoint.toLatin1() + ": "
329 + ans.left(ans.length() - 2), true));
[3172]330 _sOpenTrial = 0;
331 }
332}
333
[9715]334// Try connection to NTRIP Caster or Proxy
335////////////////////////////////////////////////////////////////////////////
336bool bncUploadCaster::connectToHost(QString outHost, int outPort, bool encrypted) {
337 const int timeOut = 5000; // 5 seconds
338 if (encrypted) {
339 _outSocket->connectToHostEncrypted(outHost, outPort);
340 if (!_outSocket->waitForEncrypted(timeOut)) {
341 emit(newMessage(
342 "Broadcaster: Connect timeout for " + _mountpoint.toLatin1() + " ("
343 + outHost.toLatin1() + ":"
344 + QString("%1) ").arg(outPort).toLatin1()
345 + _outSocket->errorString().toLatin1(), true));
346 delete _outSocket;
347 _outSocket = 0;
348 return false;
[9717]349 } else {
350 emit(newMessage("Broadcaster: SSL handshake completed for " + _mountpoint.toLatin1(), true));
[9715]351 }
352 } else {
353 _outSocket->connectToHost(outHost, outPort);
354 if (!_outSocket->waitForConnected(timeOut)) {
355 emit(newMessage(
356 "Broadcaster: Connect timeout for " + _mountpoint.toLatin1() + " ("
357 + outHost.toLatin1() + ":"
358 + QString("%1) ").arg(outPort).toLatin1()
359 + _outSocket->errorString().toLatin1(), true));
360 delete _outSocket;
361 _outSocket = 0;
362 return false;
363 }
364 }
365 return true;
366}
367
368
369
370
371
372
373
Note: See TracBrowser for help on using the repository browser.