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

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

minor changes

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