/* ------------------------------------------------------------------------- * BKG NTRIP Client * ------------------------------------------------------------------------- * * Class: bncNetQueryRtp * * Purpose: Blocking Network Requests (NTRIP Version 2 with RTSP) * * Author: L. Mervart * * Created: 27-Dec-2008 * * Changes: * * -----------------------------------------------------------------------*/ #include #include #include "bncnetqueryrtp.h" using namespace std; #define BNCVERSION "1.7" // Constructor //////////////////////////////////////////////////////////////////////////// bncNetQueryRtp::bncNetQueryRtp() { _socket = 0; _udpSocket = 0; _CSeq = 0; _eventLoop = new QEventLoop(this); } // Destructor //////////////////////////////////////////////////////////////////////////// bncNetQueryRtp::~bncNetQueryRtp() { delete _eventLoop; delete _socket; delete _udpSocket; } // //////////////////////////////////////////////////////////////////////////// void bncNetQueryRtp::stop() { _eventLoop->quit(); _status = finished; } // //////////////////////////////////////////////////////////////////////////// void bncNetQueryRtp::waitForRequestResult(const QUrl&, QByteArray&) { } // //////////////////////////////////////////////////////////////////////////// void bncNetQueryRtp::waitForReadyRead(QByteArray& outData) { // Wait Loop // --------- if (!_udpSocket->hasPendingDatagrams()) { _eventLoop->exec(); } // Append Data // ----------- QByteArray datagram; datagram.resize(_udpSocket->pendingDatagramSize()); _udpSocket->readDatagram(datagram.data(), datagram.size()); if (datagram.size() > 12) { outData.append(datagram.mid(12)); } } // Connect to Caster, send the Request //////////////////////////////////////////////////////////////////////////// void bncNetQueryRtp::startRequest(const QUrl& url, const QByteArray& gga) { const int timeOut = 5000; _status = running; delete _socket; _socket = new QTcpSocket(); // Default scheme // -------------- _url = url; _url.setScheme("rtsp"); // Connect the Socket // ------------------ QSettings settings; QString proxyHost = settings.value("proxyHost").toString(); int proxyPort = settings.value("proxyPort").toInt(); if ( proxyHost.isEmpty() ) { _socket->connectToHost(_url.host(), _url.port()); } else { _socket->connectToHost(proxyHost, proxyPort); } // Send Request 1 // -------------- if (_socket->waitForConnected(timeOut)) { QString uName = QUrl::fromPercentEncoding(_url.userName().toAscii()); QString passW = QUrl::fromPercentEncoding(_url.password().toAscii()); QByteArray userAndPwd; if(!uName.isEmpty() || !passW.isEmpty()) { userAndPwd = "Authorization: Basic " + (uName.toAscii() + ":" + passW.toAscii()).toBase64() + "\r\n"; } // Setup the RTSP Connection // ------------------------- delete _udpSocket; _udpSocket = new QUdpSocket(); _udpSocket->bind(0); connect(_udpSocket, SIGNAL(readyRead()), _eventLoop, SLOT(quit())); QByteArray clientPort = QString("%1").arg(_udpSocket->localPort()).toAscii(); QByteArray reqStr; reqStr = "SETUP " + _url.toEncoded() + " RTSP/1.0\r\n" + "CSeq: " + QString("%1").arg(++_CSeq).toAscii() + "\r\n" + "Ntrip-Version: Ntrip/2.0\r\n" + "Ntrip-Component: Ntripclient\r\n" + "User-Agent: NTRIP BNC/" BNCVERSION "\r\n" + "Transport: RTP/GNSS;unicast;client_port=" + clientPort + "\r\n" + userAndPwd + "\r\n"; _socket->write(reqStr, reqStr.length()); // Read Server Answer 1 // -------------------- if (_socket->waitForBytesWritten(timeOut)) { if (_socket->waitForReadyRead(timeOut)) { QTextStream in(_socket); QByteArray serverPort; QString line = in.readLine(); while (!line.isEmpty()) { if (line.indexOf("Session:") == 0) { _session = line.mid(9).toAscii(); } int iSrv = line.indexOf("server_port="); if (iSrv != -1) { serverPort = line.mid(iSrv+12).toAscii(); } line = in.readLine(); } // Send Request 2 // -------------- if (!_session.isEmpty()) { // Send initial RTP packet for firewall handling // --------------------------------------------- if (!serverPort.isEmpty()) { int sessInt = _session.toInt(); char rtpbuffer[12]; rtpbuffer[0] = (2<<6); rtpbuffer[1] = 96; rtpbuffer[2] = 0; rtpbuffer[3] = 0; rtpbuffer[4] = 0; rtpbuffer[5] = 0; rtpbuffer[6] = 0; rtpbuffer[7] = 0; rtpbuffer[8] = (sessInt>>24)&0xFF; rtpbuffer[9] = (sessInt>>16)&0xFF; rtpbuffer[10] = (sessInt>>8)&0xFF; rtpbuffer[11] = (sessInt)&0xFF; _udpSocket->writeDatagram(rtpbuffer, 12, _socket->peerAddress(), serverPort.toInt()); } reqStr = "PLAY " + _url.toEncoded() + " RTSP/1.0\r\n" + "CSeq: " + QString("%1").arg(++_CSeq).toAscii() + "\r\n" + "Session: " + _session + "\r\n" + "\r\n"; _socket->write(reqStr, reqStr.length()); // Read Server Answer 2 // -------------------- if (_socket->waitForBytesWritten(timeOut)) { if (_socket->waitForReadyRead(timeOut)) { QTextStream in(_socket); line = in.readLine(); while (!line.isEmpty()) { if (line.indexOf("200 OK") != -1) { emit newMessage(_url.host().toAscii() + _url.path().toAscii() + ": UDP connection established", true); return; } line = in.readLine(); } } } } } } } delete _socket; _socket = 0; _status = error; }