Index: trunk/BNC/src/upload/bncuploadcaster.cpp
===================================================================
--- trunk/BNC/src/upload/bncuploadcaster.cpp	(revision 9714)
+++ trunk/BNC/src/upload/bncuploadcaster.cpp	(revision 9715)
@@ -21,4 +21,5 @@
 #include "bnctableitem.h"
 #include "bncsettings.h"
+#include "bncsslconfig.h"
 
 using namespace std;
@@ -26,25 +27,23 @@
 // Constructor
 ////////////////////////////////////////////////////////////////////////////
-bncUploadCaster::bncUploadCaster(const QString& mountpoint,
-                                 const QString& outHost, int outPort,
-                                 const QString& ntripVersion,
-                                 const QString& userName, const QString& password,
-                                 int iRow,
-                                 int rate) {
-  _mountpoint    = mountpoint;
+bncUploadCaster::bncUploadCaster(const QString &mountpoint,
+    const QString &outHost, int outPort, const QString &ntripVersion,
+    const QString &userName, const QString &password, int iRow, int rate) {
+  bncSettings settings;
+
+  _mountpoint = mountpoint;
   _casterOutHost = outHost;
   _casterOutPort = outPort;
-  _ntripVersion  = ntripVersion;
-  _userName      = userName;
-  _password      = password;
-  _outSocket     = 0;
-  _sOpenTrial    = 0;
-  _iRow          = iRow;
-  _rate          = rate;
-
-  if      (_rate < 0) {
+  _ntripVersion = ntripVersion;
+  _userName = userName;
+  _password = password;
+  _outSocket = 0;
+  _sOpenTrial = 0;
+  _iRow = iRow;
+  _rate = rate;
+
+  if (_rate < 0) {
     _rate = 0;
-  }
-  else if (_rate > 60) {
+  } else if (_rate > 60) {
     _rate = 60;
   }
@@ -52,42 +51,44 @@
 
   connect(this, SIGNAL(newMessage(QByteArray,bool)),
-          BNC_CORE, SLOT(slotMessage(const QByteArray,bool)));
-
-  if (BNC_CORE->_uploadTableItems.find(_iRow) != BNC_CORE->_uploadTableItems.end()){
+  BNC_CORE, SLOT(slotMessage(const QByteArray,bool)));
+
+  if (BNC_CORE->_uploadTableItems.find(_iRow)
+      != BNC_CORE->_uploadTableItems.end()) {
     connect(this, SIGNAL(newBytes(QByteArray,double)),
-            BNC_CORE->_uploadTableItems.value(iRow),
-            SLOT(slotNewBytes(const QByteArray,double)));
-  }
-  if (BNC_CORE->_uploadEphTableItems.find(_iRow) != BNC_CORE->_uploadEphTableItems.end()){
+    BNC_CORE->_uploadTableItems.value(iRow),
+        SLOT(slotNewBytes(const QByteArray,double)));
+  }
+  if (BNC_CORE->_uploadEphTableItems.find(_iRow)
+      != BNC_CORE->_uploadEphTableItems.end()) {
     connect(this, SIGNAL(newBytes(QByteArray,double)),
-            BNC_CORE->_uploadEphTableItems.value(iRow),
-            SLOT(slotNewBytes(const QByteArray,double)));
-  }
-
-  bncSettings settings;
-  _sslIgnoreErrors = (Qt::CheckState(settings.value("sslIgnoreErrors").toInt()) == Qt::Checked);
-  _proxyHost = settings.value("proxyHost").toString();
-  _proxyPort = settings.value("proxyPort").toInt();
-  (_proxyHost.isEmpty()) ? _proxy = false : _proxy = true;
-
+    BNC_CORE->_uploadEphTableItems.value(iRow),
+        SLOT(slotNewBytes(const QByteArray,double)));
+  }
+
+  _sslIgnoreErrors = (Qt::CheckState(settings.value("sslIgnoreErrors").toInt())
+      == Qt::Checked);
+
+  _proxyOutHost = settings.value("proxyHost").toString();
+  _proxyOutPort = settings.value("proxyPort").toInt();
+  (_proxyOutHost.isEmpty()) ? _proxy = false : _proxy = true;
+
+  _secure = false;
   if (_ntripVersion == "2s") {
-    _secure = true;
     if (!QSslSocket::supportsSsl()) {
-      emit(newMessage("For SSL support please install OpenSSL run-time libraries: Ntrip Version 2 is tried", true));
-      _secure = false;
+      emit(newMessage(
+          "For SSL support please install OpenSSL run-time libraries: Ntrip Version 2 is tried",
+          true));
       _ntripVersion == "2";
-    }
-  } else {
-    _secure = false;
-  }
-
-  if (_secure) {
-    _casterOutPort = 443;
-    (_proxy) ? _postExtension = QString("https://%1:%2").arg(_casterOutHost).arg(_casterOutPort) : _postExtension = "";
-  }
-  else {
-    (_proxy) ? _postExtension = QString("http://%1:%2").arg(_casterOutHost).arg(_casterOutPort) : _postExtension = "";
-  }
-
+    } else {
+      _secure = true;
+      _casterOutPort = 443;
+    }
+  }
+
+  if (!_secure && _proxy) {
+    _postExtension = QString("http://%1:%2").arg(_casterOutHost).arg(_casterOutPort);
+  } else {
+    _postExtension = "";
+  }
 }
 
@@ -115,26 +116,29 @@
 ////////////////////////////////////////////////////////////////////////////
 void bncUploadCaster::slotProxyAuthenticationRequired(const QNetworkProxy&,
-                                                    QAuthenticator*) {
+    QAuthenticator*) {
   emit newMessage("slotProxyAuthenticationRequired", true);
 }
 
-
-/* TSL/SSL
-////////////////////////////////////////////////////////////////////////////
-void bncUploadCaster::slotSslErrors(QList<QSslError> errors) {
-
-  QString msg = "SSL Error\n";
-  QSslCertificate cert = _outSocket->sslConfiguration().peerCertificate();
-  if (!cert.isNull()) {
-    msg += QString("Server Certificate Issued by:\n"
-                   "%1\n%2\nCannot be verified\n")
+// TSL/SSL
+ ////////////////////////////////////////////////////////////////////////////
+ void bncUploadCaster::slotSslErrors(QList<QSslError> errors) {
+
+ QString msg = "SSL Error\n";
+ QSslCertificate cert = _outSocket->sslConfiguration().peerCertificate();
+ if (!cert.isNull() &&
+     cert.issuerInfo(QSslCertificate::OrganizationalUnitName).count() &&
+     cert.issuerInfo(QSslCertificate::Organization).count()) {
+   msg += QString("Server Certificate Issued by:\n"
+                  "%1\n%2\nCannot be verified\n")
+
 #if QT_VERSION >= 0x050000
-           .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName).at(0))
-           .arg(cert.issuerInfo(QSslCertificate::Organization).at(0));
+          .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName).at(0))
+          .arg(cert.issuerInfo(QSslCertificate::Organization).at(0));
 #else
-           .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName))
-           .arg(cert.issuerInfo(QSslCertificate::Organization));
+          .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName))
+          .arg(cert.issuerInfo(QSslCertificate::Organization));
 #endif
   }
+
   QListIterator<QSslError> it(errors);
   while (it.hasNext()) {
@@ -147,10 +151,9 @@
   if (_sslIgnoreErrors) {
     _outSocket->ignoreSslErrors();
-  }
-  else {
+  } else {
     deleteSafely();
   }
 }
-*/
+
 
 // Endless Loop
@@ -170,8 +173,9 @@
           _outSocket->write(_outBuffer);
           _outSocket->flush();
-        }
-        else {
-          QString chunkSize = QString("%1").arg(_outBuffer.size(),0,16,QLatin1Char('0'));
-          QByteArray chunkedData = chunkSize.toLatin1() + "\r\n" + _outBuffer + "\r\n";
+        } else {
+          QString chunkSize = QString("%1").arg(_outBuffer.size(), 0, 16,
+              QLatin1Char('0'));
+          QByteArray chunkedData = chunkSize.toLatin1() + "\r\n" + _outBuffer
+              + "\r\n";
           _outSocket->write(chunkedData);
           _outSocket->flush();
@@ -186,6 +190,5 @@
       }
       msleep(100); //sleep 0.1 sec
-    }
-    else {
+    } else {
       sleep(_rate);
     }
@@ -196,4 +199,7 @@
 ////////////////////////////////////////////////////////////////////////////
 void bncUploadCaster::open() {
+  const int timeOut = 5000;  // 5 seconds
+  QByteArray msg;
+  bncSslConfig sslConfig;
 
   if (_mountpoint.isEmpty()) {
@@ -204,95 +210,155 @@
     if (_outSocket->state() == QAbstractSocket::ConnectedState) {
       return;
-    }
-    else {
-      emit(newMessage("Broadcaster: No connection for " + _mountpoint.toLatin1(), true));
-    }
-  }
-
-  delete _outSocket; _outSocket = 0;
-
-  double minDt = pow(2.0,_sOpenTrial);
+    } else {
+      emit(newMessage(
+          "Broadcaster: No connection for " + _mountpoint.toLatin1(), true));
+    }
+  }
+  delete _outSocket;
+  _outSocket = 0;
+
+  double minDt = pow(2.0, _sOpenTrial);
   if (++_sOpenTrial > 4) {
     _sOpenTrial = 4;
   }
-  if (_outSocketOpenTime.isValid() &&
-      _outSocketOpenTime.secsTo(QDateTime::currentDateTime()) < minDt) {
+  if (_outSocketOpenTime.isValid()
+      && _outSocketOpenTime.secsTo(QDateTime::currentDateTime()) < minDt) {
     return;
-  }
-  else {
+  } else {
     _outSocketOpenTime = QDateTime::currentDateTime();
   }
 
   _outSocket = new QSslSocket();
-  const int timeOut = 5000;  // 5 seconds
-  if (_sslIgnoreErrors) {
-    _outSocket->ignoreSslErrors();
-  }
+  _outSocket->setSslConfiguration(sslConfig);
+  connect(_outSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>)));
   _outSocket->setProxy(QNetworkProxy::NoProxy);
-  _outHost = _casterOutHost;
-  _outPort = _casterOutPort;
+
   if (_proxy) {
-    _outHost = _proxyHost;
-    _outPort = _proxyPort;
-      connect(_outSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
-            this, SLOT(slotProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
-      if (_ntripVersion == "1") {
-        emit(newMessage("No proxy support in Ntrip Version 1 upload!",true));
-      }
-  }
-
-  if (!_secure  || _proxy) {
-    _outSocket->connectToHost(_outHost, _outPort);
-    if (!_outSocket->waitForConnected(timeOut)) {
-      emit(newMessage("Broadcaster: Connect timeout for " + _mountpoint.toLatin1()
-           + " (" + _outHost.toLatin1()+ ":" + QString("%1) ").arg(_outPort).toLatin1()
-           + _outSocket->errorString().toLatin1(), true));
+    if (_ntripVersion == "1") {
+      emit(newMessage("No proxy support in Ntrip Version 1 upload!", true));
       delete _outSocket;
       _outSocket = 0;
       return;
     }
-  }
-  else {
-   _outSocket->connectToHostEncrypted(_outHost, _outPort);
-   if (!_outSocket->waitForEncrypted(timeOut)) {
-     emit(newMessage("Broadcaster: Connect timeout for " + _mountpoint.toLatin1()
-          + " (" + _outHost.toLatin1()+ ":" + QString("%1) ").arg(_outPort).toLatin1()
-          + _outSocket->errorString().toLatin1(), true));
-     delete _outSocket;
-     _outSocket = 0;
-     return;
-   }
- }
-
-  QByteArray msg;
+    connect(_outSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
+            this,SLOT(slotProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
+
+    if (!connectToHost(_proxyOutHost, _proxyOutPort, false)) {
+      return;
+    }
+
+    if (_secure) {
+      msg = "CONNECT " + _casterOutHost.toLatin1() + ":"
+          + QString("%1").arg(_casterOutPort).toLatin1() + " HTTP/1.1\r\n"
+          + "Proxy-Connection: Keep-Alive\r\n"
+          + "Host: " + _casterOutHost.toLatin1() + "\r\n"
+          + "User-Agent: NTRIP BNC/" BNCVERSION " (" + BNC_OS + ")\r\n"
+          + "\r\n";      cout << msg.toStdString().c_str();
+      _outSocket->write(msg);
+      _outSocket->waitForBytesWritten();
+      _outSocket->waitForReadyRead();
+      QByteArray ans = _outSocket->readLine();      cout << ans.toStdString().c_str() << endl;
+      if (ans.indexOf("200") == -1) {
+        emit(newMessage(
+            "Proxy: Connection broken for " + _mountpoint.toLatin1()
+                + ": " + ans.left(ans.length() - 2), true));
+        delete _outSocket;
+        _outSocket = 0;
+        return;
+      } else {
+        emit(newMessage(
+            "Proxy: Connection opened for " + _mountpoint.toLatin1()
+                + ": " + ans.left(ans.length() - 2), true));
+        _sOpenTrial = 0;
+        _outSocket->setPeerVerifyName(_casterOutHost);
+        _outSocket->startClientEncryption();
+        if (!_outSocket->waitForEncrypted(timeOut)) {
+          emit(newMessage(
+              "Proxy: Encrypt timeout for " + _mountpoint.toLatin1() + " ("
+                  + _casterOutHost.toLatin1() + ":"
+                  + QString("%1) ").arg(_casterOutPort).toLatin1()
+                  + _outSocket->errorString().toLatin1(), true));
+          delete _outSocket;
+          _outSocket = 0;
+          return;
+        } else {
+          emit(newMessage("Proxy: SSL handshake completed for " + _mountpoint.toLatin1(), true));
+        }
+      }
+    }
+  } else {
+    if (!connectToHost(_casterOutHost, _casterOutPort, _secure)) {
+      return;
+    }
+  }
+
   if (_ntripVersion == "1") {
-    msg = "SOURCE " + _password.toLatin1() + " /" + _mountpoint.toLatin1() + "\r\n" +
-          "Source-Agent: NTRIP BNC/" BNCVERSION "\r\n\r\n";
-  }
-  else {
-    msg = "POST " + _postExtension.toLatin1() + "/" + _mountpoint.toLatin1() + " HTTP/1.1\r\n" +
-          "Host: " + _casterOutHost.toLatin1() + "\r\n" +
-          "Ntrip-Version: Ntrip/2.0\r\n" +
-          "Authorization: Basic " + (_userName + ":" + _password).toLatin1().toBase64() + "\r\n" +
-          "User-Agent: NTRIP BNC/" BNCVERSION " (" + BNC_OS + ")\r\n" +
-          "Connection: close\r\n" +
-          "Transfer-Encoding: chunked\r\n\r\n";
+    msg = "SOURCE " + _password.toLatin1() + " /" + _mountpoint.toLatin1()
+        + "\r\n" + "Source-Agent: NTRIP BNC/" BNCVERSION "\r\n\r\n";
+  } else {
+    msg = "POST " + _postExtension.toLatin1() + "/" + _mountpoint.toLatin1()
+        + " HTTP/1.1\r\n" + "Host: " + _casterOutHost.toLatin1() + "\r\n"
+        + "Ntrip-Version: Ntrip/2.0\r\n" + "Authorization: Basic "
+        + (_userName + ":" + _password).toLatin1().toBase64() + "\r\n"
+        + "User-Agent: NTRIP BNC/" BNCVERSION " (" + BNC_OS + ")\r\n"
+        + "Connection: close\r\n" + "Transfer-Encoding: chunked\r\n\r\n";
   }
   cout << msg.toStdString().c_str();
   _outSocket->write(msg);
   _outSocket->waitForBytesWritten();
-
   _outSocket->waitForReadyRead();
-  QByteArray ans = _outSocket->readLine();cout << ans.toStdString().c_str() << endl;
-
-  if (ans.indexOf("OK") == -1) {
+
+  QByteArray ans = _outSocket->readLine();  cout << ans.toStdString().c_str() << endl;
+
+  if (ans.indexOf("200") == -1) {
     delete _outSocket;
     _outSocket = 0;
-    emit(newMessage("Broadcaster: Connection broken for " + _mountpoint.toLatin1() + ": " + ans.left(ans.length()-2), true));
-  }
-  else {
-    emit(newMessage("Broadcaster: Connection opened for " + _mountpoint.toLatin1() + ": " + ans.left(ans.length()-2), true));
+    emit(newMessage(
+        "Broadcaster: Connection broken for " + _mountpoint.toLatin1() + ": "
+            + ans.left(ans.length() - 2), true));
+  } else {
+    emit(newMessage(
+        "Broadcaster: Connection opened for " + _mountpoint.toLatin1() + ": "
+            + ans.left(ans.length() - 2), true));
     _sOpenTrial = 0;
   }
 }
 
+// Try connection to NTRIP Caster or Proxy
+////////////////////////////////////////////////////////////////////////////
+bool bncUploadCaster::connectToHost(QString outHost, int outPort, bool encrypted) {
+  const int timeOut = 5000;  // 5 seconds
+  if (encrypted) {
+    _outSocket->connectToHostEncrypted(outHost, outPort);
+    if (!_outSocket->waitForEncrypted(timeOut)) {
+      emit(newMessage(
+          "Broadcaster: Connect timeout for " + _mountpoint.toLatin1() + " ("
+              + outHost.toLatin1() + ":"
+              + QString("%1) ").arg(outPort).toLatin1()
+              + _outSocket->errorString().toLatin1(), true));
+      delete _outSocket;
+      _outSocket = 0;
+      return false;
+    }
+  } else {
+    _outSocket->connectToHost(outHost, outPort);
+    if (!_outSocket->waitForConnected(timeOut)) {
+      emit(newMessage(
+          "Broadcaster: Connect timeout for " + _mountpoint.toLatin1() + " ("
+              + outHost.toLatin1() + ":"
+              + QString("%1) ").arg(outPort).toLatin1()
+              + _outSocket->errorString().toLatin1(), true));
+      delete _outSocket;
+      _outSocket = 0;
+      return false;
+    }
+  }
+  return true;
+}
+
+
+
+
+
+
+
