source: ntrip/trunk/BNC/src/bncnetqueryv2.cpp@ 9795

Last change on this file since 9795 was 9795, checked in by stuerze, 21 months ago

consideration of client SSL certificates, if they are available

File size: 8.1 KB
RevLine 
[1378]1/* -------------------------------------------------------------------------
2 * BKG NTRIP Client
3 * -------------------------------------------------------------------------
4 *
5 * Class: bncNetQueryV2
6 *
7 * Purpose: Blocking Network Requests (NTRIP Version 2)
8 *
9 * Author: L. Mervart
10 *
11 * Created: 27-Dec-2008
12 *
[7612]13 * Changes:
[1378]14 *
15 * -----------------------------------------------------------------------*/
16
[1583]17#include <iostream>
18
[1379]19#include "bncnetqueryv2.h"
[1535]20#include "bncsettings.h"
[2011]21#include "bncversion.h"
[3349]22#include "bncsslconfig.h"
[3359]23#include "bncsettings.h"
[1378]24
25// Constructor
26////////////////////////////////////////////////////////////////////////////
[3337]27bncNetQueryV2::bncNetQueryV2(bool secure) {
28 _secure = secure;
[1378]29 _manager = new QNetworkAccessManager(this);
[9706]30 connect(_manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
31 this, SLOT(slotProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
[1378]32 _reply = 0;
33 _eventLoop = new QEventLoop(this);
[1583]34 _firstData = true;
[1378]35 _status = init;
[3359]36
37 bncSettings settings;
[9795]38 _sslIgnoreErrors = (Qt::CheckState(settings.value("sslIgnoreErrors").toInt()) == Qt::Checked);
[3359]39
[9795]40 if (_secure ) {
41 if (!QSslSocket::supportsSsl()) {
42 BNC_CORE->slotMessage("No SSL support, install OpenSSL run-time libraries", true);
43 stop();
44 }
45 // Generate filenames to consider a potential client certificate
46 _crtFileName = settings.value("sslClientCertPath").toString() + _url.host() + QString(".%1.crt").arg(_url.port());
47 _keyFileName = settings.value("sslClientCertPath").toString() + _url.host() + QString(".%1.key").arg(_url.port());
[3352]48 }
[9795]49
50
[1378]51}
52
53// Destructor
54////////////////////////////////////////////////////////////////////////////
55bncNetQueryV2::~bncNetQueryV2() {
56 delete _eventLoop;
[7704]57 if (_reply) {
58 _reply->abort();
59 delete _reply;
60 }
[1378]61 delete _manager;
62}
63
[1713]64// Stop (quit event loop)
[1390]65////////////////////////////////////////////////////////////////////////////
66void bncNetQueryV2::stop() {
[1393]67 if (_reply) {
[1395]68 _reply->abort();
[7704]69 delete _reply;
70 _reply = 0;
[1393]71 }
[1394]72 _eventLoop->quit();
[1398]73 _status = finished;
[1390]74}
75
[1389]76// End of Request
77////////////////////////////////////////////////////////////////////////////
[1378]78void bncNetQueryV2::slotFinished() {
[1704]79 _eventLoop->quit();
80 if (_reply && _reply->error() != QNetworkReply::NoError) {
81 _status = error;
[9723]82 if (!_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().isEmpty()) {
[8203]83 emit newMessage(_url.path().toLatin1().replace(0,1,"") +
[7612]84 ": NetQueryV2: server replied: " +
[1704]85 _reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray(),
86 true);
[9723]87 } else {
88 emit newMessage(_url.path().toLatin1().replace(0,1,"") +
89 ": NetQueryV2: server replied: " +
90 _reply->errorString().toLatin1(),
91 true);
92 }
[1704]93 }
94 else {
[1378]95 _status = finished;
96 }
97}
98
[7612]99//
[1405]100////////////////////////////////////////////////////////////////////////////
[7612]101void bncNetQueryV2::slotProxyAuthenticationRequired(const QNetworkProxy&,
[1405]102 QAuthenticator*) {
103 emit newMessage("slotProxyAuthenticationRequired", true);
104}
105
[1389]106// Start request, block till the next read
[1378]107////////////////////////////////////////////////////////////////////////////
[1380]108void bncNetQueryV2::startRequest(const QUrl& url, const QByteArray& gga) {
[1389]109 startRequestPrivate(url, gga, false);
[1378]110}
111
[6787]112// Start request, block till the next read
113////////////////////////////////////////////////////////////////////////////
114void bncNetQueryV2::keepAliveRequest(const QUrl& url, const QByteArray& gga) {
115 startRequestPrivate(url, gga, false);
116}
117
[1389]118// Start Request (Private Method)
[1378]119////////////////////////////////////////////////////////////////////////////
[1389]120void bncNetQueryV2::startRequestPrivate(const QUrl& url, const QByteArray& gga,
121 bool full) {
[1378]122
123 _status = running;
124
125 // Default scheme and path
126 // -----------------------
[1509]127 _url = url;
128 if (_url.scheme().isEmpty()) {
[3337]129 if (_secure) {
[9795]130 _url.setPort(443);
[3337]131 _url.setScheme("https");
132 }
133 else {
134 _url.setScheme("http");
135 }
[1378]136 }
[1509]137 if (_url.path().isEmpty()) {
138 _url.setPath("/");
[1378]139 }
140
141 // Network Request
142 // ---------------
[9795]143 bncSslConfig sslConfig = BNC_SSL_CONFIG;
144
145 if (_secure) {
146 QFile clientCrtFile(_crtFileName);
147 QFile privateKeyFile(_keyFileName);
148 if ( clientCrtFile.exists() && privateKeyFile.exists()) {
149 // set local certificate if available
150 clientCrtFile.open(QIODevice::ReadOnly);
151 QSslCertificate clientCrt(&clientCrtFile);
152 sslConfig.setLocalCertificate(clientCrt);
153 // set private key if available
154 privateKeyFile.open(QIODevice::ReadOnly);
155 QSslKey privateKey(&privateKeyFile, QSsl::Rsa);
156 sslConfig.setPrivateKey(privateKey);
157 }
158 }
159
[1716]160 QNetworkRequest request;
[9795]161 request.setSslConfiguration(sslConfig);
[1716]162 request.setUrl(_url);
[8203]163 request.setRawHeader("Host" , _url.host().toLatin1());
[1716]164 request.setRawHeader("Ntrip-Version", "Ntrip/2.0");
[8203]165 request.setRawHeader("User-Agent" , "NTRIP BNC/" BNCVERSION " (" BNC_OS ")");
[1509]166 if (!_url.userName().isEmpty()) {
[8203]167 QString uName = QUrl::fromPercentEncoding(_url.userName().toLatin1());
168 QString passW = QUrl::fromPercentEncoding(_url.password().toLatin1());
[7612]169 request.setRawHeader("Authorization", "Basic " +
[8203]170 (uName + ":" + passW).toLatin1().toBase64());
[7612]171 }
[1389]172 if (!gga.isEmpty()) {
[1716]173 request.setRawHeader("Ntrip-GGA", gga);
[1389]174 }
[1716]175 request.setRawHeader("Connection" , "close");
[1378]176
[7851]177 if (_reply) {
178 delete _reply;
179 _reply = 0;
180 }
[1716]181 _reply = _manager->get(request);
[1378]182
183 // Connect Signals
184 // ---------------
185 connect(_reply, SIGNAL(finished()), this, SLOT(slotFinished()));
[9722]186 connect(_reply, SIGNAL(finished()), _eventLoop, SLOT(quit()));
[9721]187 connect(_reply, SIGNAL(sslErrors(QList<QSslError>)),this, SLOT(slotSslErrors(QList<QSslError>)));
[1378]188 if (!full) {
[9722]189 connect(_reply, SIGNAL(readyRead()), _eventLoop, SLOT(quit()));
[1378]190 }
191}
192
193// Start Request, wait for its completion
194////////////////////////////////////////////////////////////////////////////
195void bncNetQueryV2::waitForRequestResult(const QUrl& url, QByteArray& outData) {
196
197 // Send Request
198 // ------------
[1389]199 startRequestPrivate(url, "", true);
[1378]200
201 // Wait Loop
202 // ---------
[1394]203 _eventLoop->exec();
[1378]204
205 // Copy Data and Return
206 // --------------------
[7813]207 if (_reply) {
208 outData = _reply->readAll();
209 }
[1378]210}
211
212// Wait for next data
213////////////////////////////////////////////////////////////////////////////
214void bncNetQueryV2::waitForReadyRead(QByteArray& outData) {
215
216 // Wait Loop
217 // ---------
218 if (!_reply->bytesAvailable()) {
[1394]219 _eventLoop->exec();
[1378]220 }
[9723]221 if (!_reply) {
222 return;
223 }
[1378]224
[1701]225 // Check NTRIPv2 error code
226 // ------------------------
227 if (_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
228 _reply->abort();
229 }
230
[1378]231 // Append Data
232 // -----------
[1701]233 else {
234 outData.append(_reply->readAll());
[1583]235 }
[1378]236}
[1712]237
[7612]238// TSL/SSL
[3332]239////////////////////////////////////////////////////////////////////////////
[3349]240void bncNetQueryV2::slotSslErrors(QList<QSslError> errors) {
[3332]241
[9723]242 QString msg = "SSL Error: ";
[3351]243 QSslCertificate cert = _reply->sslConfiguration().peerCertificate();
[9708]244 if (!cert.isNull() &&
245 cert.issuerInfo(QSslCertificate::OrganizationalUnitName).count() &&
246 cert.issuerInfo(QSslCertificate::Organization).count()) {
[9719]247
[3354]248 msg += QString("Server Certificate Issued by:\n"
249 "%1\n%2\nCannot be verified\n")
[8203]250#if QT_VERSION >= 0x050000
251 .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName).at(0))
252 .arg(cert.issuerInfo(QSslCertificate::Organization).at(0));
253#else
[3354]254 .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName))
255 .arg(cert.issuerInfo(QSslCertificate::Organization));
[8203]256#endif
[3351]257 }
[9719]258
[9723]259 QListIterator<QSslError> it(errors);
[3363]260 while (it.hasNext()) {
261 const QSslError& err = it.next();
[9723]262 msg += err.errorString();
[3353]263 }
[3346]264
[7513]265 if (_sslIgnoreErrors) {
[3353]266 _reply->ignoreSslErrors();
[9723]267 BNC_CORE->slotMessage("BNC ignores SSL errors as configured", true);
[3353]268 }
269 else {
[9742]270 BNC_CORE->slotMessage(msg.toLatin1(), true);
[3353]271 stop();
272 }
[9723]273 return;
[3332]274}
Note: See TracBrowser for help on using the repository browser.