summaryrefslogtreecommitdiffstats
path: root/src/net/pvsServerConnection.cpp
diff options
context:
space:
mode:
authorSebastian2010-05-12 19:42:27 +0200
committerSebastian2010-05-12 19:42:27 +0200
commitce3329047d378a14006ce74ec273ac59e3375303 (patch)
tree782430f270b4c7aca1b35d5b7813518e3797c555 /src/net/pvsServerConnection.cpp
downloadpvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.gz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.xz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.zip
initial import of latest svn version
Diffstat (limited to 'src/net/pvsServerConnection.cpp')
-rw-r--r--src/net/pvsServerConnection.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/net/pvsServerConnection.cpp b/src/net/pvsServerConnection.cpp
new file mode 100644
index 0000000..04a1ef6
--- /dev/null
+++ b/src/net/pvsServerConnection.cpp
@@ -0,0 +1,243 @@
+#include "pvsServerConnection.h"
+#include "src/util/consoleLogger.h"
+#include "src/util/util.h"
+#include "pvsMsg.h"
+#include "src/pvs.h"
+#include <QtNetwork/QHostAddress>
+#include "src/core/pvsChatClient.h"
+#include "src/util/serviceDiscoveryUtil.h"
+#include "src/net/pvsDiscoveredServer.h"
+//#define verbose
+
+PVSServerConnection::PVSServerConnection(PVS *parent) : QObject(parent)
+{
+ _client = parent;
+ _incomplete = NULL;
+ _socket = NULL;
+ _timerId = 0;
+ _timer = 0;
+ _wasConnected = false;
+ loadCommands();
+}
+
+inline void PVSServerConnection::timerStop()
+{
+ if (_timer == 0) return;
+ killTimer(_timer);
+ _timer = 0;
+}
+
+bool PVSServerConnection::connectToServer(PVSDiscoveredServer* server, QString passwd)
+{
+ QHostAddress host = server->getHost();
+ if (_socket != NULL && _socket->state() == QAbstractSocket::ConnectedState
+ && _socket->peerAddress() == host) return false;
+ int port = server->getPort();
+ if (port < 1 || port > 65535) port = SERVER_PORT_INT;
+ ConsoleLog writeNetwork("Connecting to host:");
+ ConsoleLog writeNetwork(host.toString().toUtf8().data());
+ timerStop();
+ if (_socket != NULL)
+ {
+ _socket->blockSignals(true);
+ _socket->abort();
+ _socket->deleteLater();
+ }
+ _name = server->getName();
+ _expectedFingerprint = server->getFingerprint();
+ _passwd = passwd;
+ _socket = new QSslSocket(this);
+ connect(_socket, SIGNAL(encrypted()), this, SLOT(sock_connected()));
+ connect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+ connect(_socket, SIGNAL(disconnected()), this, SLOT(sock_closed()));
+ connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sock_error(QAbstractSocket::SocketError)));
+ char tex[2000];
+ snprintf(tex, 2000, "Connecting to %s on port %d", host.toString().toUtf8().data(), (int)port);
+ ConsoleLog writeNetwork(tex);
+ connect(_socket,
+ SIGNAL(sslErrors(const QList<QSslError> &)),
+ this,
+ SLOT(sslErrors(const QList<QSslError> &))
+ );
+ _socket->connectToHostEncrypted(host.toString(), port);
+ if (_timer == 0) _timer = startTimer(10000);
+
+ return true; // we really don't know yet if it will succeed since its async
+}
+
+void PVSServerConnection::sslErrors ( const QList<QSslError> & errors )
+{
+ for (QList<QSslError>::const_iterator it = errors.begin(); it != errors.end(); it++)
+ {
+ QSslError err = *it;
+ printf("Connect SSL: %s\n", err.errorString().toUtf8().data());
+ if (err.error() == QSslError::HostNameMismatch) continue; // We don't pay attention to hostnames for validation
+ if (err.error() == QSslError::SelfSignedCertificate) continue; // Also, this will always be the case; we check the fingerprint later
+ ConsoleLog writeNetwork(err.errorString().toUtf8().data());
+ ConsoleLog writeNetwork("***** SSL ERROR, ABORTING *****");
+ return;
+ }
+ _socket->ignoreSslErrors();
+}
+
+void PVSServerConnection::disconnectFromServer()
+{
+ if (_socket == NULL) return;
+ _socket->disconnectFromHost();
+ handleDisconnectInternal();
+}
+
+void PVSServerConnection::timerEvent(QTimerEvent *event)
+{
+ if (_socket != NULL && _socket->state() == QAbstractSocket::ConnectedState) return;
+ // TODO: Check for ping timeout
+}
+
+void PVSServerConnection::sendMessage(PVSMsg newMessage)
+{
+ if (_socket == NULL || _socket->state() != QAbstractSocket::ConnectedState) return;
+ char *data;
+ int len;
+ newMessage.getBinaryData(data, len);
+ QByteArray qba(data, len);
+ _socket->write(qba);
+}
+
+void PVSServerConnection::ping()
+{
+ sendMessage(PVSMsg(PVSCOMMAND, "PING", "U THERE?"));;
+}
+
+QString PVSServerConnection::getServerName()
+{
+ if (!isConnected()) return QString();
+ return _name;
+}
+
+void PVSServerConnection::loadCommands()
+{
+ addLoginHandler("ID", this, &PVSServerConnection::onID);
+ addCommandHandler("PING", this, &PVSServerConnection::onPing);
+}
+
+void PVSServerConnection::onID(PVSMsg idmsg)
+{
+ _id = (unsigned int)string2Int(idmsg.getMessage());
+}
+
+void PVSServerConnection::onPing(PVSMsg pingmsg)
+{
+ if (pingmsg.getMessage().at(pingmsg.getMessage().size()-1) == '?')
+ {
+ sendMessage(PVSMsg(PVSCOMMAND, "PING", "HI!"));
+ }
+}
+
+void PVSServerConnection::handleClientMsg(PVSMsg receiver)
+{
+ // FIXME: @SimonR, this line cuase problems with pvs in daemon mode and dbus
+ //qDebug("Got Message for this client: [%c][%s][%s]\n", (char)receiver.getType(), receiver.getIdent().toUtf8().data(), receiver.getMessage().toUtf8().data());
+ if (receiver.getType() == PVSCOMMAND)
+ {
+ _commandDispatcher.fire(receiver.getIdent(), receiver);
+// ConsoleLog writeNetwork(QString("Received a command and handled it.").append(receiver.getIdent().append(QString(":").append(receiver.getMessage()))));
+ }
+ else if (receiver.getType() == PVSMESSAGE)
+ {
+ _chatDispatcher.fire(receiver.getIdent(), receiver);
+ ConsoleLog writeNetwork(QString("Received a chat message and handled it.").append(receiver.getIdent().append(QString(":").append(receiver.getMessage()))));
+ }
+ else if (receiver.getType() == PVSLOGIN)
+ {
+ _loginDispatcher.fire(receiver.getIdent(), receiver);
+// ConsoleLog writeNetwork(QString("Received a login and handled it. Ident: ").append(receiver.getIdent().append(QString(":")).append(receiver.getMessage())));
+ }
+ else if (receiver.getType() == PVSUNKNOWN)
+ {
+ ConsoleLog writeNetwork(QString("Received an unknown type. Ident : ").append(receiver.getIdent().append(QString(" : ").append(receiver.getMessage()))));
+ }
+}
+
+void PVSServerConnection::sock_dataArrival()
+{
+ if (_socket == NULL || _socket->state() != QAbstractSocket::ConnectedState)
+ {
+ ConsoleLog writeError("dataArrival called in bad state");
+ return;
+ }
+
+ while (_socket->bytesAvailable())
+ {
+ int retval = 0;
+ do
+ {
+ if (_incomplete == NULL) _incomplete = new PVSMsg(); // we need a pvsmsg object
+ retval = _incomplete->readMessage(_socket); // let the message read data from socket
+ if (retval == -1) // error parsing msg, disconnect client!
+ {
+ this->disconnectFromServer();
+ return;
+ }
+ if (retval == 1) // message is complete
+ {
+ this->handleClientMsg(*_incomplete);
+ delete _incomplete; // ...and delete...
+ _incomplete = NULL; // ...so the next msg can be parsed
+ }
+ } while (retval == 1);
+ }
+}
+
+void PVSServerConnection::sock_closed()
+{
+ // should this be unreliable in some way i suggest using the signal "stateChanged()" instead
+ // and check if the state changed to unconnected.
+ ConsoleLog writeNetwork("Socket was closed... oh well..");
+ handleDisconnectInternal();
+}
+
+void PVSServerConnection::sock_error(QAbstractSocket::SocketError errcode)
+{
+ char txt[204];
+ snprintf(txt, 200, "Connection error: %d", (int)errcode);
+ ConsoleLog writeNetwork(txt);
+ handleDisconnectInternal();
+}
+
+// Send to server username and loginname.
+void PVSServerConnection::sock_connected()
+{
+ QByteArray cert = _socket->peerCertificate().digest(QCryptographicHash::Sha1);
+ if (_expectedFingerprint != cert)
+ { // Nich mit mir, Freundchen!
+ disconnectFromServer();
+ // Maybe you want to inform the user that there was a certificate mismatch
+ // and that it is very possible that the CIA is trying to eavesdrop on the connection
+ return;
+ }
+ ConsoleLog writeNetwork("Connected!");
+ _wasConnected = true;
+ sendMessage(
+ PVSMsg(PVSLOGIN, "USERNAME", getFullUsername()+","+getenv("USER")));
+ sendMessage(
+ PVSMsg(PVSLOGIN, "PASSWORD", _passwd));
+ ConsoleLog writeNetwork("Sent Username and password.");
+
+ _client->onConnected(_name);
+}
+
+void PVSServerConnection::handleDisconnectInternal()
+{
+ _socket->blockSignals(true);
+ _socket->abort();
+ _socket->deleteLater();
+ _socket = NULL;
+ _name = QString();
+ _client->securityUnlock();
+ timerStop();
+ if (_wasConnected)
+ {
+ _wasConnected = false;
+ _client->onDisconnected();
+ }
+}