source: ntrip/trunk/BNC/bncsocket.cpp@ 1367

Last change on this file since 1367 was 1367, checked in by mervart, 16 years ago

* empty log message *

File size: 9.4 KB
RevLine 
[1344]1/* -------------------------------------------------------------------------
2 * BKG NTRIP Client
3 * -------------------------------------------------------------------------
4 *
5 * Class: bncSocket
6 *
[1367]7 * Purpose: Combines QTcpSocket (NTRIP v1) and QHttp (NTRIP v2)
[1344]8 *
9 * Author: L. Mervart
10 *
11 * Created: 27-Dec-2008
12 *
13 * Changes:
14 *
15 * -----------------------------------------------------------------------*/
16
17#include <iostream>
18#include <iomanip>
19
[1367]20#include <string.h>
21
[1344]22#include "bncsocket.h"
[1354]23#include "bncapp.h"
[1344]24
25using namespace std;
26
[1346]27#define BNCVERSION "1.7"
28
[1344]29// Constructor
30////////////////////////////////////////////////////////////////////////////
[1348]31bncSocket::bncSocket() {
[1354]32 bncApp* app = (bncApp*) qApp;
33 app->connect(this, SIGNAL(newMessage(QByteArray,bool)),
34 app, SLOT(slotMessage(const QByteArray,bool)));
[1362]35 _socket = 0;
36 _http = 0;
[1363]37 connect(this, SIGNAL(quitEventLoop()), &_eventLoop, SLOT(quit()));
[1344]38}
39
40// Destructor
41////////////////////////////////////////////////////////////////////////////
42bncSocket::~bncSocket() {
[1348]43 delete _socket;
[1357]44 delete _http;
[1344]45}
46
47//
48////////////////////////////////////////////////////////////////////////////
49QAbstractSocket::SocketState bncSocket::state() const {
[1367]50 if (_http) {
51 if (_http->state() != QHttp::Unconnected) {
52 return QAbstractSocket::ConnectedState;
53 }
54 else {
55 return QAbstractSocket::UnconnectedState;
56 }
57 }
58 else if (_socket) {
[1348]59 return _socket->state();
60 }
61 else {
62 return QAbstractSocket::UnconnectedState;
63 }
[1344]64}
65
66//
67////////////////////////////////////////////////////////////////////////////
[1345]68void bncSocket::close() {
[1348]69 if (_socket) {
70 _socket->close();
71 }
[1344]72}
73
74//
75////////////////////////////////////////////////////////////////////////////
[1345]76qint64 bncSocket::bytesAvailable() const {
[1360]77 if (_http) {
[1363]78 return _buffer.size();
[1360]79 }
80 else if (_socket) {
[1348]81 return _socket->bytesAvailable();
82 }
83 else {
84 return 0;
85 }
[1344]86}
87
[1345]88//
89////////////////////////////////////////////////////////////////////////////
90bool bncSocket::canReadLine() const {
[1363]91 if (_http) {
92 if (_buffer.indexOf('\n') != -1) {
93 return true;
94 }
95 else {
96 return false;
97 }
[1360]98 }
99 else if (_socket) {
[1348]100 return _socket->canReadLine();
101 }
102 else {
103 return false;
104 }
[1345]105}
106
107//
108////////////////////////////////////////////////////////////////////////////
[1364]109QByteArray bncSocket::readLine() {
[1363]110 if (_http) {
[1364]111 int ind = _buffer.indexOf('\n');
112 if (ind != -1) {
113 QByteArray ret = _buffer.left(ind+1);
114 _buffer = _buffer.right(_buffer.size()-ind-1);
115 return ret;
116 }
117 else {
118 return "";
119 }
[1360]120 }
121 else if (_socket) {
[1364]122 return _socket->readLine();
[1348]123 }
124 else {
125 return "";
126 }
[1345]127}
128
129//
130////////////////////////////////////////////////////////////////////////////
[1363]131void bncSocket::waitForReadyRead(int msecs) {
132 if (_http) {
133 if (bytesAvailable() > 0) {
134 return;
135 }
136 else {
137 _eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
138 }
[1348]139 }
[1363]140 else if (_socket) {
141 _socket->waitForReadyRead(msecs);
[1348]142 }
[1345]143}
144
145//
146////////////////////////////////////////////////////////////////////////////
147qint64 bncSocket::read(char* data, qint64 maxlen) {
[1367]148 if (_http) {
149 strncpy(data, _buffer.data(), maxlen);
150 _buffer = _buffer.right(_buffer.size()-maxlen);
151 return maxlen;
152 }
153 else if (_socket) {
[1348]154 return _socket->read(data, maxlen);
155 }
156 else {
157 return -1;
158 }
[1345]159}
160
[1349]161// Connect to Caster, send the Request
[1346]162////////////////////////////////////////////////////////////////////////////
[1348]163t_irc bncSocket::request(const QUrl& mountPoint, const QByteArray& latitude,
164 const QByteArray& longitude, const QByteArray& nmea,
[1353]165 const QByteArray& ntripVersion,
[1348]166 int timeOut, QString& msg) {
[1346]167
[1354]168 if (ntripVersion == "AUTO") {
[1366]169 emit newMessage("NTRIP Version AUTO not yet implemented", true);
[1354]170 return failure;
171 }
172 else if (ntripVersion == "2") {
[1355]173 return request2(mountPoint, latitude, longitude, nmea, timeOut, msg);
[1354]174 }
175 else if (ntripVersion != "1") {
[1366]176 emit newMessage("Unknown NTRIP Version " + ntripVersion, true);
[1354]177 return failure;
178 }
179
[1348]180 delete _socket;
181 _socket = new QTcpSocket();
182
[1346]183 // Connect the Socket
184 // ------------------
185 QSettings settings;
186 QString proxyHost = settings.value("proxyHost").toString();
187 int proxyPort = settings.value("proxyPort").toInt();
188
189 if ( proxyHost.isEmpty() ) {
[1348]190 _socket->connectToHost(mountPoint.host(), mountPoint.port());
[1346]191 }
192 else {
[1348]193 _socket->connectToHost(proxyHost, proxyPort);
[1346]194 }
[1348]195 if (!_socket->waitForConnected(timeOut)) {
[1346]196 msg += "Connect timeout\n";
[1348]197 delete _socket;
198 _socket = 0;
199 return failure;
[1346]200 }
201
202 // Send Request
203 // ------------
204 QString uName = QUrl::fromPercentEncoding(mountPoint.userName().toAscii());
205 QString passW = QUrl::fromPercentEncoding(mountPoint.password().toAscii());
206 QByteArray userAndPwd;
207
208 if(!uName.isEmpty() || !passW.isEmpty())
209 {
210 userAndPwd = "Authorization: Basic " + (uName.toAscii() + ":" +
211 passW.toAscii()).toBase64() + "\r\n";
212 }
213
214 QUrl hlp;
215 hlp.setScheme("http");
216 hlp.setHost(mountPoint.host());
217 hlp.setPort(mountPoint.port());
218 hlp.setPath(mountPoint.path());
219
220 QByteArray reqStr;
221 if ( proxyHost.isEmpty() ) {
222 if (hlp.path().indexOf("/") != 0) hlp.setPath("/");
223 reqStr = "GET " + hlp.path().toAscii() + " HTTP/1.0\r\n"
224 + "User-Agent: NTRIP BNC/" BNCVERSION "\r\n"
225 + userAndPwd + "\r\n";
226 } else {
227 reqStr = "GET " + hlp.toEncoded() + " HTTP/1.0\r\n"
228 + "User-Agent: NTRIP BNC/" BNCVERSION "\r\n"
229 + "Host: " + hlp.host().toAscii() + "\r\n"
230 + userAndPwd + "\r\n";
231 }
232
233 // NMEA string to handle VRS stream
234 // --------------------------------
235 double lat, lon;
236
237 lat = strtod(latitude,NULL);
238 lon = strtod(longitude,NULL);
239
240 if ((nmea == "yes") && (hlp.path().length() > 2) && (hlp.path().indexOf(".skl") < 0)) {
241 const char* flagN="N";
242 const char* flagE="E";
243 if (lon >180.) {lon=(lon-360.)*(-1.); flagE="W";}
244 if ((lon < 0.) && (lon >= -180.)) {lon=lon*(-1.); flagE="W";}
245 if (lon < -180.) {lon=(lon+360.); flagE="E";}
246 if (lat < 0.) {lat=lat*(-1.); flagN="S";}
247 QTime ttime(QDateTime::currentDateTime().toUTC().time());
248 int lat_deg = (int)lat;
249 double lat_min=(lat-lat_deg)*60.;
250 int lon_deg = (int)lon;
251 double lon_min=(lon-lon_deg)*60.;
252 int hh = 0 , mm = 0;
253 double ss = 0.0;
254 hh=ttime.hour();
255 mm=ttime.minute();
256 ss=(double)ttime.second()+0.001*ttime.msec();
257 QString gga;
258 gga += "GPGGA,";
259 gga += QString("%1%2%3,").arg((int)hh, 2, 10, QLatin1Char('0')).arg((int)mm, 2, 10, QLatin1Char('0')).arg((int)ss, 2, 10, QLatin1Char('0'));
260 gga += QString("%1%2,").arg((int)lat_deg,2, 10, QLatin1Char('0')).arg(lat_min, 7, 'f', 4, QLatin1Char('0'));
261 gga += flagN;
262 gga += QString(",%1%2,").arg((int)lon_deg,3, 10, QLatin1Char('0')).arg(lon_min, 7, 'f', 4, QLatin1Char('0'));
263 gga += flagE + QString(",1,05,1.00,+00100,M,10.000,M,,");
264 int xori;
265 char XOR = 0;
266 char *Buff =gga.toAscii().data();
267 int iLen = strlen(Buff);
268 for (xori = 0; xori < iLen; xori++) {
269 XOR ^= (char)Buff[xori];
270 }
271 gga += QString("*%1").arg(XOR, 2, 16, QLatin1Char('0'));
272 reqStr += "$";
273 reqStr += gga;
274 reqStr += "\r\n";
275 }
276
277 msg += reqStr;
278
[1348]279 _socket->write(reqStr, reqStr.length());
[1346]280
[1348]281 if (!_socket->waitForBytesWritten(timeOut)) {
[1346]282 msg += "Write timeout\n";
[1348]283 delete _socket;
284 _socket = 0;
285 return failure;
[1346]286 }
287
[1348]288 return success;
[1346]289}
290
[1355]291//
292////////////////////////////////////////////////////////////////////////////
[1366]293void bncSocket::slotRequestFinished(int /* id */, bool error) {
[1358]294 if (error) {
[1366]295 emit newMessage("slotRequestFinished " +
296 _http->errorString().toAscii(), true);
[1358]297 }
[1355]298}
299
300//
301////////////////////////////////////////////////////////////////////////////
[1363]302void bncSocket::slotReadyRead(const QHttpResponseHeader&) {
303 _buffer.append(_http->readAll());
304 emit quitEventLoop();
[1355]305}
306
307//
308////////////////////////////////////////////////////////////////////////////
[1357]309void bncSocket::slotDone(bool error) {
[1358]310 if (error) {
[1366]311 emit newMessage("slotDone " + _http->errorString().toAscii(), true);
[1358]312 }
[1366]313 emit quitEventLoop();
[1355]314}
315
316// Connect to Caster NTRIP Version 2
317////////////////////////////////////////////////////////////////////////////
[1356]318t_irc bncSocket::request2(const QUrl& url, const QByteArray& latitude,
[1355]319 const QByteArray& longitude, const QByteArray& nmea,
320 int timeOut, QString& msg) {
321
[1361]322
[1357]323 delete _http;
324 _http = new QHttp();
325
[1358]326 _http->setHost(url.host());
327
[1356]328 // Network Request
329 // ---------------
[1358]330 QString path = url.path();
331 if (path.isEmpty()) {
332 path = "/";
333 }
334 QHttpRequestHeader request("GET", path);
[1357]335 request.addValue("Host" , url.host().toAscii());
336 request.addValue("Ntrip-Version", "NTRIP/2.0");
[1358]337 request.addValue("User-Agent" , "NTRIP BNC/" BNCVERSION);
[1356]338 if (!url.userName().isEmpty()) {
[1357]339 request.addValue("Authorization", "Basic " +
[1356]340 (url.userName() + ":" + url.password()).toAscii().toBase64());
341 }
[1357]342 request.addValue("Connection" , "close");
[1356]343
344
[1357]345 connect(_http, SIGNAL(done(bool)), this, SLOT(slotDone(bool)));
346 connect(_http, SIGNAL(requestFinished(int, bool)),
347 this, SLOT(slotRequestFinished(int, bool)));
[1363]348 connect(_http, SIGNAL(readyRead(const QHttpResponseHeader&)),
349 this, SLOT(slotReadyRead(const QHttpResponseHeader&)));
[1356]350
[1363]351 _http->request(request);
[1358]352
[1356]353 return success;
[1355]354}
Note: See TracBrowser for help on using the repository browser.