/* # 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 #include 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)) { qDebug("Message empty. Ignored."); 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() { 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(); }