diff options
| author | Sebastian | 2010-05-12 19:42:27 +0200 |
|---|---|---|
| committer | Sebastian | 2010-05-12 19:42:27 +0200 |
| commit | ce3329047d378a14006ce74ec273ac59e3375303 (patch) | |
| tree | 782430f270b4c7aca1b35d5b7813518e3797c555 /src/net/pvsClientConnection.cpp | |
| download | pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.gz pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.xz pvs-ce3329047d378a14006ce74ec273ac59e3375303.zip | |
initial import of latest svn version
Diffstat (limited to 'src/net/pvsClientConnection.cpp')
| -rw-r--r-- | src/net/pvsClientConnection.cpp | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/net/pvsClientConnection.cpp b/src/net/pvsClientConnection.cpp new file mode 100644 index 0000000..dff40d5 --- /dev/null +++ b/src/net/pvsClientConnection.cpp @@ -0,0 +1,178 @@ +/* +# Copyright (c) 2009,2010 - OpenSLX Project, Computer Center University of +# Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# pvsClientConnection.cpp +# - ???. +# ----------------------------------------------------------------------------- +*/ + +#include "pvsClientConnection.h" +#include "pvsListenServer.h" +#include "src/util/consoleLogger.h" + +#include <cassert> +#include <QtNetwork/QHostAddress> + + +PVSClientConnection::PVSClientConnection(PVSListenServer* server, QSslSocket* sock) +{ + assert(sock); + assert(server); + _socket = sock; + _incomplete = NULL; + _toldDisconnect = false; + _server = server; + _lastData = time(NULL); + sock->setParent(this); // for automatic deletion + 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))); +} + +PVSClientConnection::~PVSClientConnection() +{ + this->closeConnection(); + if (_incomplete != NULL) delete _incomplete; + if (_socket != NULL) + { + disconnect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival())); + disconnect(_socket, SIGNAL(disconnected()), this, SLOT(sock_closed())); + disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sock_error(QAbstractSocket::SocketError))); + _socket->abort(); + } +} + +void PVSClientConnection::closeConnection() +{ + if (_toldDisconnect) return; // we already got served + if (_socket == NULL || _socket->state() == QAbstractSocket::UnconnectedState) + { + // should not happen but handled anyway + _toldDisconnect = true; + _server->disconnectClient(this); + return; + } + if (_socket->state() == QAbstractSocket::ClosingState) return; // sock_close() slot should eventually be called, nothing to do + if (_socket->state() == QAbstractSocket::ConnectedState) // this is what should be the case normally + { + _socket->disconnectFromHost(); // graceful shutdown of socket, sock_close() will be called once complete + return; + } + // otherwise the socket is in some unknown state, so do a harsh shutdown + _socket->abort(); + _toldDisconnect = true; + _server->disconnectClient(this); +} + +void PVSClientConnection::sock_dataArrival() +{ + if (_socket == NULL || _socket->state() != QAbstractSocket::ConnectedState) + { + ConsoleLog writeError("dataArrival called in bad state"); + return; + } + + _lastData = time(NULL); + 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->closeConnection(); + return; + } + if (retval == 1) // message is complete + { + _server->handleClientMsg(_id, *_incomplete); + delete _incomplete; // ...and delete... + _incomplete = NULL; // ...so the next msg can be parsed + } + } while (retval == 1); + } +} + +void PVSClientConnection::sock_closed() +{ + // should this be unreliable in some way i suggest using the signal "stateChanged()" instead + // and check if the state changed to unconnected. + if (_toldDisconnect) return; + _toldDisconnect = true; + _server->disconnectClient(this); +} + +void PVSClientConnection::sock_error(QAbstractSocket::SocketError errcode) +{ + this->closeConnection(); +} + +/* +void PVSClientConnection::push_back_receive(PVSMsg newMsg) +{ + _recQueue.push_back(newMsg); +} +*/ + +bool PVSClientConnection::push_back_send(PVSMsg newMsg) +{ + if (_socket == NULL || _socket->state() != QAbstractSocket::ConnectedState) return false; + newMsg.setSndID(_id); + int len; + char data[2000]; + char *tmp = data; + if (!newMsg.getBinaryData(tmp, len)) + { + printf("Message empty. Ignored.\n"); + return false; + } + QByteArray ba; + ba.append(tmp, len); + int ret = (int)_socket->write(ba); + //printf("Sent %d of %d bytes.\n", ret, len); + if (ret == -1) + { + this->closeConnection(); + return false; + } + return true; +} + +QSslSocket* PVSClientConnection::getSocket() +{ + return _socket; +} + +void PVSClientConnection::setID(unsigned int id) +{ + _id = id; + this->push_back_send(PVSMsg(PVSLOGIN, "ID", int2String(_id))); +} + +void PVSClientConnection::ping() +{ + // still needs flag/timer to check for a ping timeout (and a reply from the client) + this->push_back_send(PVSMsg(PVSCOMMAND, "PING", "HELLO?", _id)); +} + +QString PVSClientConnection::getAddress() +{ + if (_socket == NULL) return QString(); + return _socket->peerAddress().toString(); +} + +QString PVSClientConnection::getNameUser() +{ + return getUserName(); +} |
