diff options
| author | Sebastien Braun | 2010-10-06 00:04:49 +0200 |
|---|---|---|
| committer | Sebastien Braun | 2010-10-06 00:04:49 +0200 |
| commit | f07fc3b426815e28fde23313242fbbb998a08d45 (patch) | |
| tree | ba9eda1a83135a1727d2d35661d6facabee53b95 /src | |
| parent | Fix recognition of letters in keyboard handler (diff) | |
| parent | Merge remote branch 'openslx/master' into mcastft (diff) | |
| download | pvs-f07fc3b426815e28fde23313242fbbb998a08d45.tar.gz pvs-f07fc3b426815e28fde23313242fbbb998a08d45.tar.xz pvs-f07fc3b426815e28fde23313242fbbb998a08d45.zip | |
Merge remote branch 'openslx/mcastft' into input
Conflicts:
CMakeLists.txt
i18n/pvs_ar_JO.ts
i18n/pvs_de_DE.ts
i18n/pvs_es_MX.ts
i18n/pvs_fr_FR.ts
i18n/pvs_pl_PL.ts
i18n/pvsmgr_ar_JO.ts
i18n/pvsmgr_de_DE.ts
i18n/pvsmgr_es_MX.ts
i18n/pvsmgr_fr_FR.ts
i18n/pvsmgr_pl_PL.ts
icons/README
pvsmgr.qrc
src/gui/mainWindow.cpp
src/pvs.cpp
src/pvs.h
src/pvsDaemon.cpp
src/util/clientGUIUtils.h
Diffstat (limited to 'src')
73 files changed, 5370 insertions, 1381 deletions
diff --git a/src/core/pvsConnectionManager.cpp b/src/core/pvsConnectionManager.cpp index 8a35ca9..5bf6418 100644 --- a/src/core/pvsConnectionManager.cpp +++ b/src/core/pvsConnectionManager.cpp @@ -218,6 +218,25 @@ void PVSConnectionManager::onCommand(PVSMsg command) break; } } + else if (ident == "MCASTFTANNOUNCE") + { + _pvsServer.sendToAll(command); + } + else if (ident == "MCASTFTRETRY") + { + QStringList fields = message.split(':'); + if (!fields.size() == 2) + { + qDebug() << "Malformed MCASTFTRETRY message:" << message; + return; + } + + PVSClient* client = getClientFromUsername(fields[0]); + if (client) + { + client->sendMessage(command); + } + } } void PVSConnectionManager::onChat(PVSMsg chatMsg) { diff --git a/src/gui/clientChatDialog.cpp b/src/gui/clientChatDialog.cpp index 7c32790..163ac92 100644 --- a/src/gui/clientChatDialog.cpp +++ b/src/gui/clientChatDialog.cpp @@ -29,8 +29,6 @@ ClientChatDialog::ClientChatDialog(QWidget *parent) : // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/chat", this); - dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); connect(_ifaceDBus, SIGNAL(chat_receive(QString, QString, QString)), this, SLOT(receive(QString, QString, QString))); diff --git a/src/gui/clientConfigDialog.cpp b/src/gui/clientConfigDialog.cpp index 76b4f5e..b7ba407 100644 --- a/src/gui/clientConfigDialog.cpp +++ b/src/gui/clientConfigDialog.cpp @@ -16,16 +16,33 @@ # ----------------------------------------------------------------------------- */ +#include <QtDebug> +#include <QNetworkInterface> +#include <QStandardItemModel> #include "clientConfigDialog.h" +#include <cerrno> +#include <cstdlib> +#include <cstring> +#include <src/net/pvsNetworkInterfaceListModel.h> + +using namespace std; ClientConfigDialog::ClientConfigDialog(QWidget *parent) : - QDialog(parent) + QDialog(parent), + _interfaceListModel(0) { setupUi(this); connect(this, SIGNAL(accepted()), this, SLOT(writeSettings())); connect(radioButtonOtherRO, SIGNAL(clicked()), this, SLOT(checkPermissions())); + _interfaceListModel = new PVSNetworkInterfaceListModel(this); + interfaceList->setModel(_interfaceListModel); + interfaceList->setModelColumn(0); + connect(reloadInterfaceListButton, SIGNAL(clicked()), _interfaceListModel, SLOT(reloadInterfaceList())); + // connect to D-Bus and get interface + QDBusConnection dbus = QDBusConnection::sessionBus(); + _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); } ClientConfigDialog::~ClientConfigDialog() @@ -49,50 +66,73 @@ void ClientConfigDialog::readSettings() else comboBox->setCurrentIndex(_settings.value("Display/location").toInt()); - if (_settings.value("Permissions/vnc_lecturer").toString() == "rw") - radioButtonLecturerRW->setChecked(true); - else if (_settings.value("Permissions/vnc_lecturer").toString() == "ro") - radioButtonLecturerRO->setChecked(true); - else - radioButtonLecturerNO->setChecked(true); - if (_settings.value("Permissions/vnc_other").toString() == "rw") - radioButtonOtherRW->setChecked(true); - else if (_settings.value("Permissions/vnc_other").toString() == "ro") - radioButtonOtherRO->setChecked(true); - else - radioButtonOtherNO->setChecked(true); - checkBoxAllowChat->setChecked( - _settings.value("Permissions/allow_chat").toBool()); - checkBoxAllowFiletransfer->setChecked(_settings.value( - "Permissions/allow_filetransfer").toBool()); - - qDebug("[%s] Setting read from: '%s'", metaObject()->className(), - qPrintable(_settings.fileName())); + QDBusPendingReply<QString> reply = _ifaceDBus->getConfigValue("multicast/interface"); + reply.waitForFinished(); + if (reply.isValid()) + { + interfaceList->setEditText(reply.value()); + } + + reply = _ifaceDBus->getConfigValue("Permissions/vnc_lecturer"); + reply.waitForFinished(); + if (reply.isValid()) + { + if (reply.value() == "rw") + radioButtonLecturerRW->setChecked(true); + else if (reply.value() == "ro") + radioButtonLecturerRO->setChecked(true); + else + radioButtonLecturerNO->setChecked(true); + } + + reply = _ifaceDBus->getConfigValue("Permissions/vnc_other"); + reply.waitForFinished(); + if (reply.isValid()) + { + if (reply.value() == "rw") + radioButtonOtherRW->setChecked(true); + else if (reply.value() == "ro") + radioButtonOtherRO->setChecked(true); + else + radioButtonOtherNO->setChecked(true); + } + + reply = _ifaceDBus->getConfigValue("Permissions/allow_chat"); + reply.waitForFinished(); + if (reply.isValid()) + checkBoxAllowChat->setChecked(reply.value() == "T"); + + reply = _ifaceDBus->getConfigValue("Permissions/allow_filetransfer"); + reply.waitForFinished(); + if (reply.isValid()) + checkBoxAllowFiletransfer->setChecked(reply.value() == "T"); } void ClientConfigDialog::writeSettings() { _settings.setValue("Display/location", comboBox->currentIndex()); + if (radioButtonLecturerRW->isChecked()) - _settings.setValue("Permissions/vnc_lecturer", "rw"); + _ifaceDBus->setConfigValue("Permissions/vnc_lecturer", "rw"); else if (radioButtonLecturerRO->isChecked()) - _settings.setValue("Permissions/vnc_lecturer", "ro"); + _ifaceDBus->setConfigValue("Permissions/vnc_lecturer", "ro"); else - _settings.setValue("Permissions/vnc_lecturer", "no"); + _ifaceDBus->setConfigValue("Permissions/vnc_lecturer", "no"); if (radioButtonOtherRW->isChecked()) - _settings.setValue("Permissions/vnc_other", "rw"); + _ifaceDBus->setConfigValue("Permissions/vnc_other", "rw"); else if (radioButtonOtherRO->isChecked()) - _settings.setValue("Permissions/vnc_other", "ro"); + _ifaceDBus->setConfigValue("Permissions/vnc_other", "ro"); else - _settings.setValue("Permissions/vnc_other", "no"); - _settings.setValue("Permissions/allow_chat", checkBoxAllowChat->isChecked()); - _settings.setValue("Permissions/allow_filetransfer", - checkBoxAllowFiletransfer->isChecked()); + _ifaceDBus->setConfigValue("Permissions/vnc_other", "no"); + + _ifaceDBus->setConfigValue("Permissions/allow_chat", + QString(checkBoxAllowChat->isChecked() ? "T" : "F")); + _ifaceDBus->setConfigValue("Permissions/allow_filetransfer", + QString(checkBoxAllowFiletransfer->isChecked() ? "T" : "F")); + _ifaceDBus->setConfigValue("multicast/interface", interfaceList->currentText()); + _settings.sync(); emit configChanged(); - - qDebug("[%s] Settings written to: '%s'.", metaObject()->className(), - qPrintable(_settings.fileName())); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gui/clientConfigDialog.h b/src/gui/clientConfigDialog.h index 706bd8a..fd7529e 100644 --- a/src/gui/clientConfigDialog.h +++ b/src/gui/clientConfigDialog.h @@ -15,8 +15,11 @@ #define CLIENTCONFIGDIALOG_H_ #include <QtGui> +#include "pvsinterface.h" #include "ui_clientConfigDialog.h" +class QAbstractItemModel; + class ClientConfigDialog: public QDialog, private Ui::ClientConfigDialogClass { Q_OBJECT @@ -37,7 +40,9 @@ private Q_SLOTS: void checkPermissions(); private: + OrgOpenslxPvsInterface *_ifaceDBus; QSettings _settings; + QAbstractItemModel* _interfaceListModel; }; diff --git a/src/gui/clientFileReceiveDialog.cpp b/src/gui/clientFileReceiveDialog.cpp index 669ca81..fc6a1a3 100644 --- a/src/gui/clientFileReceiveDialog.cpp +++ b/src/gui/clientFileReceiveDialog.cpp @@ -16,6 +16,9 @@ */ #include "clientFileReceiveDialog.h" +#include <pvsinterface.h> +#include <QFileInfo> +#include <limits.h> ClientFileReceiveDialog::ClientFileReceiveDialog(QTcpSocket *socket, QWidget *parent) : QDialog(parent) @@ -37,9 +40,44 @@ ClientFileReceiveDialog::ClientFileReceiveDialog(QTcpSocket *socket, QWidget *pa connect(this, SIGNAL(finished(int)), this, SLOT(deleteLater())); } +ClientFileReceiveDialog::ClientFileReceiveDialog(QString const& sender, qulonglong transferID, + QString const& filename, qulonglong size, OrgOpenslxPvsInterface* ifaceDBus, QWidget* parent) +{ + setupUi(this); + + _transferID = transferID; + _filename = filename; + _ifaceDBus = ifaceDBus; + _bytesToRead = size; + _socket = 0; + _file = 0; + div = 1; + while((size / div) > INT_MAX) + { + div <<= 1; + } + + connect(ifaceDBus, SIGNAL(incomingMulticastTransferStarted(qulonglong)), SLOT(mcastTransferStarted(qulonglong))); + connect(ifaceDBus, SIGNAL(incomingMulticastTransferProgress(qulonglong, qulonglong, qulonglong)), + SLOT(mcastTransferProgress(qulonglong, qulonglong, qulonglong))); + connect(ifaceDBus, SIGNAL(incomingMulticastTransferFinished(qulonglong)), SLOT(mcastTransferFinished(qulonglong))); + connect(ifaceDBus, SIGNAL(incomingMulticastTransferFailed(qulonglong, QString)), SLOT(mcastTransferFailed(qulonglong, QString))); + connect(cancelButton, SIGNAL(clicked()), SLOT(cancelTransfer())); + + qDebug("[%s] New multicast incoming transfer: %s from %s", metaObject()->className(), + filename.toLocal8Bit().constData(), sender.toLocal8Bit().constData()); + + + filenameLabel->setText(QFileInfo(filename).baseName()); + labelNick->setText(sender); + progressBar->setRange(0, 0); +} + + ClientFileReceiveDialog::~ClientFileReceiveDialog() { - _socket->deleteLater(); + if(_socket) + _socket->deleteLater(); qDebug("[%s] Deleted!", metaObject()->className()); } @@ -168,6 +206,61 @@ void ClientFileReceiveDialog::error(QAbstractSocket::SocketError error) close(); } +void ClientFileReceiveDialog::mcastTransferStarted(qulonglong transferID) +{ + if(transferID != _transferID) + return; +} + +void ClientFileReceiveDialog::mcastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of) +{ + if(transferID != _transferID) + return; + + progressBar->setRange(0, of); + progressBar->setValue(bytes); + + labelA->setText(formatSize(bytes)); + labelB->setText(formatSize(of)); +} + +void ClientFileReceiveDialog::mcastTransferFinished(qulonglong transferID) +{ + if(transferID != _transferID) + return; + + QString filename = QFileDialog::getSaveFileName(this, tr("Where should I save %1?").arg(_filename), _filename); + QFile* file = new QFile(_filename); + if(filename.isNull() || filename.isEmpty()) + { + file->remove(); + } + else + { + if(!file->rename(filename)) + { + QMessageBox::warning(this, tr("Could not rename file"), tr("Failed to rename %1 to %2").arg(_filename).arg(filename)); + } + } + accept(); + deleteLater(); +} + +void ClientFileReceiveDialog::mcastTransferFailed(qulonglong transferID, QString reason) +{ + if(transferID != _transferID) + return; + + QMessageBox::warning(this, tr("File transfer failed"), tr("File transfer failed for the following reason:\n%1").arg(reason)); + reject(); + deleteLater(); +} + +void ClientFileReceiveDialog::cancelTransfer() +{ + _ifaceDBus->cancelIncomingMulticastTransfer(_transferID); +} + QString ClientFileReceiveDialog::formatSize(qint64 size) { if (size >= 1000000000) // GB diff --git a/src/gui/clientFileReceiveDialog.h b/src/gui/clientFileReceiveDialog.h index c13d7b7..c9ed220 100644 --- a/src/gui/clientFileReceiveDialog.h +++ b/src/gui/clientFileReceiveDialog.h @@ -18,6 +18,8 @@ #include <QtNetwork> #include "ui_clientFileReceiveDialog.h" +class OrgOpenslxPvsInterface; + class ClientFileReceiveDialog: public QDialog, private Ui::ClientFileReceiveDialogClass { @@ -25,6 +27,7 @@ Q_OBJECT public: ClientFileReceiveDialog(QTcpSocket *socket, QWidget *parent = 0); + ClientFileReceiveDialog(QString const& sender, qulonglong transferID, QString const& basename, qulonglong size, OrgOpenslxPvsInterface* ifaceDBus, QWidget* parent = 0); ~ClientFileReceiveDialog(); private Q_SLOTS: @@ -33,6 +36,13 @@ private Q_SLOTS: void close(); void error(QAbstractSocket::SocketError error); + // multicast: + void mcastTransferStarted(qulonglong transferID); + void mcastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of); + void mcastTransferFinished(qulonglong transferID); + void mcastTransferFailed(qulonglong transferID, QString reason); + void cancelTransfer(); + private: void sendAck(bool b); QString formatSize(qint64 size); @@ -42,6 +52,10 @@ private: qint64 _bytesToRead; int div; + // multicast: + OrgOpenslxPvsInterface* _ifaceDBus; + QString _filename; + qulonglong _transferID; }; #endif /* CLIENTFILERECEIVEDIALOG_H_ */ diff --git a/src/gui/clientFileSendDialog.cpp b/src/gui/clientFileSendDialog.cpp index ccb44b3..93da725 100644 --- a/src/gui/clientFileSendDialog.cpp +++ b/src/gui/clientFileSendDialog.cpp @@ -22,14 +22,16 @@ ClientFileSendDialog::ClientFileSendDialog(QWidget *parent) : { setupUi(this); + _transferID = 0; + _error = false; + _isMulticast = false; + _file = NULL; _socket = NULL; _clientNicklistDialog = new ClientNicklistDialog(this); // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/filesend", this); - dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); // get current users name from backend @@ -60,7 +62,15 @@ void ClientFileSendDialog::open() reject(); return; } - open(_clientNicklistDialog->getNick()); + + if (_clientNicklistDialog->isSendToAll()) + { + sendToAll(); + } + else + { + open(_clientNicklistDialog->getNick()); + } } void ClientFileSendDialog::open(QString nick) @@ -75,6 +85,70 @@ void ClientFileSendDialog::open(QString nick) open(nick, filename); } +void ClientFileSendDialog::sendToAll() +{ + QString filename = QFileDialog::getOpenFileName(this, tr("Send File"), QDir::homePath(), ""); + if (filename == "") + { + reject(); + return; + } + sendToAll(filename); +} + +void ClientFileSendDialog::sendToAll(QString filename) +{ + _isMulticast = true; + + connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferStarted(qulonglong)), SLOT(multicastTransferStarted(qulonglong))); + connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferProgress(qulonglong,qulonglong,qulonglong)), SLOT(multicastTransferProgress(qulonglong, qulonglong, qulonglong))); + connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferFinished(qulonglong)), SLOT(multicastTransferFinished(qulonglong))); + connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferFailed(qulonglong, QString const&)), SLOT(multicastTransferFailed(qulonglong, QString const&))); + + filenameLabel->setText(filename); + progressBar->setRange(0, 0); + labelNick->setText(tr("all")); + labelStatus->setText(tr("Waiting to start")); + + QString errorMessage("Backend error"); + + // We need to jump through a lot of hoops because this call is prone to time out, and + // QtDBus does not support specifying timeouts in generated interfaces. + QDBusMessage call = QDBusMessage::createMethodCall("org.openslx.pvs", "/", "org.openslx.pvs", "createMulticastTransfer"); + call << filename; + + QDBusMessage reply = _ifaceDBus->connection().call(call, QDBus::Block, 5000); + if (reply.type() == QDBusMessage::ErrorMessage) + { + QMessageBox::critical(this, tr("File Send error"), tr("Error communicating with backend: %1: %2").arg(reply.errorName()).arg(reply.errorMessage())); + reject(); + return; + } + else if (reply.type() == QDBusMessage::InvalidMessage) + { + QMessageBox::critical(this, tr("File Send error"), tr("Something went wrong while communicating with backend, but I don't know what.")); + reject(); + return; + } + else if (reply.type() == QDBusMessage::ReplyMessage) + { + QList<QVariant> args = reply.arguments(); + bool created = args.at(0).toBool(); + _transferID = args.at(1).toULongLong(); + QString errorMessage = args.at(2).toString(); + if (!created) + { + QMessageBox::critical(this, tr("File Send error"), tr("Could not create a multicast transfer: %1").arg(errorMessage)); + reject(); + return; + } + } + + connect(cancelButton, SIGNAL(clicked()), SLOT(canceled())); + + show(); +} + void ClientFileSendDialog::open(QString nick, QString filename) { // open file @@ -129,6 +203,8 @@ void ClientFileSendDialog::receiveAck() QString ack = QString::fromUtf8(_socket->readLine()); if (ack != "ok\n") { + _error = true; + _reason = tr("Receiver declined"); qDebug("[%s] Received nack!", metaObject()->className()); close(); return; @@ -160,27 +236,30 @@ void ClientFileSendDialog::sendFile() void ClientFileSendDialog::close() { - if (_file && _file->isOpen()) + if (!_isMulticast) { - _file->close(); - qDebug("[%s] File closed.", metaObject()->className()); + if (_file && _file->isOpen()) + { + _file->close(); + qDebug("[%s] File closed.", metaObject()->className()); + } + + if (_socket && _socket->isOpen()) + { + disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck())); + disconnect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile())); + disconnect(_socket, SIGNAL(disconnected()), this, SLOT(close())); + disconnect(_socket, SIGNAL(connected()), this, SLOT(sendHeader())); + disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(error(QAbstractSocket::SocketError))); + _socket->disconnectFromHost(); + qDebug("[%s] Connection closed.", metaObject()->className()); + } } - if (_socket && _socket->isOpen()) - { - disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck())); - disconnect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile())); - disconnect(_socket, SIGNAL(disconnected()), this, SLOT(close())); - disconnect(_socket, SIGNAL(connected()), this, SLOT(sendHeader())); - disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(error(QAbstractSocket::SocketError))); - _socket->disconnectFromHost(); - qDebug("[%s] Connection closed.", metaObject()->className()); - } - - disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(close())); + disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(canceled())); - if (_bytesToWrite == 0) + if (!_error) { accept(); QMessageBox::information(0, tr("PVS - File Transfer"), @@ -190,12 +269,26 @@ void ClientFileSendDialog::close() { reject(); QMessageBox::warning(0, tr("PVS - File Transfer"), - tr("File Transfer canceled!")); + tr("File Transfer canceled: %1").arg(_reason)); + } +} + +void ClientFileSendDialog::canceled() +{ + if(_isMulticast) + { + _ifaceDBus->cancelOutgoingMulticastTransfer(_transferID); } + + _error = true; + _reason = tr("You clicked 'Cancel'"); + close(); } void ClientFileSendDialog::error(QAbstractSocket::SocketError error) { + _error = true; + _reason = tr("Socket Error"); qDebug("[%s] Socket error: %i", metaObject()->className(), error); close(); } @@ -212,6 +305,55 @@ QString ClientFileSendDialog::formatSize(qint64 size) return QString("%1B").arg((qreal)size, 0, 'f',1); } +void ClientFileSendDialog::multicastTransferStarted(qulonglong transferID) +{ + qDebug() << "multicastTransferStarted(" << transferID << ")"; + if (transferID != _transferID) + { + return; + } + labelStatus->setText("Started"); +} + +void ClientFileSendDialog::multicastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of) +{ + qDebug() << "multicastTransferProgress(" << transferID << bytes << of << ")"; + if (transferID != _transferID) + { + return; + } + + if(bytes < of) + { + labelStatus->setText("Transferring"); + progressBar->setRange(0, of); + progressBar->setValue(bytes); + } + else + { + labelStatus->setText("Waiting to finish"); + progressBar->setRange(0, 0); + } + + labelA->setText(formatSize(bytes)); + labelB->setText(formatSize(of)); +} + +void ClientFileSendDialog::multicastTransferFinished(quint64 transferID) +{ + qDebug() << "multicastTransferFinished(" << transferID << ")"; + qDebug("[%s] MulticastTransfer finished", metaObject()->className()); + close(); +} + +void ClientFileSendDialog::multicastTransferFailed(quint64 transferID, QString const& reason) +{ + qDebug() << "multicastTransferFailed(" << transferID << reason << ")"; + _error = true; + _reason = reason; + close(); +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -235,6 +377,25 @@ ClientNicklistDialog::ClientNicklistDialog(QWidget *parent) : listWidget->addItems(nicknames); listWidget->setCurrentRow(0); + + connect(sendToAllCheckBox, SIGNAL(stateChanged(int)), SLOT(sendToAllStateChanged(int))); + + sendToAllCheckBox->setCheckState(Qt::Unchecked); + _isSendToAll = false; +} + +void ClientNicklistDialog::sendToAllStateChanged(int state) +{ + if (state) + { + listWidget->setEnabled(false); + _isSendToAll = true; + } + else + { + listWidget->setEnabled(true); + _isSendToAll = false; + } } ClientNicklistDialog::~ClientNicklistDialog() diff --git a/src/gui/clientFileSendDialog.h b/src/gui/clientFileSendDialog.h index d8afc3a..7abdcc7 100644 --- a/src/gui/clientFileSendDialog.h +++ b/src/gui/clientFileSendDialog.h @@ -30,9 +30,17 @@ public: ~ClientNicklistDialog(); QString getNick(); + bool isSendToAll() const + { + return _isSendToAll; + } + +private Q_SLOTS: + void sendToAllStateChanged(int state); private: OrgOpenslxPvsInterface *_ifaceDBus; + bool _isSendToAll; }; @@ -51,14 +59,22 @@ public: void open(); void open(QString nick); void open(QString nick, QString filename); + void sendToAll(); + void sendToAll(QString filename); private Q_SLOTS: void sendHeader(); void receiveAck(); void sendFile(); void close(); + void canceled(); void error(QAbstractSocket::SocketError error); + void multicastTransferStarted(qulonglong transferID); + void multicastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of); + void multicastTransferFinished(qulonglong transferID); + void multicastTransferFailed(qulonglong transferID, QString const& reason); + private: QString formatSize(qint64 size); @@ -71,6 +87,11 @@ private: OrgOpenslxPvsInterface *_ifaceDBus; QString _nickname; + quint64 _transferID; + bool _error; + QString _reason; + bool _isMulticast; + }; #endif /* CLIENTFILESENDDIALOG_H_ */ diff --git a/src/gui/clientVNCViewer.cpp b/src/gui/clientVNCViewer.cpp index d6a218b..d794b0b 100644 --- a/src/gui/clientVNCViewer.cpp +++ b/src/gui/clientVNCViewer.cpp @@ -22,8 +22,6 @@ ClientVNCViewer::ClientVNCViewer(QWidget *parent) : { // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/vnc", this); - dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); connect(_ifaceDBus, SIGNAL(project(QString, int, QString, bool, bool, int)), this, SLOT(open(QString, int, QString, bool, bool, int))); diff --git a/src/gui/mainWindow.cpp b/src/gui/mainWindow.cpp index 8a2b512..0f2fd0e 100644 --- a/src/gui/mainWindow.cpp +++ b/src/gui/mainWindow.cpp @@ -10,13 +10,16 @@ # General information about OpenSLX can be found at http://openslx.org/ # ----------------------------------------------------------------------------- # mainWindow.cpp - This is the Main class for the pvsManager. The GUI is contructed here. + This is the Main class for the pvsManager. The GUI is contructed here. # ----------------------------------------------------------------------------- */ #include <QtGui> #include <QFileDialog> +#include <QBuffer> +#include <QDataStream> #include <src/gui/mainWindow.h> +#include <src/net/mcast/McastConfiguration.h> using namespace std; // setting the IF-DEF Block for the touchgui and the normal gui, for later use @@ -34,134 +37,138 @@ using namespace std; #include <src/gui/profileDialog.h> //#include <src/gui/dialog.h> #include <src/core/pvsConnectionManager.h> +#include <src/gui/multicastConfigDialog.h> #include <iostream> MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), ui(new Ui::MainWindow) + QMainWindow(parent), ui(new Ui::MainWindow) { + ui->setupUi(this); - ui->setupUi(this); + if (!QFile::exists(_settings.fileName())) + { + QDir::root().mkpath(QFileInfo(_settings.fileName()).path()); + QFile::copy("/etc/openslx/pvsmgr.conf", _settings.fileName()); + } - ui->horizontalSlider->setValue(100); - ui->label_2->setText("100"); + ui->horizontalSlider->setValue(100); + ui->label_2->setText("100"); - ui->separator->setVisible(false); + ui->separator->setVisible(false); - myself = this; - conWin = new ConnectionWindow(ui->widget); - ui->VconWinLayout->addWidget(conWin); - conList = new ConnectionList(ui->ClWidget); - ui->ClientGLayout->addWidget(conList); + myself = this; + conWin = new ConnectionWindow(ui->widget); + ui->VconWinLayout->addWidget(conWin); + conList = new ConnectionList(ui->ClWidget); + ui->ClientGLayout->addWidget(conList); - bgimage = false; + bgimage = false; - _aboutDialog = new AboutDialog(this); + _aboutDialog = new AboutDialog(this); - PVSConnectionManager::getManager(); + PVSConnectionManager::getManager(); - //set the maximum width for list content - ui->ClWidget->setMaximumWidth(160); + //set the maximum width for list content + ui->ClWidget->setMaximumWidth(160); - ui->pvsLog->setReadOnly(true); - ui->pvsLog->hide(); + ui->pvsLog->setReadOnly(true); + ui->pvsLog->hide(); - onToggleLog(false); - // add ourself to the log listeners, so we can output them too - ConsoleLog addListener(this, &MainWindow::on_log_line); + onToggleLog(false); + // add ourself to the log listeners, so we can output them too + ConsoleLog addListener(this, &MainWindow::on_log_line); - _firstResize = 1; - _oldRatio = "100"; - _isThumbnailrate = false; - is_closeup = false; - is_fullscreen = false; - _isLockAll = false; - locked = false; + _firstResize = 1; + _oldRatio = "100"; + _isThumbnailrate = false; + is_closeup = false; + is_fullscreen = false; + _isLockAll = false; + locked = false; - /* - * _sessionName: The session name for this Connection - * _pwdCon: Password needed to connect to the session with the name _sessionName - */ - _pwdCon = PVSConnectionManager::getManager()->setNeedPassword(false); - _sessionName = PVSConnectionManager::getManager()->getSessionName(); + /* + * _sessionName: The session name for this Connection + * _pwdCon: Password needed to connect to the session with the name _sessionName + */ + _pwdCon = PVSConnectionManager::getManager()->setNeedPassword(false); + _sessionName = PVSConnectionManager::getManager()->getSessionName(); - ui->setPassword->setCheckState(Qt::Checked); + ui->setPassword->setCheckState(Qt::Checked); #ifdef MAINWINDOW_USE_TOUCHGUI //only used for the touchgui + // define the slots we want to use + connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox1(int))); // Combobox 1 verknüpfen mit IndexChangend Signal + connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(setindexback())); - // define the slots we want to use - connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox1(int))); // Combobox 1 verknüpfen mit IndexChangend Signal - connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(setindexback())); - - - connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(createProfile())); // profile button - connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(clientlisthide())); // clienlist button - - // toolbar slots - connect(ui->actionresetall, SIGNAL(triggered()), this, SLOT(resetall())); - connect(ui->actionLocksingle, SIGNAL(triggered()), this, SLOT(locksingle())); - connect(ui->actionUnlocksingle, SIGNAL(triggered()), this, SLOT(unlocksingle())); - connect(ui->actionProjection, SIGNAL(triggered()), this, SLOT(projecttoolbar())); - connect(ui->actionUnprojection, SIGNAL(triggered()), this, SLOT(unprojecttoolbar())); - connect(ui->actionDozent, SIGNAL(triggered()), this, SLOT(setdozenttoolbar())); + connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(createProfile())); // profile button + connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(clientlisthide())); // clienlist button - // Ui specific settings + // toolbar slots + connect(ui->actionresetall, SIGNAL(triggered()), this, SLOT(resetall())); + connect(ui->actionLocksingle, SIGNAL(triggered()), this, SLOT(locksingle())); + connect(ui->actionUnlocksingle, SIGNAL(triggered()), this, SLOT(unlocksingle())); + connect(ui->actionProjection, SIGNAL(triggered()), this, SLOT(projecttoolbar())); + connect(ui->actionUnprojection, SIGNAL(triggered()), this, SLOT(unprojecttoolbar())); + connect(ui->actionDozent, SIGNAL(triggered()), this, SLOT(setdozenttoolbar())); + connect(ui->actionShowProcesses, SIGNAL(triggered()), this, SLOT(showProcesses())); - ui->ClWidget->hide(); - ui->progressBar->hide(); - ui->pvsLog->hide(); + // Ui specific settings + ui->ClWidget->hide(); + ui->progressBar->hide(); + ui->pvsLog->hide(); #endif - - // toolbar and actions in pvsmgr - connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(close())); - ui->action_Exit->setStatusTip(tr("Exit")); - connect(ui->action_Disconnect, SIGNAL(triggered()), this, SLOT(disconnect())); - ui->action_Disconnect->setStatusTip(tr("Remove the vnc-Connection for the selected client(s)")); - ui->action_Disconnect->setVisible(false);//we need it only for debug - connect(ui->actionView, SIGNAL(triggered()), this, SLOT(closeUp())); - ui->actionView->setStatusTip(tr("Show the selected client in the whole window")); - connect(ui->actionFoto, SIGNAL(triggered()), this, SLOT(foto())); - connect(ui->actionLock, SIGNAL(triggered()), this, SLOT(lockalltoolbar())); - connect(ui->actionChat, SIGNAL(triggered()), this, SLOT(startChatDialog())); - ui->actionFoto->setStatusTip(tr("Make a screenshot for the selected client(s)")); - ui->actionLock->setStatusTip(tr("Lock or Unlock all Clients")); - connect(ui->actionCreate_profile, SIGNAL(triggered()), this, SLOT(createProfile())); - - connect(ui->actionShow_Username, SIGNAL(triggered()), this, SLOT(showusername())); - connect(ui->actionShow_Hostname_IP, SIGNAL(triggered()), this, SLOT(showip())); - connect(ui->actionShow_Fullname, SIGNAL(triggered()), this, SLOT(showname())); - connect(ui->horizontalSlider, SIGNAL(valueChanged (int)), this, SLOT(changeRatio(int))); - connect(ui->setPassword, SIGNAL(stateChanged (int)), this, SLOT(setPasswordForConnection(int))); - connect(ui->vncQuality, SIGNAL(currentIndexChanged (int)), this, SLOT(setVNCQuality(int))); - connect(ui->thumbStatus, SIGNAL(currentIndexChanged(int)), this, SLOT(changeStatus(int))); - connect(ui->actionShow_Log, SIGNAL(toggled(bool)), this, SLOT(setLogConsoleDisabled(bool))); - connect(ui->actionShow_Network, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); - connect(ui->actionShow_Chat, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); - connect(ui->actionShow_Terminal, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); - connect(ui->actionShow_Normal, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); - connect(ui->actionShow_Error, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); - connect(ui->actionAbout_pvs, SIGNAL(triggered()), _aboutDialog, SLOT(open())); - - loadSettings(); //we load the appliocation settings - - setUnifiedTitleAndToolBarOnMac(true); - statusBar()->showMessage(tr("The pvs manager")); - this->showMaximized(); // show the Mainwindow maximized - - // listen on port 29481 for incoming file transfers + // toolbar and actions in pvsmgr + connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(close())); + ui->action_Exit->setStatusTip(tr("Exit")); + connect(ui->action_Disconnect, SIGNAL(triggered()), this, SLOT(disconnect())); + ui->action_Disconnect->setStatusTip(tr("Remove the vnc-Connection for the selected client(s)")); + ui->action_Disconnect->setVisible(false);//we need it only for debug + connect(ui->actionView, SIGNAL(triggered()), this, SLOT(closeUp())); + ui->actionView->setStatusTip(tr("Show the selected client in the whole window")); + connect(ui->actionFoto, SIGNAL(triggered()), this, SLOT(foto())); + connect(ui->actionLock, SIGNAL(triggered()), this, SLOT(lockalltoolbar())); + connect(ui->actionChat, SIGNAL(triggered()), this, SLOT(startChatDialog())); + ui->actionFoto->setStatusTip(tr("Make a screenshot for the selected client(s)")); + ui->actionLock->setStatusTip(tr("Lock or Unlock all Clients")); + connect(ui->actionCreate_profile, SIGNAL(triggered()), this, SLOT(createProfile())); + connect(ui->actionConfigure_Network, SIGNAL(triggered()), this, SLOT(configureNetwork())); + connect(ui->actionShowProcesses, SIGNAL(triggered()), this, SLOT(showProcesses())); + ui->actionShowProcesses->setStatusTip(tr("Show Processes of the selected Client")); + + connect(ui->actionShow_Username, SIGNAL(triggered()), this, SLOT(showusername())); + connect(ui->actionShow_Hostname_IP, SIGNAL(triggered()), this, SLOT(showip())); + connect(ui->actionShow_Fullname, SIGNAL(triggered()), this, SLOT(showname())); + connect(ui->horizontalSlider, SIGNAL(valueChanged (int)), this, SLOT(changeRatio(int))); + connect(ui->setPassword, SIGNAL(stateChanged (int)), this, SLOT(setPasswordForConnection(int))); + connect(ui->vncQuality, SIGNAL(currentIndexChanged (int)), this, SLOT(setVNCQuality(int))); + connect(ui->thumbStatus, SIGNAL(currentIndexChanged(int)), this, SLOT(changeStatus(int))); + connect(ui->actionShow_Log, SIGNAL(toggled(bool)), this, SLOT(setLogConsoleDisabled(bool))); + connect(ui->actionShow_Network, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); + connect(ui->actionShow_Chat, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); + connect(ui->actionShow_Terminal, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); + connect(ui->actionShow_Normal, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); + connect(ui->actionShow_Error, SIGNAL(toggled(bool)), this, SLOT(onToggleLog(bool))); + connect(ui->actionAbout_pvs, SIGNAL(triggered()), _aboutDialog, SLOT(open())); + + loadSettings(); //we load the appliocation settings + + setUnifiedTitleAndToolBarOnMac(true); + statusBar()->showMessage(tr("The pvs manager")); + this->showMaximized(); // show the Mainwindow maximized + + // listen on port 29481 for incoming file transfers _serverSocket = new QTcpServer(); _serverSocket->listen(QHostAddress::Any, 29481); connect(_serverSocket, SIGNAL(newConnection()), this, SLOT(incomingFile())); - - } MainWindow::~MainWindow() { - delete ui; + delete ui; } /* @@ -180,38 +187,38 @@ void MainWindow::closeEvent(QCloseEvent *e) MainWindow* MainWindow::getWindow() // catches the window { - if (myself) - { - return myself; - } - else - { - return myself = new MainWindow; - } + if (myself) + { + return myself; + } + else + { + return myself = new MainWindow; + } } ConnectionWindow* MainWindow::getConnectionWindow() // catches the ConnectionWindow { - if (conWin) - { - return conWin; - } - else - { - conWin = new ConnectionWindow; - return conWin; - } + if (conWin) + { + return conWin; + } + else + { + conWin = new ConnectionWindow; + return conWin; + } } ConnectionList* MainWindow::getConnectionList() // catches the ConnectionList { - if (conList) - return conList; - else - { - conList = new ConnectionList; - return conList; - } + if (conList) + return conList; + else + { + conList = new ConnectionList; + return conList; + } } int MainWindow::getConnectionWindowWidth() // returns the width of the ConnectionWindow @@ -226,9 +233,9 @@ int MainWindow::getConnectionWindowHeight() // returns the height of the Coonect QStringList MainWindow::getProfilList() // loads the profile list { - QSettings settings("openslx", "pvsmgr"); - profilList = settings.childGroups(); - return profilList; + QSettings settings("openslx", "pvsmgr"); + profilList = settings.childGroups(); + return profilList; } #ifdef MAINWINDOW_USE_NORMALGUI @@ -254,70 +261,63 @@ void MainWindow::removeProfileInMenu(QString name) #endif void MainWindow::loadSettings() { - QSettings settings("openslx", "pvsmgr"); - QString current = settings.value("current", "default").toString(); - currentProfi = current; - _profilName = current; + QSettings settings("openslx", "pvsmgr"); + QString current = settings.value("current", "default").toString(); + currentProfi = current; + _profilName = current; - //When no profile is available, we define a default one whith 9 dummy screens - if (current.compare("default") == 0) - { - setWindowTitle("PVSmgr - Default"); - QPoint pos1 = settings.value("default/1", QPoint(0, 0)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("1", pos1); - QPoint pos2 = - settings.value("default/2", QPoint(194, 0)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("2", pos2); - QPoint pos3 = - settings.value("default/3", QPoint(388, 0)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("3", pos3); - QPoint pos4 = - settings.value("default/4", QPoint(582, 0)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("4", pos4); - QPoint pos5 = - settings.value("default/5", QPoint(0, 173)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("5", pos5); - QPoint pos6 = - settings.value("default/6", QPoint(194, 173)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("6", pos6); - QPoint pos7 = - settings.value("default/7", QPoint(388, 173)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("7", pos7); - QPoint pos8 = - settings.value("default/8", QPoint(582, 173)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("8", pos8); - QPoint pos9 = - settings.value("default/9", QPoint(293, 346)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings("9", pos9); - - QString title = "PVSmgr - "; + //When no profile is available, we define a default one whith 9 dummy screens + if (current.compare("default") == 0) + { + setWindowTitle("PVSmgr - Default"); + QPoint pos1 = settings.value("default/1", QPoint(0, 0)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("1", pos1); + QPoint pos2 = settings.value("default/2", QPoint(194, 0)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("2", pos2); + QPoint pos3 = settings.value("default/3", QPoint(388, 0)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("3", pos3); + QPoint pos4 = settings.value("default/4", QPoint(582, 0)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("4", pos4); + QPoint pos5 = settings.value("default/5", QPoint(0, 173)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("5", pos5); + QPoint pos6 = settings.value("default/6", QPoint(194, 173)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("6", pos6); + QPoint pos7 = settings.value("default/7", QPoint(388, 173)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("7", pos7); + QPoint pos8 = settings.value("default/8", QPoint(582, 173)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("8", pos8); + QPoint pos9 = settings.value("default/9", QPoint(293, 346)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings("9", pos9); + + QString title = "PVSmgr - "; title.append(_profilName); - title.append(" ["+_sessionName + " : "); - title.append(_pwdCon+"]"); + title.append(" [" + _sessionName + " : "); + title.append(_pwdCon + "]"); setWindowTitle(title); - } - else - { - QString title = "PVSmgr - "; + } + else + { + QString title = "PVSmgr - "; title.append(_profilName); - title.append(" ["+_sessionName + " : "); - title.append(_pwdCon+"]"); + title.append(" [" + _sessionName + " : "); + title.append(_pwdCon + "]"); setWindowTitle(title); - settings.beginGroup(current); - QStringList keys = settings.childKeys(); - for (int i=0; i<keys.size(); i++) - { - QString profil = current; - profil = profil.append("/").append(keys.at(i)); - QPoint pos = settings.value(keys.at(i)).toPoint(); - MainWindow::getConnectionWindow()->addFrameBySettings(keys.at(i), pos); - } - } + settings.beginGroup(current); + QStringList keys = settings.childKeys(); + for (int i = 0; i < keys.size(); i++) + { + QString profil = current; + profil = profil.append("/").append(keys.at(i)); + QPoint pos = settings.value(keys.at(i)).toPoint(); + MainWindow::getConnectionWindow()->addFrameBySettings(keys.at(i), + pos); + } + } - MainWindow::getConnectionWindow()->showFrameFromSettings(); + MainWindow::getConnectionWindow()->showFrameFromSettings(); #ifdef MAINWINDOW_USE_NORMALGUI - foreach (QString profile, getProfilList()) - addProfileInMenu(profile); + foreach (QString profile, getProfilList()) + addProfileInMenu(profile); #endif } @@ -329,17 +329,17 @@ void MainWindow::loadProfile(QAction* actiontriggered) void MainWindow::loadSettings(QString profilname) // loads the current profile { - QList<ConnectionFrame*> AllFrameOnWindow = - MainWindow::getConnectionWindow()->getAllFrameOnWindow(); + QList<ConnectionFrame*> AllFrameOnWindow = + MainWindow::getConnectionWindow()->getAllFrameOnWindow(); - if (AllFrameOnWindow.size() > 0) - { - _profilName = profilname; - MainWindow::getConnectionWindow()->ClientLocationList.clear(); - QSettings settings("openslx", "pvsmgr"); - settings.setValue("current", _profilName); - ConnectionFrame* cFrame; - foreach (cFrame, AllFrameOnWindow) + if (AllFrameOnWindow.size() > 0) + { + _profilName = profilname; + MainWindow::getConnectionWindow()->ClientLocationList.clear(); + QSettings settings("openslx", "pvsmgr"); + settings.setValue("current", _profilName); + ConnectionFrame* cFrame; + foreach (cFrame, AllFrameOnWindow) { if (cFrame->isDummy()) { @@ -348,90 +348,91 @@ void MainWindow::loadSettings(QString profilname) // loads the current profile cFrame->deleteLater(); } } - settings.beginGroup(_profilName); - QStringList keys = settings.childKeys(); - int rest = AllFrameOnWindow.size(); - int init = 1; - for (int i = 0; i < keys.size(); i++) - { - if (init <= rest) - { - ConnectionFrame* cF = AllFrameOnWindow.at(i); - QString profil = _profilName; - profil = profil.append("/").append(cF->getTaskbarTitle()); - if (!cF->isDummy()) - cF->move(settings.value(keys.at(i)).toPoint()); - else - cF->move(settings.value(profil, QPoint(10,(10+(5*i)))).toPoint()); - - init += 1; - } - else - { - MainWindow::getConnectionWindow()->addFrameBySettings( - keys.at(i), settings.value(keys.at(i)).toPoint()); - } - } - - MainWindow::getConnectionWindow()->showFrameFromSettings(); - - QString title = "PVSmgr - "; - title.append(_profilName); - title.append(" ["+_sessionName + " : "); - title.append(_pwdCon+"]"); - setWindowTitle(title); - } + settings.beginGroup(_profilName); + QStringList keys = settings.childKeys(); + int rest = AllFrameOnWindow.size(); + int init = 1; + for (int i = 0; i < keys.size(); i++) + { + if (init <= rest) + { + ConnectionFrame* cF = AllFrameOnWindow.at(i); + QString profil = _profilName; + profil = profil.append("/").append(cF->getTaskbarTitle()); + if (!cF->isDummy()) + cF->move(settings.value(keys.at(i)).toPoint()); + else + cF->move( + settings.value(profil, QPoint(10, (10 + (5 * i)))).toPoint()); + + init += 1; + } + else + { + MainWindow::getConnectionWindow()->addFrameBySettings( + keys.at(i), settings.value(keys.at(i)).toPoint()); + } + } + + MainWindow::getConnectionWindow()->showFrameFromSettings(); + + QString title = "PVSmgr - "; + title.append(_profilName); + title.append(" [" + _sessionName + " : "); + title.append(_pwdCon + "]"); + setWindowTitle(title); + } } void MainWindow::saveSettings(QString profilname) { - QList<ConnectionFrame*> AllFrameOnWindow = - MainWindow::getConnectionWindow()->getAllFrameOnWindow(); - QSettings settings("openslx", "pvsmgr"); - settings.setValue("current", profilname); - settings.setValue("size", QString("%1").arg(AllFrameOnWindow.size())); + QList<ConnectionFrame*> AllFrameOnWindow = + MainWindow::getConnectionWindow()->getAllFrameOnWindow(); + QSettings settings("openslx", "pvsmgr"); + settings.setValue("current", profilname); + settings.setValue("size", QString("%1").arg(AllFrameOnWindow.size())); - for (int i = 0; i < AllFrameOnWindow.size(); i++) - { - ConnectionFrame* current = AllFrameOnWindow.at(i); - QString profil = ""; - profil = settings.value("current").toString().append("/"); - if (!current->isDummy()) - profil.append(QString(current->getTaskbarTitle())); - else - profil.append(QString("%1").arg(i + 1)); - settings.setValue(profil, current->pos()); - } + for (int i = 0; i < AllFrameOnWindow.size(); i++) + { + ConnectionFrame* current = AllFrameOnWindow.at(i); + QString profil = ""; + profil = settings.value("current").toString().append("/"); + if (!current->isDummy()) + profil.append(QString(current->getTaskbarTitle())); + else + profil.append(QString("%1").arg(i + 1)); + settings.setValue(profil, current->pos()); + } #ifdef MAINWINDOW_USE_NORMALGUI -addProfileInMenu(profilname); + addProfileInMenu(profilname); #endif } void MainWindow::removeProfil(QString profilname) { - QSettings settings("openslx", "pvsmgr"); - settings.remove(profilname); + QSettings settings("openslx", "pvsmgr"); + settings.remove(profilname); #ifdef MAINWINDOW_USE_NORMALGUI -removeProfileInMenu(profilname); + removeProfileInMenu(profilname); #endif } void MainWindow::addConnection(PVSClient* newCon) { - conWin->addConnection(newCon); - if (!_chatListClients.contains(newCon->getUserName())) - { - _chatListClients.append(newCon->getUserName()); - sChatDialog.chat_client_add(newCon->getUserName()); - sChatDialog.chat_nicklist_update(); - } - // sChatDialog->chat_nicklist_update(newCon->getUserName()); + conWin->addConnection(newCon); + if (!_chatListClients.contains(newCon->getUserName())) + { + _chatListClients.append(newCon->getUserName()); + sChatDialog.chat_client_add(newCon->getUserName()); + sChatDialog.chat_nicklist_update(); + } + // sChatDialog->chat_nicklist_update(newCon->getUserName()); } void MainWindow::removeConnection(PVSClient* newCon) { - conWin->removeConnection(newCon); - if (_chatListClients.contains(newCon->getUserName())) + conWin->removeConnection(newCon); + if (_chatListClients.contains(newCon->getUserName())) { _chatListClients.removeOne(newCon->getUserName()); sChatDialog.chat_client_remove(newCon->getUserName()); @@ -442,87 +443,87 @@ void MainWindow::removeConnection(PVSClient* newCon) void MainWindow::onConnectionFailed(QString host) { #ifdef never - // code is voided because the info-management will be overhauled sometime + // code is voided because the info-management will be overhauled sometime - if (pwDiag) // assume this thing failed after the pw-question... so a wrong password, ey? + if (pwDiag) // assume this thing failed after the pw-question... so a wrong password, ey? - { - onPasswordFailed(host); - return; - } + { + onPasswordFailed(host); + return; + } - QString caption, secondary; - if (host != "") - { - caption = ("PVSConnection with hostname \""); - caption.append(host); - caption.append("\" failed."); - secondary = "PVSConnection attempt for this hostname failed.Maybe the host is not prepared to accept vnc connections. Please make sure hostname and (if needed) password are correct."; - } - else - { - caption = "No IP given"; - secondary = "PVSConnection attempt for this host failed. There was either no or an errorous Hostname given."; - } - QMessageBox::information(*this, caption, secondary); - /* Gtk::MessageDialog dialog(*this, Glib::ustring(caption)); - dialog.set_secondary_text(secondary); - dialog.run();*/ + QString caption, secondary; + if (host != "") + { + caption = ("PVSConnection with hostname \""); + caption.append(host); + caption.append("\" failed."); + secondary = "PVSConnection attempt for this hostname failed.Maybe the host is not prepared to accept vnc connections. Please make sure hostname and (if needed) password are correct."; + } + else + { + caption = "No IP given"; + secondary = "PVSConnection attempt for this host failed. There was either no or an errorous Hostname given."; + } + QMessageBox::information(*this, caption, secondary); + /* Gtk::MessageDialog dialog(*this, Glib::ustring(caption)); + dialog.set_secondary_text(secondary); + dialog.run();*/ #endif } void MainWindow::onConnectionTerminated(PVSClient* newConnection) { #ifdef never - // code is voided because the info-management will be overhauled sometime + // code is voided because the info-management will be overhauled sometime - QString host; - if (newConnection) - { - host = newConnection->getIp(); // copy hostname for message - } - else - host = "spooky unknown"; + QString host; + if (newConnection) + { + host = newConnection->getIp(); // copy hostname for message + } + else + host = "spooky unknown"; - // now inform - QString caption, secondary; + // now inform + QString caption, secondary; - caption = "Hostname \""; - caption.append(host); - caption.append("\" terminated connection."); - secondary = "The server has closed the connection to your client."; + caption = "Hostname \""; + caption.append(host); + caption.append("\" terminated connection."); + secondary = "The server has closed the connection to your client."; - QMessageBox::information(*this, caption, secondary); - /*Gtk::MessageDialog dialog(*this, Glib::ustring(caption)); - dialog.set_secondary_text(secondary); - dialog.run();*/ + QMessageBox::information(*this, caption, secondary); + /*Gtk::MessageDialog dialog(*this, Glib::ustring(caption)); + dialog.set_secondary_text(secondary); + dialog.run();*/ #endif } void MainWindow::onConnectionRemoved(PVSClient* newConnection) { - // TODO this would be the place to handle the rest of the fullscreen issue - conWin->onConnectionRemoved(newConnection); + // TODO this would be the place to handle the rest of the fullscreen issue + conWin->onConnectionRemoved(newConnection); } void MainWindow::onPasswordFailed(QString Qhost) { #ifdef never - // code is voided because the info-management will be overhauled sometime - QString caption, secondary; - if (Qhost != "") - { - caption = "Hostname \""; - caption.append(Qhost); - caption.append("\" refused password."); - secondary = "You have entered no or a wrong password."; - } - else - return; // unknown connection was terminated? too spooky - QMessageBox::information(*this, caption, secondary); - /* Gtk::MessageDialog dialog(*this, Glib::ustring(caption)); - dialog.set_secondary_text(secondary); - Gtk::Main::run(dialog);*/ + // code is voided because the info-management will be overhauled sometime + QString caption, secondary; + if (Qhost != "") + { + caption = "Hostname \""; + caption.append(Qhost); + caption.append("\" refused password."); + secondary = "You have entered no or a wrong password."; + } + else + return; // unknown connection was terminated? too spooky + QMessageBox::information(*this, caption, secondary); + /* Gtk::MessageDialog dialog(*this, Glib::ustring(caption)); + dialog.set_secondary_text(secondary); + Gtk::Main::run(dialog);*/ #endif } @@ -538,41 +539,41 @@ void MainWindow::receiveChatMsg(QString nick_from, QString nick_to, QString msg) int MainWindow::getPrevWidth() // PVSConnectionManager::getManager()->getPrevWidth() { - return prev_width; + return prev_width; } void MainWindow::setPrevWidth(int newWidth) { - if (newWidth > 100) - prev_width = newWidth; - else - prev_width = 100; + if (newWidth > 100) + prev_width = newWidth; + else + prev_width = 100; } int MainWindow::getPrevHeight() { - return prev_height; + return prev_height; } void MainWindow::setPrevHeight(int newHeight) { - if (newHeight > 100) - prev_height = newHeight; - else - prev_height = 100; + if (newHeight > 100) + prev_height = newHeight; + else + prev_height = 100; } void MainWindow::changeEvent(QEvent *e) { - QMainWindow::changeEvent(e); - switch (e->type()) - { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } + QMainWindow::changeEvent(e); + switch (e->type()) + { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } } /* @@ -586,107 +587,108 @@ void MainWindow::changeEvent(QEvent *e) void MainWindow::resizeEvent(QResizeEvent *event) { - if (bgimage == true){ - repaintbackgroundpicture(); // repaint the backgroundpicture scaled to the window size + if (bgimage == true) + { + repaintbackgroundpicture(); // repaint the backgroundpicture scaled to the window size } if (_firstResize == 3) { QSize oldSize = event->oldSize(); - _initW = ui->widget->width(); - _initH = ui->widget->height(); + _initW = ui->widget->width(); + _initH = ui->widget->height(); _firstResize++; } - std::list<QString>* selectedClients = - MainWindow::getConnectionList()->getSelectedClients(); - if (is_closeup && selectedClients->size() == 1) - { - PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - selectedClients->front().toStdString().c_str()); - pvsClient->getConnectionFrame()->paintCloseUp(ui->widget->width(), - ui->widget->height()); - } - else if (!is_closeup && _firstResize > 3) - { - int ratio_w = (ui->widget->width()*100)/_initW; - int ratio_h = (ui->widget->height()*100)/_initH; - foreach (ConnectionFrame* cf, getConnectionWindow()->getFrameList()) - { - /*int margin = ui->widget->style()->pixelMetric(QStyle::PM_DefaultTopLevelMargin); - int x = ui->widget->width() - margin; - int y = ui->widget->height() - margin; - updatePos(cf, x, y);*/ - int w = (cf->init_w * ratio_w) / 100; - int h = (cf->init_h * ratio_h) / 100; - cf->paintCloseUp(w,h); - } - } + std::list<QString>* selectedClients = + MainWindow::getConnectionList()->getSelectedClients(); + if (is_closeup && selectedClients->size() == 1) + { + PVSClient* pvsClient = + PVSConnectionManager::getManager()->getClientFromIp( + selectedClients->front().toStdString().c_str()); + pvsClient->getConnectionFrame()->paintCloseUp(ui->widget->width(), + ui->widget->height()); + } + else if (!is_closeup && _firstResize > 3) + { + int ratio_w = (ui->widget->width() * 100) / _initW; + int ratio_h = (ui->widget->height() * 100) / _initH; +foreach (ConnectionFrame* cf, getConnectionWindow()->getFrameList()) + { + /*int margin = ui->widget->style()->pixelMetric(QStyle::PM_DefaultTopLevelMargin); + int x = ui->widget->width() - margin; + int y = ui->widget->height() - margin; + updatePos(cf, x, y);*/ + int w = (cf->init_w * ratio_w) / 100; + int h = (cf->init_h * ratio_h) / 100; + cf->paintCloseUp(w,h); + } +} - if (_firstResize < 3) - _firstResize++; +if (_firstResize < 3) +_firstResize++; } void MainWindow::updatePos(ConnectionFrame* cf, int x, int y) { - int posx = (x*cf->pos().x())/_initW; - int posy = (y*cf->pos().y())/_initH; + int posx = (x * cf->pos().x()) / _initW; + int posy = (y * cf->pos().y()) / _initH; cf->move(posx, posy); /*QSize size = cf->sizeHint(); - cf->setGeometry(x - size.rwidth(), y - size.rheight(), - size.rwidth(), size.rheight());*/ + cf->setGeometry(x - size.rwidth(), y - size.rheight(), + size.rwidth(), size.rheight());*/ } void MainWindow::on_log_line(LogEntry consoleEntry) { - ConsoleLogger::LOG_LEVEL level = consoleEntry.getLevel(); - if (level == ConsoleLogger::LOG_ERROR && !showError) - return; - if (level == ConsoleLogger::LOG_NORMAL && !showNormal) - return; - if (level == ConsoleLogger::LOG_NETWORK && !showNetwork) - return; - if (level == ConsoleLogger::LOG_TERMINAL && !showTerminal) - return; - if (level == ConsoleLogger::LOG_CHAT && !showChat) - return; - - ui->pvsLog->insertPlainText(consoleEntry.getLine()); + ConsoleLogger::LOG_LEVEL level = consoleEntry.getLevel(); + if (level == ConsoleLogger::LOG_ERROR && !showError) + return; + if (level == ConsoleLogger::LOG_NORMAL && !showNormal) + return; + if (level == ConsoleLogger::LOG_NETWORK && !showNetwork) + return; + if (level == ConsoleLogger::LOG_TERMINAL && !showTerminal) + return; + if (level == ConsoleLogger::LOG_CHAT && !showChat) + return; + + ui->pvsLog->insertPlainText(consoleEntry.getLine()); } void MainWindow::onToggleLog(bool showtime) { - if (showtime) - ;//to kill the system warning due "unused variable" - showError = ui->actionShow_Error->isChecked(); - showTerminal = ui->actionShow_Terminal->isChecked(); - showNetwork = ui->actionShow_Network->isChecked(); - showChat = ui->actionShow_Chat->isChecked(); - showNormal = ui->actionShow_Normal->isChecked(); - //showAtAll = ui->logAtAllAction->get_active(); + if (showtime) + ;//to kill the system warning due "unused variable" + showError = ui->actionShow_Error->isChecked(); + showTerminal = ui->actionShow_Terminal->isChecked(); + showNetwork = ui->actionShow_Network->isChecked(); + showChat = ui->actionShow_Chat->isChecked(); + showNormal = ui->actionShow_Normal->isChecked(); + //showAtAll = ui->logAtAllAction->get_active(); - ConsoleLog dump2Listener(this, &MainWindow::on_log_line); + ConsoleLog dump2Listener(this, &MainWindow::on_log_line); } void MainWindow::setLogConsoleDisabled(bool visible) { - if (!visible) - ui->pvsLog->hide(); - else - ui->pvsLog->show(); + if (!visible) + ui->pvsLog->hide(); + else + ui->pvsLog->show(); } /*void MainWindow::close() -{ - //sChatDialog.close(); - QApplication::closeAllWindows(); -}*/ + { + //sChatDialog.close(); + QApplication::closeAllWindows(); + }*/ void MainWindow::disconnect() { - conWin->removeVNC(); + conWin->removeVNC(); } void MainWindow::lockUnlockAll() @@ -707,122 +709,153 @@ void MainWindow::lockUnlockAll() void MainWindow::closeUp() { - std::list<QString>* selectedClients = - MainWindow::getConnectionList()->getSelectedClients(); - if (!is_closeup) - { - if (selectedClients->size() == 1) - { - PVSClient - * pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - selectedClients->front().toStdString().c_str()); - _framePosOnCloseUp = pvsClient->getConnectionFrame()->pos();//get the actualy position before run closeup - if (pvsClient->getVNCConnection()) - { - conWin->setCloseupFrame(pvsClient->getConnectionFrame()); - _updatefreq = pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->getUpdatefreq(); - pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(50); - pvsClient->getConnectionFrame()->move(5,5); - pvsClient->getConnectionFrame()->setWindowFlags(Qt::WindowStaysOnTopHint); + std::list<QString>* selectedClients = + MainWindow::getConnectionList()->getSelectedClients(); + if (!is_closeup) + { + if (selectedClients->size() == 1) + { + PVSClient * pvsClient = + PVSConnectionManager::getManager()->getClientFromIp( + selectedClients->front().toStdString().c_str()); + _framePosOnCloseUp = pvsClient->getConnectionFrame()->pos();//get the actualy position before run closeup + if (pvsClient->getVNCConnection()) + { + conWin->setCloseupFrame(pvsClient->getConnectionFrame()); + _updatefreq + = pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->getUpdatefreq(); + pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq( + 50); + pvsClient->getConnectionFrame()->move(5, 5); + pvsClient->getConnectionFrame()->setWindowFlags( + Qt::WindowStaysOnTopHint); pvsClient->getConnectionFrame()->raise(); - pvsClient->getConnectionFrame()->paintCloseUp(ui->widget->width(),ui->widget->height()); + pvsClient->getConnectionFrame()->paintCloseUp( + ui->widget->width(), ui->widget->height()); is_closeup = true; conWin->setCloseupFrame(pvsClient->getConnectionFrame()); } - } - else - { - QString - message = - QString( - tr( - "This operation can only be performed for one selected Client!")); - QMessageBox::information(this, "PVS", message); - } - } - else - { - if (conWin->getCloseupFrame()) - { - /*PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - selectedClients->front().toStdString().c_str());*/ - conWin->getCloseupFrame()->setWindowFlags(Qt::Widget); - conWin->getCloseupFrame()->paintCloseUp(conWin->getCloseupFrame()->getPrevWidth(), conWin->getCloseupFrame()->getPrevHeight()); - conWin->getCloseupFrame()->move(_framePosOnCloseUp);//back to the position before the closeup - if (conWin->getCloseupFrame()->getConnection()->getVNCConnection()) - conWin->getCloseupFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(_updatefreq); - conWin->setCloseupFrame(NULL); - } - - is_closeup = false; - } + } + else + { + QString + message = + QString( + tr( + "This operation can only be performed for one selected Client!")); + QMessageBox::information(this, "PVS", message); + } + } + else if (conWin->getCloseupFrame()) + { + /*PVSClient* pvsClient = + PVSConnectionManager::getManager()->getClientFromIp( + selectedClients->front().toStdString().c_str());*/ + conWin->getCloseupFrame()->setWindowFlags(Qt::Widget); + conWin->getCloseupFrame()->paintCloseUp( + conWin->getCloseupFrame()->getPrevWidth(), + conWin->getCloseupFrame()->getPrevHeight()); + conWin->getCloseupFrame()->move(_framePosOnCloseUp);//back to the position before the closeup + if (conWin->getCloseupFrame()->getConnection()->getVNCConnection()) + conWin->getCloseupFrame()->getFrame()->getVNCClientThread()->setUpdatefreq( + _updatefreq); + + is_closeup = false; + conWin->setCloseupFrame(NULL); + } +} + +/* Perform some action if actionShowProcesses button was pressed + * + */ +void MainWindow::showProcesses() +{ + std::list<QString>* selectedClients = + MainWindow::getConnectionList()->getSelectedClients(); + if (selectedClients->size() == 1) + { + // do stuff + PVSClient * pvsClient = + PVSConnectionManager::getManager()->getClientFromIp( + selectedClients->front().toStdString().c_str()); + pvsClient->sendMessage(PVSCOMMAND, "SHOWPROCESSES", ""); + } + else + { + QString + message = + QString( + tr( + "This operation can only be performed if you have selected a Client!")); + QMessageBox::information(this, "PVS", message); + } } void MainWindow::foto() // makes a screenshot of the selected client { - std::list<QString>* selectedClients = - MainWindow::getConnectionList()->getSelectedClients(); - if (selectedClients->size() > 0) - { - QString format = "png"; - for (std::list<QString>::iterator tmpIt = selectedClients->begin(); tmpIt - != selectedClients->end(); tmpIt++) - { - - QString path = QDir::homePath().append("/").append(*tmpIt).append( - ".png"); - PVSClient - * pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - (*tmpIt).toUtf8().data()); - if (pvsClient->getVNCConnection()) - { - const QImage img = pvsClient->getConnectionFrame()->getFrame()->getImageForFoto(); - if (!img.isNull()) - img.save(path, format.toAscii()); - } - else printf("Cannot save screen: Image is null.\n"); - } - } - else - { - QString - message = - QString( - tr( - "This operation can only be performed for at least one selected Client!")); - QMessageBox::information(this, "PVS", message); - } + std::list<QString>* selectedClients = + MainWindow::getConnectionList()->getSelectedClients(); + if (selectedClients->size() > 0) + { + QString format = "png"; + for (std::list<QString>::iterator tmpIt = selectedClients->begin(); tmpIt + != selectedClients->end(); tmpIt++) + { + + QString path = QDir::homePath().append("/").append(*tmpIt).append( + ".png"); + PVSClient * pvsClient = + PVSConnectionManager::getManager()->getClientFromIp( + (*tmpIt).toUtf8().data()); + if (pvsClient->getVNCConnection()) + { + const QImage + img = + pvsClient->getConnectionFrame()->getFrame()->getImageForFoto(); + if (!img.isNull()) + img.save(path, format.toAscii()); + } + else + qDebug("Cannot save screen: Image is null."); + } + } + else + { + QString + message = + QString( + tr( + "This operation can only be performed for at least one selected Client!")); + QMessageBox::information(this, "PVS", message); + } } void MainWindow::createProfile() { - profileDialog proDiag; - proDiag.exec(); + profileDialog proDiag; + proDiag.exec(); } void MainWindow::showusername() { - MainWindow::getConnectionList()->setColumnHidden(2, false); - MainWindow::getConnectionList()->setColumnHidden(0, true); - MainWindow::getConnectionList()->setColumnHidden(1, true); + MainWindow::getConnectionList()->setColumnHidden(2, false); + MainWindow::getConnectionList()->setColumnHidden(0, true); + MainWindow::getConnectionList()->setColumnHidden(1, true); } void MainWindow::showname() { - MainWindow::getConnectionList()->setColumnHidden(0, false); - MainWindow::getConnectionList()->setColumnHidden(1, true); - MainWindow::getConnectionList()->setColumnHidden(2, true); + MainWindow::getConnectionList()->setColumnHidden(0, false); + MainWindow::getConnectionList()->setColumnHidden(1, true); + MainWindow::getConnectionList()->setColumnHidden(2, true); } void MainWindow::showip() { - MainWindow::getConnectionList()->setColumnHidden(1, false); - MainWindow::getConnectionList()->setColumnHidden(2, true); - MainWindow::getConnectionList()->setColumnHidden(0, true); + MainWindow::getConnectionList()->setColumnHidden(1, false); + MainWindow::getConnectionList()->setColumnHidden(2, true); + MainWindow::getConnectionList()->setColumnHidden(0, true); } void MainWindow::incomingFile() @@ -841,15 +874,16 @@ void MainWindow::changeRatio(int ratio) // needed the change the size of the vnc str.append(QString("%1").arg(ratio)); ui->label_2->setText(str); - std::list<QString>* selClients = getConnectionList()->getSelectedClients(); + std::list<QString>* selClients = + getConnectionList()->getSelectedClients(); if (selClients->size() > 0) { for (std::list<QString>::iterator client = selClients->begin(); client != selClients->end(); client++) { PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - (*client).toUtf8().data()); + PVSConnectionManager::getManager()->getClientFromIp( + (*client).toUtf8().data()); ConnectionFrame *frame = pvsClient->getConnectionFrame(); int w = (frame->init_w * ratio) / 100; int h = (frame->init_h * ratio) / 100; @@ -864,46 +898,46 @@ void MainWindow::changeRatio(int ratio) // needed the change the size of the vnc QList<ConnectionFrame *> frameList = MainWindow::getConnectionWindow()->getFrameList(); ConnectionFrame *frame; - foreach(frame, frameList) - { - int w = (frame->init_w * ratio) / 100; - int h = (frame->init_h * ratio) / 100; - frame->setPrevWidth(w); - frame->setPrevHeight(h); - frame->paintCloseUp(w, h); - } +foreach (frame, frameList) + { + int w = (frame->init_w * ratio) / 100; + int h = (frame->init_h * ratio) / 100; + frame->setPrevWidth(w); + frame->setPrevHeight(h); + frame->paintCloseUp(w, h); } } - else +} +else +{ + int updatefreq = (ratio*500)/100; + QString str; + str.append(QString("%1").arg(updatefreq)); + ui->label_2->setText(str); + std::list<QString>* selClients = getConnectionList()->getSelectedClients(); + if (selClients->size() > 0) { - int updatefreq = (ratio*500)/100; - QString str; - str.append(QString("%1").arg(updatefreq)); - ui->label_2->setText(str); - std::list<QString>* selClients = getConnectionList()->getSelectedClients(); - if (selClients->size() > 0) + for (std::list<QString>::iterator client = selClients->begin(); client + != selClients->end(); client++) { - for (std::list<QString>::iterator client = selClients->begin(); client - != selClients->end(); client++) - { - PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - (*client).toUtf8().data()); - if (pvsClient->getVNCConnection()) - pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(updatefreq); - } + PVSClient* pvsClient = + PVSConnectionManager::getManager()->getClientFromIp( + (*client).toUtf8().data()); + if (pvsClient->getVNCConnection()) + pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(updatefreq); } - else + } + else + { + std::list<PVSClient*> clients = PVSConnectionManager::getManager()->getConnections(); + foreach (PVSClient* client, clients) { - std::list<PVSClient*> clients = PVSConnectionManager::getManager()->getConnections(); - foreach (PVSClient* client, clients) - { - if (client->getVNCConnection()) - client->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(updatefreq); - } + if (client->getVNCConnection()) + client->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(updatefreq); } - } + +} } /* @@ -917,18 +951,19 @@ void MainWindow::changeRatio(int ratio) // needed the change the size of the vnc */ void MainWindow::changeStatus(int index) { - QString status = ui->thumbStatus->currentText (); + QString status = ui->thumbStatus->currentText(); if (status == "Thumbnailratio") { _isThumbnailrate = false; ui->label_3->setText("%"); - std::list<QString>* selClients = getConnectionList()->getSelectedClients(); + std::list<QString>* selClients = + getConnectionList()->getSelectedClients(); if (selClients->size() == 1) { PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - selClients->front().toStdString().c_str()); + PVSConnectionManager::getManager()->getClientFromIp( + selClients->front().toStdString().c_str()); int ratio = pvsClient->getConnectionFrame()->getRatio(); ui->label_2->setText(QString::number(ratio)); ui->horizontalSlider->setValue(ratio); @@ -944,16 +979,19 @@ void MainWindow::changeStatus(int index) { _isThumbnailrate = true; ui->label_3->setText("ms"); - std::list<QString>* selClients = getConnectionList()->getSelectedClients(); + std::list<QString>* selClients = + getConnectionList()->getSelectedClients(); if (selClients->size() == 1) { PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - selClients->front().toStdString().c_str()); + PVSConnectionManager::getManager()->getClientFromIp( + selClients->front().toStdString().c_str()); if (pvsClient->getVNCConnection()) { - int updatefreq = pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->getUpdatefreq(); - int showfreq = (updatefreq*100)/500; + int + updatefreq = + pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->getUpdatefreq(); + int showfreq = (updatefreq * 100) / 500; ui->label_2->setText(QString::number(updatefreq)); ui->horizontalSlider->setValue(showfreq); } @@ -966,7 +1004,6 @@ void MainWindow::changeStatus(int index) } } - /* * Going to run a new vncthread with quality: quality */ @@ -976,47 +1013,48 @@ void MainWindow::setVNCQuality(int quality) if (selClients->size() > 0) { for (std::list<QString>::iterator client = selClients->begin(); client - != selClients->end(); client++) + != selClients->end(); client++) { PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - (*client).toUtf8().data()); + PVSConnectionManager::getManager()->getClientFromIp( + (*client).toUtf8().data()); pvsClient->getConnectionFrame()->resetConnectionWithQuality(quality); pvsClient->getConnectionFrame()->update(); } } else { - QList<ConnectionFrame*> FrameList = MainWindow::getConnectionWindow()->getFrameList(); - foreach(ConnectionFrame* frame, FrameList) - { - frame->resetConnectionWithQuality(quality); - frame->update(); - } + QList<ConnectionFrame*> FrameList = + MainWindow::getConnectionWindow()->getFrameList(); +foreach (ConnectionFrame* frame, FrameList) + { + frame->resetConnectionWithQuality(quality); + frame->update(); } - } +} void MainWindow::setPasswordForConnection(int enabled) { - if(enabled == 0)//the checkbox isn't checked, so no passowrd needed, we remove it in the titlebar + if (enabled == 0)//the checkbox isn't checked, so no passowrd needed, we remove it in the titlebar { - QString dummy = PVSConnectionManager::getManager()->setNeedPassword(false); - _sessionName = PVSConnectionManager::getManager()->getSessionName(); + QString dummy = PVSConnectionManager::getManager()->setNeedPassword( + false); + _sessionName = PVSConnectionManager::getManager()->getSessionName(); QString title = "PVSmgr - "; title.append(_profilName); - title.append(" ["+_sessionName + " : ]"); + title.append(" [" + _sessionName + " : ]"); setWindowTitle(title); } else if (enabled == 2) //password is needed, we show it in the titlebar { - _pwdCon = PVSConnectionManager::getManager()->setNeedPassword(true); + _pwdCon = PVSConnectionManager::getManager()->setNeedPassword(true); _sessionName = PVSConnectionManager::getManager()->getSessionName(); QString title = "PVSmgr - "; title.append(_profilName); - title.append(" ["+_sessionName + " : "); - title.append(_pwdCon+"]"); + title.append(" [" + _sessionName + " : "); + title.append(_pwdCon + "]"); setWindowTitle(title); } } @@ -1026,153 +1064,155 @@ void MainWindow::setPasswordForConnection(int enabled) void MainWindow::setindexback() //sets the index of the combobox back { #ifdef MAINWINDOW_USE_TOUCHGUI - ui->comboBox_touch1->setCurrentIndex(0); + ui->comboBox_touch1->setCurrentIndex(0); #endif } void MainWindow::clientlisthide() // hide or show the clientlist { - if (locked1 == false) - { - ui->ClWidget->show(); - locked1 = true; - } + if (locked1 == false) + { + ui->ClWidget->show(); + locked1 = true; + } - else - { - ui->ClWidget->hide(); - locked1 = false; - } + else + { + ui->ClWidget->hide(); + locked1 = false; + } } - void MainWindow::lockalltoolbar() // locks all if a dozent is set { + if (locked == false) + { + if (MainWindow::getConnectionWindow()->hasDozent) + { + MainWindow::getConnectionList()->on_lock_all(); + locked = true; + } + else + { + QString + message = + QString( + tr( + "You have to set a Superclient-machine before performing this action.")); + QMessageBox::information(this, "PVS", message); + } + } - if (locked == false) - { - if (MainWindow::getConnectionWindow()->hasDozent) - { - MainWindow::getConnectionList()->on_lock_all(); - locked = true; - } - else - { - QString message = QString(tr("You have to set a Superclient-machine before performing this action.")); - QMessageBox::information(this, "PVS", message); - } - } - - else - { - MainWindow::getConnectionList()->on_unlock_all(); - locked = false; - } + else + { + MainWindow::getConnectionList()->on_unlock_all(); + locked = false; + } } void MainWindow::locksingle() // locks a single client { - MainWindow::getConnectionList()->on_lock(); + MainWindow::getConnectionList()->on_lock(); } void MainWindow::unlocksingle() // unlocks a single client { - MainWindow::getConnectionList()->on_unlock(); + MainWindow::getConnectionList()->on_unlock(); } - void MainWindow::combobox1(int menuindex1) // defines the functions to call from the combobox { - switch (menuindex1) - // index comes from the slot definition - { - case 1: - // Lock all - MainWindow::getConnectionList()->on_lock_all(); - break; - - case 2: - // UnLock all - MainWindow::getConnectionList()->on_unlock_all(); - break; - - case 3: - // UnProject all - MainWindow::getConnectionList()->on_unproject_all(); - break; - - case 4: - //Background Picture - backgroundpicture(); - break; - } + switch (menuindex1) + // index comes from the slot definition + { + case 1: + // Lock all + MainWindow::getConnectionList()->on_lock_all(); + break; + + case 2: + // UnLock all + MainWindow::getConnectionList()->on_unlock_all(); + break; + + case 3: + // UnProject all + MainWindow::getConnectionList()->on_unproject_all(); + break; + + case 4: + //Background Picture + backgroundpicture(); + break; + } } void MainWindow::resetall() // unlock and unproject all in toolbar - { +{ MainWindow::getConnectionList()->on_unlock_all(); MainWindow::getConnectionList()->on_unproject_all(); - } - +} void MainWindow::projecttoolbar() // projection from toolbar button - { +{ MainWindow::getConnectionList()->on_projection(); - } +} void MainWindow::unprojecttoolbar() // unproject all in toolbar - { +{ MainWindow::getConnectionList()->on_unprojection(); - } +} void MainWindow::backgroundpicture() - { - +{ - fileName = QFileDialog::getOpenFileName(this, - tr("Open Image"), "/home", tr("Image Files (*.png *.jpg *.svg)")); // user chooses a file + fileName = QFileDialog::getOpenFileName(this, tr("Open Image"), "/home", + tr("Image Files (*.png *.jpg *.svg)")); // user chooses a file - QImage img(""+fileName+""); // set image + QImage img("" + fileName + ""); // set image QString test("/tmp/test.png"); // set path for saving the scaled picture - QImage img2 = img.scaled(ui->widget->size(),Qt::IgnoreAspectRatio,Qt::FastTransformation); // scale it + QImage img2 = img.scaled(ui->widget->size(), Qt::IgnoreAspectRatio, + Qt::FastTransformation); // scale it - img2.save(""+test+""); // save it + img2.save("" + test + ""); // save it - ui->widget->setStyleSheet("background-image: url(/tmp/test.png);background-repeat:no-repeat; background-position:center;"); //set the picture as background + ui->widget->setStyleSheet( + "background-image: url(/tmp/test.png);background-repeat:no-repeat; background-position:center;"); //set the picture as background foreach (ConnectionFrame* cf, MainWindow::getConnectionWindow()->getAllFrameOnWindow()) { cf->setStyleSheet(QString::fromUtf8("background-color: rgb(150, 150, 168);")); } - bgimage=true; // for the resize event, set background true + bgimage = true; // for the resize event, set background true - } +} void MainWindow::repaintbackgroundpicture() // same as backgroundpicture but called when mainwindow is resized - { +{ QImage img("/tmp/test.png"); QString test("/tmp/test.png"); - QImage img2 = img.scaled(ui->widget->size(),Qt::IgnoreAspectRatio,Qt::FastTransformation); + QImage img2 = img.scaled(ui->widget->size(), Qt::IgnoreAspectRatio, + Qt::FastTransformation); - img2.save(""+test+""); + img2.save("" + test + ""); - ui->widget->setStyleSheet("background-image: url(/tmp/test.png);background-repeat:no-repeat; background-position:center;"); + ui->widget->setStyleSheet( + "background-image: url(/tmp/test.png);background-repeat:no-repeat; background-position:center;"); - - } +} void MainWindow::setdozenttoolbar() // set the dozents pc which is not locked with lockedall { @@ -1184,8 +1224,8 @@ void MainWindow::setdozenttoolbar() // set the dozents pc which is not locked wi { PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - selectedClients->front().toStdString().c_str()); + PVSConnectionManager::getManager()->getClientFromIp( + selectedClients->front().toStdString().c_str()); if (pvsClient->getVNCConnection()) pvsClient->getConnectionFrame()->getFrame()->setDozent(); } @@ -1200,9 +1240,19 @@ void MainWindow::startChatDialog() sChatDialog.raise();//show the chat dialog on top level } +void MainWindow::configureNetwork() +{ + PVSServer* server = PVSConnectionManager::getManager()->getServer(); + McastConfiguration mc(*(server->getMulticastConfiguration())); + MulticastConfigDialog* mcd = new MulticastConfigDialog(&mc, this); + int result = mcd->exec(); + if(result == QDialog::Accepted) + { + server->multicastReconfigure(&mc); + } +} - -MainWindow* MainWindow::myself = NULL; -ConnectionList* MainWindow::conList = NULL; -ConnectionWindow* MainWindow::conWin = NULL; -bool MainWindow::_isLockAll = false; +MainWindow* MainWindow::myself = NULL; +ConnectionList* MainWindow::conList = NULL; +ConnectionWindow* MainWindow::conWin = NULL; +bool MainWindow::_isLockAll = false; diff --git a/src/gui/mainWindow.h b/src/gui/mainWindow.h index 00bd927..88756fd 100644 --- a/src/gui/mainWindow.h +++ b/src/gui/mainWindow.h @@ -159,6 +159,8 @@ private: QMenu* _profileMenuList; QMap<QString, QAction*> _mapProfileToAction; + QSettings _settings; + public slots: void loadProfile(QAction* actiontriggered); void setindexback(); @@ -176,6 +178,7 @@ public slots: void repaintbackgroundpicture(); void setdozenttoolbar(); void startChatDialog(); + void showProcesses(); private slots: void onToggleLog(bool showtime); @@ -194,6 +197,7 @@ private slots: void setPasswordForConnection(int enabled); void combobox1(int menuindex1); // Funktion um index der combobox auszulesen und weiterzuverarbeiten s. Ticker 671 //void combobox2(int menuindex2); // Funktion um index der combobox auszulesen und weiterzuverarbeiten + void configureNetwork(); }; diff --git a/src/gui/multicastConfigDialog.cpp b/src/gui/multicastConfigDialog.cpp new file mode 100644 index 0000000..ff370c7 --- /dev/null +++ b/src/gui/multicastConfigDialog.cpp @@ -0,0 +1,170 @@ +#include <QValidator> +#include <QIntValidator> +#include <QHostAddress> +#include <QPushButton> +#include "multicastConfigDialog.h" +#include <src/net/mcast/McastConfiguration.h> +// #include "multicastValidators.h" + +MulticastConfigDialog::MulticastConfigDialog(QWidget* parent) : + QDialog(parent) +{ + setupUi(); +} + +MulticastConfigDialog::MulticastConfigDialog(McastConfiguration* config, + QWidget *parent) : + QDialog(parent) +{ + setupUi(); + _config = config; + + _ui.groupAddressEdit->setText(config->multicastAddress()); + _ui.dataPortEdit->setText(QString::number(config->multicastUDPPortBase())); + + connect(_ui.buttonBox, SIGNAL(accepted()), this, SLOT(dialogAccepted())); + connect(_ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject())); +} + +void MulticastConfigDialog::setupUi() +{ + _ui.setupUi(this); + + QIntValidator* portValidator = new QIntValidator(1024, 65535, this); + _ui.dataPortEdit->setValidator(portValidator); + + connect(_ui.groupAddressEdit, SIGNAL(textChanged(QString const&)), this, + SLOT(validateGroupAddress(QString const&))); + connect(_ui.dataPortEdit, SIGNAL(textChanged(QString const&)), this, + SLOT(validateDataPort(QString const&))); + + connect(_ui.buttonBox, SIGNAL(accepted()), this, SLOT(dialogAccepted())); + connect(_ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + validateGroupAddress(_ui.groupAddressEdit->text()); + validateDataPort(_ui.dataPortEdit->text()); +} + +MulticastConfigDialog::~MulticastConfigDialog() +{ +} + +void MulticastConfigDialog::dialogAccepted() +{ + QHostAddress addr; + bool addressParses = addr.setAddress(_ui.groupAddressEdit->text()); + _config->multicastAddress(_ui.groupAddressEdit->text()); + quint16 port = _ui.dataPortEdit->text().toInt(); + _config->multicastUDPPortBase(port); + _config->multicastDPort(port + 1); + _config->multicastSPort(port + 2); + _config->multicastRate(_ui.rateSpinbox->value() * 1024); + accept(); +} + +void MulticastConfigDialog::setError(QWidget* widget, + QLabel* errorMessageLabel, QString text) +{ + if (errorMessageLabel) + errorMessageLabel->setText(QString( + "<span style=\"font-weight: 600; color: #880000;\">") + text + + "</span>"); + if (widget) + widget->setStyleSheet("background-color: #ffcccc;"); +} + +void MulticastConfigDialog::setOK(QWidget* widget, QLabel* errorMessageLabel) +{ + if (errorMessageLabel) + errorMessageLabel->setText(QString( + "<span style=\"font-weight: 600; color: #008800;\">") + + tr("OK") + "</span>"); + if (widget) + widget->setStyleSheet("background-color: #ccffcc;"); +} + +void MulticastConfigDialog::validateGroupAddress(QString const& input) +{ + QHostAddress a; + + _isAddressValid = false; + + if (!a.setAddress(input)) + { + setError(_ui.groupAddressEdit, _ui.groupAddressMessage, tr( + "Not a valid IP Address")); + revalidateButtons(); + return; + } + + // check if it is IPv4 + if (a.protocol() != QAbstractSocket::IPv4Protocol) + { + setError(_ui.groupAddressEdit, _ui.groupAddressMessage, tr( + "Not a valid IPv4 Address")); + revalidateButtons(); + return; + } + + // check if it is a valid multicast address + quint32 addr = a.toIPv4Address(); + if ((addr & 0xf0000000) != 0xe0000000) + { + setError(_ui.groupAddressEdit, _ui.groupAddressMessage, tr( + "Not an IPv4 multicast address")); + revalidateButtons(); + return; + } + + _isAddressValid = true; + setOK(_ui.groupAddressEdit, _ui.groupAddressMessage); + revalidateButtons(); +} + +void MulticastConfigDialog::validateDataPort(QString const& input) +{ + bool ok; + int p = input.toInt(&ok, 0); + + _isPortValid = false; + + if (!ok) + { + setError(_ui.dataPortEdit, _ui.dataPortMessage, tr("Not a number")); + revalidateButtons(); + return; + } + + if (p < 0) + { + setError(_ui.dataPortEdit, _ui.dataPortMessage, tr("Must be positive")); + revalidateButtons(); + return; + } + + if (p < 1024) + { + setError(_ui.dataPortEdit, _ui.dataPortMessage, tr( + "Must not be a privileged port")); + revalidateButtons(); + return; + } + + if (p > 65535) + { + setError(_ui.dataPortEdit, _ui.dataPortMessage, tr( + "Port number too large")); + revalidateButtons(); + return; + } + + _isPortValid = true; + setOK(_ui.dataPortEdit, _ui.dataPortMessage); + revalidateButtons(); +} + +void MulticastConfigDialog::revalidateButtons() +{ + _ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(_isAddressValid + && _isPortValid); +} diff --git a/src/gui/multicastConfigDialog.h b/src/gui/multicastConfigDialog.h new file mode 100644 index 0000000..6421813 --- /dev/null +++ b/src/gui/multicastConfigDialog.h @@ -0,0 +1,38 @@ +#ifndef MULTICASTCONFIGDIALOG_H +#define MULTICASTCONFIGDIALOG_H + +#include <QtGui/QDialog> +#include <QPointer> +#include "ui_multicastConfigDialog.h" +#include <pvsinterface.h> + +class McastConfiguration; + +class MulticastConfigDialog : public QDialog +{ + Q_OBJECT + +public: + MulticastConfigDialog(QWidget* parent = 0); + MulticastConfigDialog(McastConfiguration* dbusIface, QWidget *parent = 0); + ~MulticastConfigDialog(); + +private: + Ui::MulticastConfigDialogClass _ui; + McastConfiguration* _config; + bool _isAddressValid; + bool _isPortValid; + + void setupUi(); + + void setError(QWidget* input, QLabel* messageLabel, QString text); + void setOK(QWidget* input, QLabel* messageLabel); + void revalidateButtons(); + +private slots: + void dialogAccepted(); + void validateGroupAddress(QString const&); + void validateDataPort(QString const&); +}; + +#endif // MULTICASTCONFIGDIALOG_H diff --git a/src/gui/ui/clientConfigDialog.ui b/src/gui/ui/clientConfigDialog.ui index 3262b6b..bb4bdc9 100644 --- a/src/gui/ui/clientConfigDialog.ui +++ b/src/gui/ui/clientConfigDialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>438</width> - <height>257</height> + <width>445</width> + <height>266</height> </rect> </property> <property name="windowTitle"> @@ -27,7 +27,7 @@ <enum>QTabWidget::North</enum> </property> <property name="currentIndex"> - <number>0</number> + <number>2</number> </property> <widget class="QWidget" name="tabPermissions"> <attribute name="title"> @@ -197,6 +197,64 @@ </item> </layout> </widget> + <widget class="QWidget" name="networkTab"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <attribute name="title"> + <string>Network</string> + </attribute> + <layout class="QFormLayout" name="formLayout"> + <item row="2" column="1"> + <widget class="QComboBox" name="interfaceList"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>true</bool> + </property> + <property name="insertPolicy"> + <enum>QComboBox::NoInsert</enum> + </property> + <property name="frame"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Network Interface</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QPushButton" name="reloadInterfaceListButton"> + <property name="text"> + <string>Reload List</string> + </property> + </widget> + </item> + </layout> + </widget> </widget> </item> <item> diff --git a/src/gui/ui/clientFileReceiveDialog.ui b/src/gui/ui/clientFileReceiveDialog.ui index af3a135..a137def 100644 --- a/src/gui/ui/clientFileReceiveDialog.ui +++ b/src/gui/ui/clientFileReceiveDialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>208</width> - <height>108</height> + <width>528</width> + <height>117</height> </rect> </property> <property name="windowTitle"> @@ -61,6 +61,13 @@ </property> </spacer> </item> + <item> + <widget class="QLabel" name="labelStatus"> + <property name="text"> + <string/> + </property> + </widget> + </item> </layout> </item> <item> diff --git a/src/gui/ui/clientFileSendDialog.ui b/src/gui/ui/clientFileSendDialog.ui index d2d9c75..85462ba 100644 --- a/src/gui/ui/clientFileSendDialog.ui +++ b/src/gui/ui/clientFileSendDialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>186</width> - <height>108</height> + <width>528</width> + <height>144</height> </rect> </property> <property name="windowTitle"> @@ -33,7 +33,7 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="label"> <property name="text"> @@ -61,10 +61,17 @@ </property> </spacer> </item> + <item> + <widget class="QLabel" name="labelStatus"> + <property name="text"> + <string/> + </property> + </widget> + </item> </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QLabel" name="labelA"> <property name="text"> diff --git a/src/gui/ui/clientNicklistDialog.ui b/src/gui/ui/clientNicklistDialog.ui index afd84f1..3679b55 100644 --- a/src/gui/ui/clientNicklistDialog.ui +++ b/src/gui/ui/clientNicklistDialog.ui @@ -29,6 +29,13 @@ <widget class="QListWidget" name="listWidget"/> </item> <item> + <widget class="QCheckBox" name="sendToAllCheckBox"> + <property name="text"> + <string>Send to &all</string> + </property> + </widget> + </item> + <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <spacer name="horizontalSpacer"> diff --git a/src/gui/ui/clientToolbar.ui b/src/gui/ui/clientToolbar.ui index 5a59c5f..d70857a 100644 --- a/src/gui/ui/clientToolbar.ui +++ b/src/gui/ui/clientToolbar.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>577</width> + <width>328</width> <height>28</height> </rect> </property> @@ -144,46 +144,6 @@ p, li { white-space: pre-wrap; } </spacer> </item> <item> - <widget class="QCheckBox" name="vncCheckBox"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="toolTip"> - <string>Enable/Disable VNC only for this session</string> - </property> - <property name="text"> - <string>Allow VNC</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600; font-style:italic; color:#0055ff;">Pool Video Switch</span></p></body></html></string> - </property> - </widget> - </item> - <item> <widget class="QLabel" name="label_3"> <property name="maximumSize"> <size> diff --git a/src/gui/ui/mainwindow.ui b/src/gui/ui/mainwindow.ui index eb49d1b..7913e38 100644 --- a/src/gui/ui/mainwindow.ui +++ b/src/gui/ui/mainwindow.ui @@ -28,8 +28,8 @@ <rect> <x>0</x> <y>0</y> - <width>776</width> - <height>534</height> + <width>778</width> + <height>542</height> </rect> </property> <layout class="QGridLayout" name="gridLayout_2"> @@ -195,7 +195,7 @@ <x>0</x> <y>0</y> <width>838</width> - <height>28</height> + <height>23</height> </rect> </property> <widget class="QMenu" name="menu_File"> @@ -243,9 +243,16 @@ </property> <addaction name="actionAbout_pvs"/> </widget> + <widget class="QMenu" name="menuNetwork"> + <property name="title"> + <string>Network</string> + </property> + <addaction name="actionConfigure_Network"/> + </widget> <addaction name="menu_File"/> <addaction name="menuClients"/> <addaction name="menuLogging"/> + <addaction name="menuNetwork"/> <addaction name="menu_Help"/> </widget> <widget class="QStatusBar" name="statusBar"/> @@ -286,6 +293,7 @@ <addaction name="actionView"/> <addaction name="actionLock"/> <addaction name="actionChat"/> + <addaction name="actionShowProcesses"/> </widget> <action name="actionShow_Username"> <property name="checkable"> @@ -531,6 +539,26 @@ <string>-</string> </property> </action> + <action name="actionConfigure_Network"> + <property name="text"> + <string>&Configure...</string> + </property> + <property name="toolTip"> + <string>Configure Network Parameters</string> + </property> + </action> + <action name="actionShowProcesses"> + <property name="icon"> + <iconset resource="../../../pvsmgr.qrc"> + <normaloff>:/icons/gears.png</normaloff>:/icons/gears.png</iconset> + </property> + <property name="text"> + <string>showProcesses</string> + </property> + <property name="toolTip"> + <string>Show Processes of the selected Client</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <resources> diff --git a/src/gui/ui/mainwindowtouch.ui b/src/gui/ui/mainwindowtouch.ui index 9030b17..24f40b6 100644 --- a/src/gui/ui/mainwindowtouch.ui +++ b/src/gui/ui/mainwindowtouch.ui @@ -28,8 +28,8 @@ <rect> <x>0</x> <y>0</y> - <width>1327</width> - <height>658</height> + <width>1329</width> + <height>660</height> </rect> </property> <layout class="QGridLayout" name="gridLayout_3"> @@ -365,6 +365,9 @@ <addaction name="actionresetall"/> <addaction name="separator"/> <addaction name="actionDozent"/> + <addaction name="separator"/> + <addaction name="actionConfigure_Network"/> + <addaction name="actionShowProcesses"/> </widget> <action name="actionShow_Username"> <property name="checkable"> @@ -636,6 +639,27 @@ <string>Ctrl+D</string> </property> </action> + <action name="actionConfigure_Network"> + <property name="icon"> + <iconset resource="../../../pvsmgr.qrc"> + <normaloff>:/netconf</normaloff>:/netconf</iconset> + </property> + <property name="text"> + <string>Configure Network...</string> + </property> + </action> + <action name="actionShowProcesses"> + <property name="icon"> + <iconset resource="../../../pvsmgr.qrc"> + <normaloff>:/icons/gears.png</normaloff>:/icons/gears.png</iconset> + </property> + <property name="text"> + <string>showProcesses</string> + </property> + <property name="toolTip"> + <string>Show Processes of the selected Client</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <resources> diff --git a/src/gui/ui/multicastConfigDialog.ui b/src/gui/ui/multicastConfigDialog.ui new file mode 100644 index 0000000..1ddf02c --- /dev/null +++ b/src/gui/ui/multicastConfigDialog.ui @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MulticastConfigDialogClass</class> + <widget class="QDialog" name="MulticastConfigDialogClass"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>331</width> + <height>314</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>PVS - Multicast Configuration</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<table style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;"> +<tr> +<td style="border: none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You need to specify connection parameters for multicast messaging on your network. These parameters will automatically be distributed to client computers, so you need to assign them only once.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You will probably want to assign an address from the <span style=" text-decoration: underline;">239.0.0.0/8</span> &quot;Administratively Scoped&quot; range.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Do not assign arbitrary numbers without checking with your network administrator!</span></p></td></tr></table></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Multicast Group Address</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="groupAddressEdit"> + <property name="inputMask"> + <string notr="true">009.009.009.009; </string> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QLabel" name="groupAddressMessage"> + <property name="text"> + <string><span style=" font-weight:600; color:#008800;">OK</span></string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Data Port (1024-65535)</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="dataPortEdit"> + <property name="inputMask"> + <string notr="true">00009; </string> + </property> + <property name="maxLength"> + <number>5</number> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2"> + <widget class="QLabel" name="dataPortMessage"> + <property name="text"> + <string><span style=" font-weight:600; color:#008800;">OK</span></string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Transmission Rate</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QSpinBox" name="rateSpinbox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="suffix"> + <string> KiB/s</string> + </property> + <property name="maximum"> + <number>10240</number> + </property> + <property name="singleStep"> + <number>10</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <layoutdefault spacing="6" margin="11"/> + <resources/> + <connections/> +</ui> diff --git a/src/net/SslServer.cpp b/src/net/SslServer.cpp index e353e0a..9940a61 100644 --- a/src/net/SslServer.cpp +++ b/src/net/SslServer.cpp @@ -59,7 +59,7 @@ void SslServer::incomingConnection(int socketDescriptor) void SslServer :: sslErrors ( const QList<QSslError> & errors ) { - printf("FIXME: SSL ERRORS on SERVER: %s\n", errors.begin()->errorString().toUtf8().data()); + qDebug("FIXME: SSL ERRORS on SERVER: %s", qPrintable(errors.begin()->errorString())); } void SslServer::timerEvent (QTimerEvent* event) @@ -98,7 +98,7 @@ bool SslServer::hasPendingConnections() { for (QList<QSslSocket*>::iterator it = _pending.begin(); it != _pending.end(); it++) { - printf("State: %d - Encrypted: %d\n", (int)(*it)->state(), (*it)->isEncrypted()); + qDebug("State: %d - Encrypted: %d", (int)(*it)->state(), (*it)->isEncrypted()); if ((*it)->state() == QAbstractSocket::ConnectedState && (*it)->isEncrypted()) return true; } return false; diff --git a/src/net/mcast/CMakeLists.txt b/src/net/mcast/CMakeLists.txt new file mode 100644 index 0000000..e92b090 --- /dev/null +++ b/src/net/mcast/CMakeLists.txt @@ -0,0 +1,61 @@ +INCLUDE(../../../OpenPGMConfig.cmake) + +ADD_DEFINITIONS( + ${LIBPGM_CXXFLAGS} + -D__STDC_CONSTANT_MACROS + -D__STDC_LIMIT_MACROS +) + +# OpenPGM uses the C99 restrict keyword which g++ does not recognize: +#IF(CMAKE_COMPILER_IS_GNUCXX) +# ADD_DEFINITIONS(${LIBPGM_CXXFLAGS}) +#ENDIF(CMAKE_COMPILER_IS_GNUCXX) + +INCLUDE(${QT_USE_FILE}) + +SET(pvsmcast_MOC_HDRS + McastConfiguration.h + McastPGMSocket.h + McastReceiver.h + McastSender.h +) + +SET(pvsmcast_HDRS + McastConfiguration.h + McastPGMSocket.h + McastReceiver.h + McastSender.h +) + +SET(pvsmcast_SRCS + McastConfiguration.cpp + McastPGMSocket.cpp + McastReceiver.cpp + McastSender.cpp +) + +QT4_WRAP_CPP( + pvsmcast_MOC_SRCS + ${pvsmcast_MOC_HDRS} +) + +SET_SOURCE_FILES_PROPERTIES(${pvsmcast_SRCS} ${pvsmcast_MOC_SRCS} + PROPERTIES + OBJECT_DEPENDS "3rdparty/libpgm.a" # Make sure libpgm gets unpacked before building C++ files +) + +ADD_LIBRARY( + pvsmcast + STATIC + ${pvsmcast_HDRS} + ${pvsmcast_SRCS} + ${pvsmcast_MOC_SRCS} +) + +TARGET_LINK_LIBRARIES( + pvsmcast + pgm + ${QT_LIBRARIES} +) + +ADD_SUBDIRECTORY(trial_programs) diff --git a/src/net/mcast/McastConfiguration.cpp b/src/net/mcast/McastConfiguration.cpp new file mode 100644 index 0000000..6c5e620 --- /dev/null +++ b/src/net/mcast/McastConfiguration.cpp @@ -0,0 +1,57 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastConfiguration.cpp +# - hold Multicast protocol configuration data +# ----------------------------------------------------------------------------- +*/ + +#include <QSettings> + +#include "McastConfiguration.h" + +void McastConfiguration::loadFrom(QSettings* _settings, char const* group) +{ + if (group) + _settings->beginGroup(group); + + _multicastAddress = _settings->value("groupAddress", DEFAULT_MULTICAST_ADDRESS).toString(); + _multicastInterface = _settings->value("interface", DEFAULT_MULTICAST_INTERFACE).toString(); + _multicastMTU = _settings->value("mtu", DEFAULT_MULTICAST_MTU).value<quint16>(); + _multicastRate = _settings->value("rate", DEFAULT_MULTICAST_RATE).value<quint32>(); + _multicastUseUDP = _settings->value("use-udp", DEFAULT_MULTICAST_USEUDP).toBool(); + _multicastWinSize = _settings->value("winsize", DEFAULT_MULTICAST_WSIZ).value<quint16>(); + _multicastUDPPortBase = _settings->value("portbase", DEFAULT_MULTICAST_UDPPORT).value<quint16>(); + _multicastDPort = _settings->value("dport", DEFAULT_MULTICAST_DPORT).value<quint16>(); + _multicastSPort = _settings->value("sport", DEFAULT_MULTICAST_SPORT).value<quint16>(); + + if (group) + _settings->endGroup(); +} + +void McastConfiguration::writeTo(QSettings* _settings, char const* group) const +{ + if (group) + _settings->beginGroup(group); + + _settings->setValue("groupAddress", _multicastAddress); + _settings->setValue("interface", _multicastInterface); + _settings->setValue("mtu", _multicastMTU); + _settings->setValue("rate", _multicastRate); + _settings->setValue("use-udp", _multicastUseUDP); + _settings->setValue("winsize", _multicastWinSize); + _settings->setValue("portbase", _multicastUDPPortBase); + _settings->setValue("dport", _multicastDPort); + _settings->setValue("sport", _multicastSPort); + + if (group) + _settings->endGroup(); +} diff --git a/src/net/mcast/McastConfiguration.h b/src/net/mcast/McastConfiguration.h new file mode 100644 index 0000000..53f7a54 --- /dev/null +++ b/src/net/mcast/McastConfiguration.h @@ -0,0 +1,204 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastConfiguration.h +# - hold Multicast protocol configuration data +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTCONFIGURATION_H_ +#define MCASTCONFIGURATION_H_ + +#include <QObject> +#include <QString> +#include <QtGlobal> + +#include "McastConstants.h" + +class QSettings; + +class McastConfiguration: public QObject +{ + Q_OBJECT +public: + McastConfiguration(QObject* parent = 0) : + QObject(parent), + _multicastInterface(DEFAULT_MULTICAST_INTERFACE), + _multicastAddress(DEFAULT_MULTICAST_ADDRESS), + _multicastRate(DEFAULT_MULTICAST_RATE), + _multicastSPort(DEFAULT_MULTICAST_SPORT), + _multicastDPort(DEFAULT_MULTICAST_DPORT), + _multicastWinSize(DEFAULT_MULTICAST_WSIZ), + _multicastMTU(DEFAULT_MULTICAST_MTU), + _multicastUDPPortBase(DEFAULT_MULTICAST_UDPPORT), + _multicastUseUDP(DEFAULT_MULTICAST_USEUDP) + { + } + + McastConfiguration(McastConfiguration const& other, QObject* parent = 0) : + QObject(parent), + _multicastInterface(other._multicastInterface), + _multicastAddress(other._multicastAddress), + _multicastRate(other._multicastRate), + _multicastSPort(other._multicastSPort), + _multicastDPort(other._multicastDPort), + _multicastWinSize(other._multicastWinSize), + _multicastMTU(other._multicastMTU), + _multicastUDPPortBase(other._multicastUDPPortBase), + _multicastUseUDP(other._multicastUseUDP) + { + } + + virtual ~McastConfiguration() + { + } + + QString multicastAddress() const + { + return _multicastAddress; + } + McastConfiguration* multicastAddress(QString const& address) + { + _multicastAddress = address; + return this; + } + + quint16 multicastSPort() const + { + return _multicastSPort; + } + McastConfiguration* multicastSPort(quint16 port) + { + _multicastSPort = port; + return this; + } + + quint16 multicastDPort() const + { + return _multicastDPort; + } + McastConfiguration* multicastDPort(quint16 port) + { + _multicastDPort = port; + return this; + } + + quint32 multicastRate() const + { + return _multicastRate; + } + McastConfiguration* multicastRate(quint32 rate) + { + _multicastRate = rate; + return this; + } + + quint16 multicastWinSize() const + { + return _multicastWinSize; + } + McastConfiguration* multicastWinSize(quint16 size) + { + _multicastWinSize = size; + return this; + } + + quint16 multicastMTU() const + { + return _multicastMTU; + } + McastConfiguration* multicastMTU(quint16 mtu) + { + _multicastMTU = mtu; + return this; + } + + bool multicastUseUDP() const + { + return _multicastUseUDP; + } + McastConfiguration* multicastUseUDP(bool useUDP) + { + _multicastUseUDP = useUDP; + return this; + } + + quint16 multicastUDPPortBase() const + { + return _multicastUDPPortBase; + } + McastConfiguration* multicastUDPPortBase(quint16 port) + { + _multicastUDPPortBase = port; + return this; + } + + QString multicastInterface() const + { + return _multicastInterface; + } + McastConfiguration* multicastInterface(QString const& interface) + { + _multicastInterface = interface; + return this; + } + + quint16 multicastUDPUPort() const + { + return _multicastUDPPortBase; + } + + quint16 multicastUDPMPort() const + { + return _multicastUDPPortBase; + } + + void commit() + { + emit changed(); + } + + McastConfiguration& operator=(McastConfiguration const& source) + { + if(this != &source) + { + _multicastInterface = source._multicastInterface; + _multicastAddress = source._multicastAddress; + _multicastRate = source._multicastRate; + _multicastSPort = source._multicastSPort; + _multicastDPort = source._multicastDPort; + _multicastWinSize = source._multicastWinSize; + _multicastMTU = source._multicastMTU; + _multicastUDPPortBase = source._multicastUDPPortBase; + _multicastUseUDP = source._multicastUseUDP; + } + return *this; + } + + void loadFrom(QSettings* settings, char const* group = 0); + void writeTo(QSettings* settings, char const* group = 0) const; + +signals: + void changed(); + +private: + QString _multicastInterface; + QString _multicastAddress; + quint32 _multicastRate; + quint16 _multicastSPort; + quint16 _multicastDPort; + quint16 _multicastWinSize; + quint16 _multicastMTU; + quint16 _multicastUDPPortBase; + bool _multicastUseUDP; +}; + +#endif /* MCASTCONFIGURATION_H_ */ diff --git a/src/net/mcast/McastConstants.h b/src/net/mcast/McastConstants.h new file mode 100644 index 0000000..624e195 --- /dev/null +++ b/src/net/mcast/McastConstants.h @@ -0,0 +1,36 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastMagic.h +# - Specify the magic numbers for the McastFT protocol +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTMAGIC_H_ +#define MCASTMAGIC_H_ + +#include <stdint.h> + +#define MCASTFT_MAGIC UINT64_C(0x6d60ad83825fb7f9) +#define DEFAULT_MULTICAST_INTERFACE "" +#define DEFAULT_MULTICAST_ADDRESS "239.255.220.207" +#define DEFAULT_MULTICAST_SPORT 6964 +#define DEFAULT_MULTICAST_DPORT 6965 +#define DEFAULT_MULTICAST_USEUDP true +#define DEFAULT_MULTICAST_UDPPORT 6966 +#define DEFAULT_MULTICAST_WSIZ 30 +#define DEFAULT_MULTICAST_RATE (100*1024) +#define DEFAULT_MULTICAST_MTU 1400 +#define DEFAULT_MULTICAST_APDU 1200 +#define DEFAULT_MULTICAST_CHUNK 1024 +#define DEFAULT_MULTICAST_SHUTDOWN_TIMEOUT 10000 + +#endif /* MCASTMAGIC_H_ */ diff --git a/src/net/mcast/McastPGMSocket.cpp b/src/net/mcast/McastPGMSocket.cpp new file mode 100644 index 0000000..731fc13 --- /dev/null +++ b/src/net/mcast/McastPGMSocket.cpp @@ -0,0 +1,666 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastPGMSocket.cpp +# - wrap OpenPGM Sockets in a nicer interface -- implementation +# ----------------------------------------------------------------------------- +*/ + +#include <cstdlib> + +#include <sys/poll.h> +#include <sys/socket.h> + +#include <QByteArray> +#include <QList> +#include <QtDebug> +#include <QPointer> +#include <QSocketNotifier> +#include <QTimer> + +#include <pgm/pgm.h> + +#include "McastPGMSocket.h" + +using namespace std; + +class McastPGMSocket_priv +{ +public: + McastPGMSocket_priv() : + socket(0), + send_notif(0) + { + } + ~McastPGMSocket_priv() + { + if (socket) + pgm_close(socket, 0); + Q_FOREACH(QSocketNotifier* notif, _notifs) + { + delete notif; + } + if (send_notif) + delete send_notif; + } + + pgm_sock_t* socket; + McastPGMSocket::Direction direction; + QSocketNotifier* send_notif; + QList<QSocketNotifier*> _notifs; + + QSocketNotifier* notifier_for(int fd) { + Q_FOREACH(QSocketNotifier* notif, _notifs) + { + if(notif->socket() == fd) + { + return notif; + } + } + return 0; + } +}; + +static void _ensurePGMInited() +{ + if (!pgm_supported()) + { + pgm_error_t* err; + int good = pgm_init(&err); + if (!good) + { + qCritical() << "Could not init OpenPGM library: PGM Error: " << (err->message ? err->message : "(null)"); + std::exit(1); + } + } +} + +McastPGMSocket::McastPGMSocket(QObject* parent) : + QObject(parent), + _priv(new McastPGMSocket_priv), + _opened(false), + _finished(false), + _nakTimeout(new QTimer()), + _dataTimeout(new QTimer()), + _sendTimeout(new QTimer()), + _shutdownTimer(0), + _shutdown_timeout(0) +{ + _ensurePGMInited(); + + _nakTimeout->setSingleShot(true); + _dataTimeout->setSingleShot(true); + _sendTimeout->setSingleShot(true); + + connect(_nakTimeout, SIGNAL(timeout()), this, SLOT(handleNakTimeout())); + connect(_dataTimeout, SIGNAL(timeout()), this, SLOT(handleDataTimeout())); + connect(_sendTimeout, SIGNAL(timeout()), this, SLOT(canSend())); +} + +McastPGMSocket::~McastPGMSocket() +{ + delete _priv; + delete _nakTimeout; + delete _dataTimeout; + delete _sendTimeout; +} + +bool McastPGMSocket::open(McastConfiguration const* config, Direction direction) +{ + _priv->direction = direction; + + pgm_error_t* err = 0; + int good; + + pgm_addrinfo_t* addrinfo; + // parse the address string + good = pgm_getaddrinfo((config->multicastInterface() + ";" + config->multicastAddress()).toLatin1().constData(), + 0, &addrinfo, &err); + if (!good) + { + qCritical() << "Could not parse address info: PGM Error: " + << err->message; + return false; + } + + sa_family_t family = addrinfo->ai_send_addrs[0].gsr_group.ss_family; + + if(config->multicastUseUDP()) + { + good = pgm_socket(&_priv->socket, family, SOCK_SEQPACKET, IPPROTO_UDP, &err); + } + else + { + good = pgm_socket(&_priv->socket, family, SOCK_SEQPACKET, IPPROTO_PGM, &err); + } + + if (!good) + { + qCritical() << "Could not open socket: PGM Error: " << err->message; + pgm_error_free(err); + return false; + } + + unsigned const ambient_spm = 2000 * 1000; // every one hundred milliseconds (approx.) + + /* Options for sending data */ + const int spm_heartbeat[] = + { 512 * 1000, + 1024 * 1000, + 2048 * 1000, + 4096 * 1000 }, + max_rate = 0, + max_window = config->multicastWinSize() * config->multicastRate() / config->multicastMTU(); + // const int max_window_sqns = 3000; + qDebug() << "Computed window size " << max_window << " packets"; + +// pgm_setsockopt(_priv->socket, PGM_SEND_ONLY, &send_only, +// sizeof(send_only)); + + // SPM messages + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_AMBIENT_SPM, &ambient_spm, sizeof(ambient_spm)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_HEARTBEAT_SPM, &spm_heartbeat, sizeof(spm_heartbeat)); + + // Transmit window + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_TXW_MAX_RTE, &max_rate, sizeof(max_rate)); +// pgm_setsockopt(_priv->socket, PGM_TXW_SECS, &max_window, sizeof(max_window)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_TXW_SQNS, &max_window, sizeof(max_window)); + + /* Options for receiving data */ + const int passive = 0, + spmr_expiry = 500 * 1000, + nak_bo_ivl = 200 * 1000, + nak_rpt_ivl = 500 * 1000, + nak_rdata_ivl = 500 * 1000, + nak_data_retries = 50, + nak_ncf_retries = 50; + qDebug() << "Computed window size " << max_window << " packets"; + +// pgm_setsockopt(_priv->socket, PGM_RECV_ONLY, &recv_only, sizeof(recv_only)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_PASSIVE, &passive, sizeof(passive)); +// pgm_setsockopt(_priv->socket, PGM_RXW_MAX_RTE, &max_rate, sizeof(max_rate)); +// pgm_setsockopt(_priv->socket, PGM_RXW_SECS, &max_window, sizeof(max_window)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_SPMR_EXPIRY, &spmr_expiry, sizeof(spmr_expiry)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_NAK_BO_IVL, &nak_bo_ivl, sizeof(nak_bo_ivl)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_NAK_RPT_IVL, &nak_rpt_ivl, sizeof(nak_rpt_ivl)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_NAK_RDATA_IVL, &nak_rdata_ivl, sizeof(nak_rdata_ivl)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_NAK_DATA_RETRIES, &nak_data_retries, sizeof(nak_data_retries)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_NAK_NCF_RETRIES, &nak_ncf_retries, sizeof(nak_ncf_retries)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_RXW_SQNS, &max_window, sizeof(max_window)); + + /* Try using PGMCC */ + const struct pgm_pgmccinfo_t pgmccinfo = { + 100 /* usecs */ * 1000 /* msecs */, + 75 /* from OpenPGM examples */, + 500 /* from PGMCC internet-draft */ + }; + good = pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_USE_PGMCC, &pgmccinfo, sizeof(pgmccinfo)); + if(!good) + { + qCritical() << "Could not enable PGMCC"; + return false; + } + +// /* Forward Error Correction */ +// const struct pgm_fecinfo_t pgmfecinfo = { +// 255 /* from OpenPGM examples */, +// 2 /* send two proactive packets */, +// 8 /* from OpenPGM examples */, +// 1 /* enable on-demand parity */, +// 1 /* enable variable packet length */ +// }; +// good = pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_USE_FEC, &pgmfecinfo, sizeof(pgmfecinfo)); +// if(!good) +// { +// qCritical() << "Could not enable FEC"; +// return false; +// } + + // Peer Expiry: We will give 1 minute. + int const peer_expiry = 60 /* seconds */ * 1000000 /* microseconds */; + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_PEER_EXPIRY, &peer_expiry, sizeof(peer_expiry)); + + // MTU + int const mtu = config->multicastMTU(); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_MTU, &mtu, sizeof(mtu)); + + pgm_sockaddr_t addr; + addr.sa_addr.sport = config->multicastSPort(); + addr.sa_port = config->multicastDPort(); + good = pgm_gsi_create_from_hostname(&addr.sa_addr.gsi, &err); + if (!good) + { + qCritical() << "Could not generate a GSI: PGM Error: " << err->message; + pgm_error_free(err); + return false; + } + + struct pgm_interface_req_t ifreq; + ifreq.ir_interface = addrinfo->ai_send_addrs[0].gsr_interface; + ifreq.ir_scope_id = 0; + if (AF_INET6 == family) + { + ifreq.ir_scope_id = ((struct sockaddr_in6*)&addrinfo->ai_send_addrs[0])->sin6_scope_id; + } + + // UDP Encapsulation + if(config->multicastUseUDP()) + { + const int uport = config->multicastUDPUPort(); + const int mport = config->multicastUDPMPort(); + + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_UDP_ENCAP_MCAST_PORT, &mport, sizeof(mport)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_UDP_ENCAP_UCAST_PORT, &uport, sizeof(uport)); + } + + good = pgm_bind3(_priv->socket, &addr, sizeof(addr), &ifreq , sizeof(ifreq), &ifreq, sizeof(ifreq), &err); + if (!good) + { + qCritical() << "Could not bind socket: PGM Error: " << err->message; + pgm_error_free(err); + return false; + } + + // qDebug() << "Max APDU is " << _priv->socket->max_apdu; + // qDebug() << "Max TPDU is " << _priv->socket->max_tpdu; + // qDebug() << "Max TSDU Fragment is " << _priv->socket->max_tsdu_fragment; + // qDebug() << "TXW_SQNS is " << _priv->socket->txw_sqns; + + // join the group + for (unsigned i = 0; i < addrinfo->ai_recv_addrs_len; i++) + { + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_JOIN_GROUP, + &addrinfo->ai_recv_addrs[i], sizeof(struct group_req)); + } + + // set send address + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_SEND_GROUP, &addrinfo->ai_send_addrs[0], + sizeof(struct group_req)); + + // IP parameters + const int nonblocking = 1, multicast_loop = 0, multicast_hops = 16; + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_MULTICAST_LOOP, &multicast_loop, + sizeof(multicast_loop)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_MULTICAST_HOPS, &multicast_hops, + sizeof(multicast_hops)); + pgm_setsockopt(_priv->socket, IPPROTO_PGM, PGM_NOBLOCK, &nonblocking, + sizeof(nonblocking)); + + good = pgm_connect(_priv->socket, &err); + if (!good) + { + qCritical() << "Could not connect socket: PGM Error: " << err->message; + pgm_error_free(err); + return false; + } + + _opened = true; + + setupNotifiers(); + + pgm_freeaddrinfo(addrinfo); + + /* Prime the generation of SPM packets during the waiting period */ + if(_priv->direction == PSOCK_WRITE) + QTimer::singleShot(0, this, SLOT(handleNak())); + + return true; +} + +void McastPGMSocket::setupNotifiers() +{ + int recv_sock, repair_sock, pending_sock; + char const* slotname = (_priv->direction == PSOCK_WRITE) ? SLOT(handleNak(int)) : SLOT(handleData(int)); + + struct pollfd pollin[10]; + int in_nfds = 10; + pgm_poll_info(_priv->socket, pollin, &in_nfds, POLLIN); + for(int i = 0; i < in_nfds; i++) + { + QSocketNotifier* notif = new QSocketNotifier(pollin[i].fd, QSocketNotifier::Read, this); + _priv->_notifs.append(notif); + connect(notif, SIGNAL(activated(int)), this, slotname); + } + + if(_priv->direction == PSOCK_WRITE) + { + struct pollfd pfd; + int nfds = 1; + pgm_poll_info(_priv->socket, &pfd, &nfds, POLLOUT); + _priv->send_notif = new QSocketNotifier(pfd.fd, QSocketNotifier::Write, this); + connect(_priv->send_notif, SIGNAL(activated(int)), this, SLOT(canSend())); + } +} + +void McastPGMSocket::handleNak(int fd) +{ + qDebug() << "handleNak(" << fd << ")"; + + QSocketNotifier* notif = _priv->notifier_for(fd); + notif->setEnabled(false); + + if (_shutdownTimer) + { + _shutdownTimer->start(_shutdown_timeout); + qDebug() << "Started shutdown timer"; + } + + handleNak(); + + notif->setEnabled(true); +} + +void McastPGMSocket::handleNak() +{ + if (_finished) + return; + + // QTimer::singleShot(1000, this, SLOT(handleNakTimeout())); + + // to handle NAKs in OpenPGM, we need to pgm_recv: + char buf[4096]; + pgm_error_t* err = 0; + + int status; + // while we don't block: + do + { + status = pgm_recv(_priv->socket, buf, sizeof(buf), MSG_DONTWAIT, 0, &err); + + if(status == PGM_IO_STATUS_TIMER_PENDING) + { + struct timeval tv; + socklen_t size = sizeof(tv); + pgm_getsockopt(_priv->socket, IPPROTO_PGM, PGM_TIME_REMAIN, &tv, &size); + const long usecs = tv.tv_sec * 1000000 + tv.tv_usec; + int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + if(msecs == 0) + msecs = 1; + qDebug() << " timer pending: " << usecs << "us (rounded to " << msecs << "ms)"; + _nakTimeout->start(msecs); + break; + } + else if(status == PGM_IO_STATUS_RATE_LIMITED) + { + struct timeval tv; + socklen_t size = sizeof(tv); + pgm_getsockopt(_priv->socket, IPPROTO_PGM, PGM_RATE_REMAIN, &tv, &size); + int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + if(msecs == 0) + msecs = 1; + qDebug() << " rate limited: " << msecs << "ms"; + _nakTimeout->start(msecs); + break; + } + else if(status == PGM_IO_STATUS_WOULD_BLOCK) + { + qDebug() << " wouldblock"; + break; + } + else + { + if(err) + { + qCritical() << "Could not handle NAKs: PGM Error: " << err->message; + pgm_error_free(err); + err = 0; + } + } + } + while (true); +} + +void McastPGMSocket::handleNakTimeout() +{ + qDebug() << "handleNakTimeout()"; + + handleNak(); +} + +void McastPGMSocket::handleData(int fd) +{ + // need to guard against destruction in finish() via signals/slots + QPointer<QSocketNotifier> notif(_priv->notifier_for(fd)); + notif->setEnabled(false); + + handleData(); + + if (notif) + notif->setEnabled(true); +} + +void McastPGMSocket::handleData() +{ + if (_finished) { + return; + } + + int status; + do + { + char buf[4096]; + size_t size; + pgm_error_t* err = 0; + + status = pgm_recv(_priv->socket, buf, sizeof(buf), MSG_DONTWAIT, &size, &err); + + if (status == PGM_IO_STATUS_NORMAL) + { + qDebug() << " normally received"; + if(size > 0) + { + QByteArray bytes(buf, size); + emit receivedPacket(bytes); + } + } + else if (status == PGM_IO_STATUS_WOULD_BLOCK) + { + qDebug() << " would block"; + // nothing more to do this time + break; + } + else if (status == PGM_IO_STATUS_TIMER_PENDING) + { + struct timeval tv; + socklen_t size = sizeof(tv); + pgm_getsockopt(_priv->socket, IPPROTO_PGM, PGM_TIME_REMAIN, &tv, &size); + const long usecs = tv.tv_sec * 1000000 + tv.tv_usec; + int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + if(msecs == 0) + msecs = 1; + qDebug() << " timer pending: " << usecs << "us (rounded to " << msecs << "ms)"; + _dataTimeout->start(msecs); + break; + } + else if (status == PGM_IO_STATUS_RATE_LIMITED) + { + struct timeval tv; + socklen_t size = sizeof(tv); + pgm_getsockopt(_priv->socket, IPPROTO_PGM, PGM_RATE_REMAIN, &tv, &size); + int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + if(msecs == 0) + msecs = 1; + qDebug() << " rate limit pending: " << msecs << "ms"; + _dataTimeout->start(msecs); + break; + } + else if (status == PGM_IO_STATUS_RESET) + { + qDebug() << " connection reset"; + emit connectionReset(); + qCritical() << "Connection Reset: PGM Error: " << (err ? err->message : "(null)"); + pgm_error_free(err); + break; + } + else if (status == PGM_IO_STATUS_FIN) + { + qDebug() << " connection finished"; + emit connectionFinished(); + break; + } + else + { + if(err) + { + qCritical() << "Could not read packet: PGM Error: " << (err ? err->message: "(null)"); + break; + } + } + + // the socket might have been closed from under us + if (!_priv->socket) + break; + } + while (true); +} + +void McastPGMSocket::handleDataTimeout() +{ + qDebug() << "handleDataTimeout()"; + + handleData(); +} + +void McastPGMSocket::canSend() +{ + if (_finished) + return; + + + if (_priv->send_notif) + { + _priv->send_notif->setEnabled(false); + } + + if(_q.isEmpty()) + { + emit readyToSend(); + } + else + { + QByteArray const packet(_q.head()); + int status; + + status = pgm_send(_priv->socket, packet.constData(), packet.size(), 0); + + if(status == PGM_IO_STATUS_NORMAL) + { + _q.dequeue(); + if(!_q.isEmpty()) + { + _priv->send_notif->setEnabled(true); + } + else + { + emit readyToSend(); + } + } + else if(status == PGM_IO_STATUS_WOULD_BLOCK) + { + _priv->send_notif->setEnabled(true); + } + else if(status == PGM_IO_STATUS_CONGESTION) + { + qDebug() << " congested..."; + // wait a short time (10ms?) + _sendTimeout->start(10); + } + else if(status == PGM_IO_STATUS_RATE_LIMITED) + { + struct timeval tv; + socklen_t size = sizeof(tv); + pgm_getsockopt(_priv->socket, IPPROTO_PGM, PGM_RATE_REMAIN, &tv, &size); + int msecs = (tv.tv_sec * 1000) + ((tv.tv_usec + 999) / 1000); + if(msecs == 0) + msecs = 1; + qDebug() << " rate_limited, waiting" << msecs << "ms"; + _sendTimeout->start(msecs); + } + else + { + qCritical() << "Unhandled status in canSend():" << status; + } + } + + if (_shutdownTimer) + _shutdownTimer->start(_shutdown_timeout); +} + +void McastPGMSocket::sendPacket(QByteArray const& bytes) +{ + if(_shutdownTimer) + { + qCritical() << "Logic error: sendPacket() after shutdown()"; + } + + _q.enqueue(bytes); + _priv->send_notif->setEnabled(true); +} + +void McastPGMSocket::finish() +{ + if (_finished) + { + return; + } + + qDebug() << "finish()"; + + Q_FOREACH(QSocketNotifier* notif, _priv->_notifs) + { + notif->setEnabled(false); + delete notif; + } + _priv->_notifs.clear(); + + if(_priv->send_notif) + { + delete _priv->send_notif; + _priv->send_notif = 0; + } + + if (_priv->socket) + { + pgm_close(_priv->socket, 1); + _priv->socket = 0; + } + + _finished = true; + + emit connectionFinished(); + + qDebug() << "Socket finished"; +} + +bool McastPGMSocket::finished() const +{ + return _finished; +} + +bool McastPGMSocket::isOpen() const +{ + return _opened && !_finished; +} + +void McastPGMSocket::shutdown(int interval) +{ + if(_priv->direction == PSOCK_READ) + return; + + _shutdown_timeout = interval; + _shutdownTimer = new QTimer(this); + connect(_shutdownTimer, SIGNAL(timeout()), this, SLOT(finish())); + if (_q.isEmpty()) + { + _shutdownTimer->start(_shutdown_timeout); + qDebug() << "Started shutdown timer"; + } +} diff --git a/src/net/mcast/McastPGMSocket.h b/src/net/mcast/McastPGMSocket.h new file mode 100644 index 0000000..4ccf931 --- /dev/null +++ b/src/net/mcast/McastPGMSocket.h @@ -0,0 +1,81 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastPGMSocket.h +# - wrap OpenPGM Sockets in a nicer interface -- interface +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTPGMSOCKET_H_ +#define MCASTPGMSOCKET_H_ + +#include <QByteArray> +#include <QObject> +#include <QQueue> + +#include <src/net/mcast/McastConfiguration.h> +#include <src/net/mcast/McastConstants.h> + +class McastPGMSocket_priv; +class QTimer; + +class McastPGMSocket : public QObject +{ + Q_OBJECT +public: + enum Direction { + PSOCK_READ, + PSOCK_WRITE + }; + + McastPGMSocket(QObject* parent = 0); + virtual ~McastPGMSocket(); + + bool open(McastConfiguration const* config, Direction direction); + bool finished() const; + bool isOpen() const; + void shutdown(int interval = DEFAULT_MULTICAST_SHUTDOWN_TIMEOUT); + +signals: + void readyToSend(); + void receivedPacket(QByteArray const& bytes); + void connectionReset(); + void connectionFinished(); + void shutdownComplete(); + +public slots: + void sendPacket(QByteArray const& bytes); + void finish(); + +private slots: + void handleNak(int fd); + void handleData(int fd); + void handleNak(); + void handleData(); + void handleNakTimeout(); + void handleDataTimeout(); + void canSend(); + +private: + McastPGMSocket_priv* _priv; + QQueue<QByteArray> _q; + bool _finished; + bool _opened; + QTimer* _nakTimeout; + QTimer* _dataTimeout; + QTimer* _sendTimeout; + QTimer* _shutdownTimer; + int _shutdown_timeout; + + void setupNotifiers(); +}; + +#endif /* MCASTPGMSOCKET_H_ */ diff --git a/src/net/mcast/McastReceiver.cpp b/src/net/mcast/McastReceiver.cpp new file mode 100644 index 0000000..1f27127 --- /dev/null +++ b/src/net/mcast/McastReceiver.cpp @@ -0,0 +1,179 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastReceiver.h +# - implement the receiver-side multicast file transfer protocol -- implementation +# ----------------------------------------------------------------------------- +*/ + +#include <QDataStream> +#include <QtDebug> +#include <QtGlobal> + +#include <pgm/pgm.h> +// OpenPGM #defines bool. This is bad in C++. +#undef bool + +#include "McastConstants.h" +#include "McastReceiver.h" + +McastReceiver::McastReceiver(QIODevice* iodev, McastConfiguration* config, QObject* parent) : + QObject(parent), + _config(config ? new McastConfiguration(*config) : 0), + _socket(0), + _curoffs(0), + _closed(false), + _hash(QCryptographicHash::Md5), + _iodev(iodev) +{ + _config->setParent(this); +} + +McastReceiver::~McastReceiver() +{ + if (_config) + delete _config; +} + +void McastReceiver::config(McastConfiguration const* config) +{ + if (_config) + delete _config; + _config = new McastConfiguration(*config, this); +} + +bool McastReceiver::start() +{ + McastConfiguration *config = _config; + if (!config) + config = new McastConfiguration(); + + if (_socket) + { + delete _socket; + } + _socket = new McastPGMSocket(this); + + connect(_socket, SIGNAL(receivedPacket(QByteArray)), SLOT(receivedPacket(QByteArray))); + connect(_socket, SIGNAL(connectionReset()), SLOT(connectionReset())); + // connect(_socket, SIGNAL(connectionFinished()), this, SLOT(connectionFinished())); + if (_socket->open(_config, McastPGMSocket::PSOCK_READ)) + { + return true; + } + else + { + disconnect(_socket, SIGNAL(receivedPacket(QByteArray)), this, SLOT(receivedPacket(QByteArray))); + disconnect(_socket, SIGNAL(connectionReset()), this, SLOT(connectionReset())); + return false; + } +} + +void McastReceiver::abort() +{ + if (_socket) + { + delete _socket; + _socket = 0; + } + + if (_iodev) + { + _iodev->close(); + } +} + +void McastReceiver::receivedPacket(QByteArray const& bytes) +{ + if(_closed) + return; + + quint16 checksum_should = qChecksum(bytes.constData(), bytes.size() - 2); + + QDataStream strm(bytes); + strm.setByteOrder(QDataStream::BigEndian); + + // read the packet + quint64 magic; + quint64 offset; + quint16 checksum; + + + strm >> magic; + if(magic != MCASTFT_MAGIC) + { + qCritical() << "Received packet whose magic number does not match. Ignoring."; + return; + } + + strm >> offset; + qDebug() << " Received packet for offset" << offset; + + if (offset == UINT64_C(0xffffffffffffffff)) + { + // this is the end of the data stream. + QByteArray md5; + strm >> md5; + + quint16 fchecksum; + strm >> fchecksum; + + // compare the hash value + if ((fchecksum != checksum_should) || (md5 != _hash.result())) + { + _close(RES_MD5_MISMATCH); + } + else + { + _close(RES_OK); + } + + return; + } + else if (offset != _curoffs) + { + qCritical() << "Packet loss or double delivery. PGM should have prevented this. Bailing out."; + _close(RES_OFFSET_MISMATCH); + return; + } + + QByteArray contents; + strm >> contents; + _curoffs += contents.size(); + + strm >> checksum; + if(checksum != checksum_should) + { + qCritical() << "Checksum does not match. Bailing out."; + _close(RES_CHECKSUM_MISMATCH); + return; + } + + _hash.addData(contents); + + _iodev->write(contents); + + emit progress(_curoffs); +} + +void McastReceiver::connectionReset() +{ + _close(RES_CONNECTION_RESET); +} + +void McastReceiver::_close(Result result) +{ + _iodev->close(); + _socket->finish(); + + _closed = true; + emit finished(result); +} diff --git a/src/net/mcast/McastReceiver.h b/src/net/mcast/McastReceiver.h new file mode 100644 index 0000000..247733d --- /dev/null +++ b/src/net/mcast/McastReceiver.h @@ -0,0 +1,80 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastReceiver.h +# - implement the receiver-side multicast file transfer protocol -- interface +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTRECEIVER_H_ +#define MCASTRECEIVER_H_ + +#include <QByteArray> +#include <QCryptographicHash> +#include <QIODevice> +#include <QObject> +#include <QtGlobal> + +#include <src/net/mcast/McastConfiguration.h> +#include <src/net/mcast/McastPGMSocket.h> + +class McastReceiver : public QObject +{ + Q_OBJECT +public: + enum Result { + RES_OK, + RES_ABORTED, + RES_OFFSET_MISMATCH, + RES_CHECKSUM_MISMATCH, + RES_MD5_MISMATCH, + RES_CONNECTION_RESET + }; + + McastReceiver(QIODevice* iodev, McastConfiguration* config = 0, QObject* parent = 0); + virtual ~McastReceiver(); + + McastConfiguration* config() + { + return _config; + } + + void config(McastConfiguration const* config); + + static inline bool is_error(Result result) + { + return result != RES_OK; + } + +signals: + void finished(int result); + void progress(quint64 offset); + +public slots: + bool start(); + void abort(); + +private: + McastConfiguration* _config; + McastPGMSocket* _socket; + quint64 _curoffs; + bool _closed; + QCryptographicHash _hash; + QIODevice* _iodev; + +private slots: + void receivedPacket(QByteArray const& bytes); + void connectionReset(); + + void _close(Result result); +}; + +#endif /* MCASTRECEIVER_H_ */ diff --git a/src/net/mcast/McastSender.cpp b/src/net/mcast/McastSender.cpp new file mode 100644 index 0000000..3fec6a4 --- /dev/null +++ b/src/net/mcast/McastSender.cpp @@ -0,0 +1,127 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastReceiver.h +# - implement the receiver-side multicast file transfer protocol -- implementation +# ----------------------------------------------------------------------------- +*/ + +#include "McastSender.h" +#include "McastConstants.h" + +#include <QDataStream> +#include <QTimer> + +#include <pgm/pgm.h> +// OpenPGM #defines bool. This is bad in C++. +#undef bool + +#define MCASTFT_START_DEFER_TIME 2000 /* msec */ + +McastSender::McastSender(QIODevice* iodev, McastConfiguration const* config, QObject* parent) : + QObject(parent), + _config(config ? new McastConfiguration(*config) : new McastConfiguration()), + _socket(0), + _iodev(iodev), + _curoffs(0), + _hash(QCryptographicHash::Md5), + _finished(false) +{ +} + +McastSender::~McastSender() +{ + delete _config; +} + +void McastSender::start() +{ + _socket = new McastPGMSocket(this); + connect(_socket, SIGNAL(readyToSend()), this, SLOT(deferredStart())); + _socket->open(_config, McastPGMSocket::PSOCK_WRITE); +} + +void McastSender::start(McastPGMSocket* socket) +{ + _socket = socket; + Q_ASSERT(_socket->isOpen()); + deferredStart(); +} + +void McastSender::deferredStart() +{ + // Wait some time, to give the PGM library the chance to generate some + // undisturbed SPM messages: + QTimer::singleShot(MCASTFT_START_DEFER_TIME, this, SLOT(readyToSend())); + disconnect(_socket, SIGNAL(readyToSend()), this, SLOT(deferredStart())); + connect(_socket, SIGNAL(readyToSend()), this, SLOT(readyToSend())); +} + +void McastSender::readyToSend() +{ + if(_finished) + return; + + if(_iodev->atEnd()) + { + QByteArray fpdu; + QDataStream strm(&fpdu, QIODevice::WriteOnly); + strm.setByteOrder(QDataStream::BigEndian); + + strm << (quint64)MCASTFT_MAGIC << (quint64)UINT64_C(0xffffffffffffffff) << _hash.result(); + strm << qChecksum(fpdu.constData(), fpdu.size()); + + _socket->sendPacket(fpdu); + connect(_socket, SIGNAL(connectionFinished()), this, SLOT(socketFinished())); + _socket->shutdown(); + + _finished = true; + + _iodev->close(); + + emit allSent(); + } + else + { + QByteArray barr(DEFAULT_MULTICAST_APDU, '\0'); + qint64 len_read; + len_read = _iodev->read(barr.data(), barr.capacity()); + barr.resize((int)len_read); + + _hash.addData(barr); + + QByteArray pdu; + QDataStream strm(&pdu, QIODevice::WriteOnly); + strm.setByteOrder(QDataStream::BigEndian); + + strm << (quint64)MCASTFT_MAGIC << _curoffs; + strm << barr; + quint16 checksum = qChecksum(pdu.constData(), pdu.size()); + strm << checksum; + + _curoffs += len_read; + + _socket->sendPacket(pdu); + + emit progress(_curoffs); + } +} + +void McastSender::close() +{ + _socket->finish(); +} + +void McastSender::socketFinished() +{ + _socket->deleteLater(); + emit finished(); +} diff --git a/src/net/mcast/McastSender.h b/src/net/mcast/McastSender.h new file mode 100644 index 0000000..0c5e29f --- /dev/null +++ b/src/net/mcast/McastSender.h @@ -0,0 +1,73 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastReceiver.h +# - implement the sender-side multicast file transfer protocol -- interface +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTSENDER_H_ +#define MCASTSENDER_H_ + +#include <QCryptographicHash> +#include <QIODevice> +#include <QObject> + +#include "McastConfiguration.h" +#include "McastPGMSocket.h" + +class McastSender : public QObject +{ + Q_OBJECT +public: + McastSender(QIODevice* iodev = 0, McastConfiguration const* config = 0, QObject* parent = 0); + virtual ~McastSender(); + + McastConfiguration* config() + { + return _config; + } + + QIODevice* iodevice() const + { + return _iodev; + } + + void setIODevice(QIODevice* iodevice) + { + _iodev = iodevice; + } + +signals: + void finished(); + void progress(quint64 offset); + void allSent(); + +public slots: + void start(); + void start(McastPGMSocket* openSocket); + void close(); + +private slots: + void deferredStart(); + void readyToSend(); + void socketFinished(); + +private: + McastConfiguration* _config; + McastPGMSocket* _socket; + QIODevice* _iodev; + quint64 _curoffs; + QCryptographicHash _hash; + bool _finished; +}; + +#endif /* MCASTSENDER_H_ */ diff --git a/src/net/mcast/trial_programs/CMakeLists.txt b/src/net/mcast/trial_programs/CMakeLists.txt new file mode 100644 index 0000000..d0f68fa --- /dev/null +++ b/src/net/mcast/trial_programs/CMakeLists.txt @@ -0,0 +1,38 @@ +INCLUDE(${QT_USE_FILE}) + +QT4_WRAP_CPP( + mcastsend_MOC + mcastsend.h +) + +QT4_WRAP_CPP( + mcastreceive_MOC + mcastreceive.h +) + +SET(argparser_SRC + McastConfigArgParser.h + McastConfigArgParser.cpp +) + +ADD_EXECUTABLE(mcastsend + mcastsend.cpp + mcastsend.h + ${argparser_SRC} + ${mcastsend_MOC} +) + +ADD_EXECUTABLE(mcastreceive + mcastreceive.cpp + mcastreceive.h + ${argparser_SRC} + ${mcastreceive_MOC} +) + +TARGET_LINK_LIBRARIES(mcastsend + pvsmcast +) + +TARGET_LINK_LIBRARIES(mcastreceive + pvsmcast +)
\ No newline at end of file diff --git a/src/net/mcast/trial_programs/McastConfigArgParser.cpp b/src/net/mcast/trial_programs/McastConfigArgParser.cpp new file mode 100644 index 0000000..881f728 --- /dev/null +++ b/src/net/mcast/trial_programs/McastConfigArgParser.cpp @@ -0,0 +1,165 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/McastConfigArgParser.cpp +# - Parse common Multicast Configuration CLI arguments +# ----------------------------------------------------------------------------- +*/ + +#include <iostream> + +#include <QCoreApplication> + +#include "McastConfigArgParser.h" + +using namespace std; + +bool parseMcastConfigArg(QStringList::iterator& i, QStringList::iterator const& end, McastConfiguration* config) +{ + QString arg = *i; + + if (arg == "-addr") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + config->multicastAddress(*i); + } + else if (arg == "-dport") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 dport = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: dport is not an integer" << endl; + return false; + } + config->multicastDPort(dport); + } + else if (arg == "-sport") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 sport = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: sport is not an integer" << endl; + return false; + } + config->multicastSPort(sport); + } + else if (arg == "-mtu") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 mtu = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: MTU is not an integer" << endl; + return false; + } + config->multicastMTU(mtu); + } + else if (arg == "-rate") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint32 rate = i->toInt(&ok); + if (!ok) + { + cerr << "Error: Rate is not an integer" << endl; + return false; + } + config->multicastRate(rate); + } + else if (arg == "-winsize") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 winsize = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: Winsize is not an integer" << endl; + return false; + } + config->multicastWinSize(winsize); + } + else if (arg == "-udp") + { + config->multicastUseUDP(true); + } + else if (arg == "-no-udp") + { + config->multicastUseUDP(false); + } + else if (arg == "-udp-port") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 udpport = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: UDP-Port is not an integer" << endl; + return false; + } + config->multicastUDPPortBase(udpport); + } + else if (arg == "-intf") + { + i++; + if (i == end) + { + cerr << "Option " << arg.toLatin1().constData() << "is missing argument" << endl; + return false; + } + config->multicastInterface(*i); + } + else + { + return false; + } + + return true; +} diff --git a/src/net/mcast/trial_programs/McastConfigArgParser.h b/src/net/mcast/trial_programs/McastConfigArgParser.h new file mode 100644 index 0000000..4fb18a7 --- /dev/null +++ b/src/net/mcast/trial_programs/McastConfigArgParser.h @@ -0,0 +1,26 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/McastConfigArgParser.h +# - Parse common Multicast Configuration CLI arguments +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTCONFIGARGPARSER_H_ +#define MCASTCONFIGARGPARSER_H_ + +#include <QStringList> + +#include "../McastConfiguration.h" + +bool parseMcastConfigArg(QStringList::iterator& i, QStringList::iterator const& end, McastConfiguration* config); + +#endif /* MCASTCONFIGARGPARSER_H_ */ diff --git a/src/net/mcast/trial_programs/mcastreceive.cpp b/src/net/mcast/trial_programs/mcastreceive.cpp new file mode 100644 index 0000000..48a0f10 --- /dev/null +++ b/src/net/mcast/trial_programs/mcastreceive.cpp @@ -0,0 +1,150 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/mcastsend.cpp +# - Receive a file via the PVS Mcast protocol +# ----------------------------------------------------------------------------- +*/ + +#include <iostream> + +#include <QCoreApplication> +#include <QFile> +#include <QStringList> +#include <QTimer> + +#include "mcastreceive.h" +#include "McastConfigArgParser.h" +#include "../McastConfiguration.h" +#include "../McastReceiver.h" + +using namespace std; + +int main(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + McastReceive me; + + QTimer::singleShot(0, &me, SLOT(run())); + + return app.exec(); +} + +void McastReceive::run() +{ + QStringList args = QCoreApplication::arguments(); + QStringList::iterator i = args.begin(); + QStringList::iterator const end = args.end(); + + QString filename(""); + + McastConfiguration config; + + ++i; + while (i != end) + { + QString arg = *i; + + cerr << "Arg: " << arg.toLatin1().constData() << endl; + + if (arg == "-file") + { + ++i; + if (i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing its argument" << endl; + QCoreApplication::exit(1); + return; + } + filename = *i; + } + else if (arg == "-help") + { + cerr << "Options:" << endl << endl + << " -file <FILE> Receive to file FILE" << endl + << " -addr <ADDR> Use ADDR as address specification" << endl + << " -dport <PORT> Send to port PORT" << endl + << " -sport <PORT> Send from port PORT" << endl + << " -mtu <BYTES> Set MTU to BYTES" << endl + << " -rate <BYTES> Send BYTES per second" << endl + << " -winsize <SECONDS> Set Window Size to SECONDS" << endl + << " -udp Use UDP encapsulation" << endl + << " -udp-port PORT Use UDP port PORT" << endl; + QCoreApplication::quit(); + return; + } + else + { + if (!parseMcastConfigArg(i, end, &config)) + { + cerr << "Unknown argument: " << arg.toLatin1().constData() << endl; + QCoreApplication::exit(1); + return; + } + } + + ++i; + } + + if (filename == "") + { + cerr << "No Filename given" << endl; + QCoreApplication::exit(1); + return; + } + + _target = new QFile(filename, this); + _target->open(QIODevice::WriteOnly); + + McastReceiver* recv = new McastReceiver(_target, &config, this); + + connect(recv, SIGNAL(finished(int)), this, SLOT(finished(int))); + + QTimer::singleShot(0, recv, SLOT(start())); +} + +void McastReceive::finished(int state) +{ + cerr << "finished: "; + + switch(state) + { + case McastReceiver::RES_OK: + cerr << "OK." << endl; + break; + case McastReceiver::RES_ABORTED: + cerr << "Aborted." << endl; + goto failed; + case McastReceiver::RES_CHECKSUM_MISMATCH: + cerr << "Checksum mismatch." << endl; + goto failed; + case McastReceiver::RES_CONNECTION_RESET: + cerr << "Connection reset." << endl; + goto failed; + case McastReceiver::RES_MD5_MISMATCH: + cerr << "MD5 mismatch." << endl; + goto failed; + case McastReceiver::RES_OFFSET_MISMATCH: + cerr << "Offset mismatch. Undetected packet loss?" << endl; + goto failed; + default: + cerr << "Unknown error code!" << endl; + goto failed; + } + + QCoreApplication::quit(); + return; +failed: + cerr << "Deleting file." << endl; + _target->remove(); + QCoreApplication::exit(1); + return; +} diff --git a/src/net/mcast/trial_programs/mcastreceive.h b/src/net/mcast/trial_programs/mcastreceive.h new file mode 100644 index 0000000..3e72d4c --- /dev/null +++ b/src/net/mcast/trial_programs/mcastreceive.h @@ -0,0 +1,44 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/mcastsend.cpp +# - Receive a file via the PVS Mcast protocol +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTRECEIVE_H_ +#define MCASTRECEIVE_H_ + +#include <QObject> + +class QFile; +class McastReceiver; + +class McastReceive : public QObject +{ + Q_OBJECT +public: + McastReceive() : + QObject(), + _receiver(0) + { + } + +public slots: + void run(); + void finished(int state); + +private: + McastReceiver* _receiver; + QFile* _target; +}; + +#endif /* MCASTRECEIVE_H_ */ diff --git a/src/net/mcast/trial_programs/mcastsend.cpp b/src/net/mcast/trial_programs/mcastsend.cpp new file mode 100644 index 0000000..f78a9ce --- /dev/null +++ b/src/net/mcast/trial_programs/mcastsend.cpp @@ -0,0 +1,122 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/mcastsend.cpp +# - Send a file via the PVS Mcast protocol +# ----------------------------------------------------------------------------- +*/ + +#include <iostream> + +#include <QCoreApplication> +#include <QFile> +#include <QStringList> +#include <QTimer> + +#include <src/net/mcast/McastSender.h> +#include "mcastsend.h" +#include "McastConfigArgParser.h" +#include "../McastConstants.h" +#include "../McastConfiguration.h" + +using namespace std; + +int +main(int argc, char**argv) +{ + QCoreApplication app(argc, argv); + McastSend me; + + QTimer::singleShot(0, &me, SLOT(run())); + + return app.exec(); +} + +void McastSend::run() +{ + QStringList args = QCoreApplication::arguments(); + QStringList::iterator i = args.begin(); + QStringList::iterator const end = args.end(); + QString filename(""); + McastConfiguration config; + + ++i; + while(i != end) + { + // parse command line arguments + + QString arg = *i; + + cerr << "Arg: " << arg.toLatin1().constData() << endl; + + if (arg == "-file") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + QCoreApplication::exit(1); + return; + } + filename = *i; + } + else if (arg == "-help") + { + cerr << "Options:" << endl << endl + << " -file <FILE> Send FILE to the listeners" << endl + << " -addr <ADDR> Use ADDR as address specification" << endl + << " -dport <PORT> Send to port PORT" << endl + << " -sport <PORT> Send from port PORT" << endl + << " -mtu <BYTES> Set MTU to BYTES" << endl + << " -rate <BYTES> Send BYTES per second" << endl + << " -winsize <SECONDS> Set Window Size to SECONDS" << endl + << " -udp Use UDP encapsulation" << endl + << " -udp-port PORT Use UDP port PORT" << endl; + QCoreApplication::quit(); + return; + } + else + { + if (!parseMcastConfigArg(i, end, &config)) + { + cerr << "Unknown command line argument: " << arg.toLatin1().constData() << endl; + QCoreApplication::exit(1); + return; + } + } + + ++i; + } + + if(filename == "") + { + cerr << "No filename given" << endl; + QCoreApplication::exit(1); + return; + } + + // now, do it. + QFile* file = new QFile(filename); + file->open(QIODevice::ReadOnly); + + McastSender* sender = new McastSender(file, &config, this); + file->setParent(sender); + + connect(sender, SIGNAL(finished()), this, SLOT(finished())); + + QTimer::singleShot(0, sender, SLOT(start())); +} + +void McastSend::finished() +{ + cerr << "finished." << endl; + QCoreApplication::quit(); +} diff --git a/src/net/mcast/trial_programs/mcastsend.h b/src/net/mcast/trial_programs/mcastsend.h new file mode 100644 index 0000000..ae15eb4 --- /dev/null +++ b/src/net/mcast/trial_programs/mcastsend.h @@ -0,0 +1,42 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/mcastsend.cpp +# - Send a file via the PVS Mcast protocol +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTSEND_H_ +#define MCASTSEND_H_ + +#include <QObject> + +#include "../McastSender.h" + +class McastSend : public QObject +{ + Q_OBJECT +public: + McastSend() : + QObject(), + _sender(0) + { + } + +public slots: + void run(); + void finished(); + +private: + McastSender* _sender; +}; + +#endif /* MCASTSEND_H_ */ diff --git a/src/net/pvsClientConnection.cpp b/src/net/pvsClientConnection.cpp index dff40d5..5354e95 100644 --- a/src/net/pvsClientConnection.cpp +++ b/src/net/pvsClientConnection.cpp @@ -134,7 +134,7 @@ bool PVSClientConnection::push_back_send(PVSMsg newMsg) char *tmp = data; if (!newMsg.getBinaryData(tmp, len)) { - printf("Message empty. Ignored.\n"); + qDebug("Message empty. Ignored."); return false; } QByteArray ba; diff --git a/src/net/pvsDiscoveredServer.cpp b/src/net/pvsDiscoveredServer.cpp index dddb5a0..efa1506 100644 --- a/src/net/pvsDiscoveredServer.cpp +++ b/src/net/pvsDiscoveredServer.cpp @@ -48,7 +48,7 @@ void PVSDiscoveredServer::ssl_Error( const QList<QSslError> & errors ) } //ConsoleLog writeNetwork(err.errorString().toUtf8().data()); //ConsoleLog writeNetwork("***** SSL ERROR, ABORTING *****"); - printf("Unhandled SSL Error in SD: %s\n", err.errorString().toUtf8().data()); + qDebug("Unhandled SSL Error in SD: %s", qPrintable(err.errorString())); return; } _socket->ignoreSslErrors(); @@ -70,30 +70,30 @@ void PVSDiscoveredServer::sock_connected() QByteArray cert = _socket->peerCertificate().digest(QCryptographicHash::Sha1); if (_socket->peerCertificate().isNull()) { - printf("**** WARNING - PEER CERTIFICATE IS NULL ****\n"); + qDebug("**** WARNING - PEER CERTIFICATE IS NULL ****"); } else { - printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::Organization).toUtf8().data()); - printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::CommonName).toUtf8().data()); - printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::LocalityName).toUtf8().data()); - printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::OrganizationalUnitName ).toUtf8().data()); - printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::CountryName ).toUtf8().data()); - printf("%s\n", _socket->peerCertificate().subjectInfo(QSslCertificate::StateOrProvinceName ).toUtf8().data()); + qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::Organization))); + qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::CommonName))); + qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::LocalityName))); + qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::OrganizationalUnitName))); + qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::CountryName))); + qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::StateOrProvinceName))); } if (cert == _fingerprint && !_validated) { _validated = true; emit validated(this); - printf("Validated certificate of %s :)\n", _socket->peerAddress().toString().toUtf8().data()); + qDebug("Validated certificate of %s :)", qPrintable(_socket->peerAddress().toString())); } else { - printf("Certificate of %s is invalid :(\n", _socket->peerAddress().toString().toUtf8().data()); + qDebug("Certificate of %s is invalid :(", qPrintable(_socket->peerAddress().toString())); QByteArray is, should; is = cert.toBase64(); should = _fingerprint.toBase64(); - printf("Is %s and should be %s\n", is.data(), should.data()); + qDebug("Is %s and should be %s", is.data(), should.data()); } _socket->disconnectFromHost(); } diff --git a/src/net/pvsIncomingMulticastTransfer.cpp b/src/net/pvsIncomingMulticastTransfer.cpp new file mode 100644 index 0000000..10b5307 --- /dev/null +++ b/src/net/pvsIncomingMulticastTransfer.cpp @@ -0,0 +1,133 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/pcsIncomingMulticastTransfer.h +# - wrap McastReceiver functionality in PVS daemon +# ----------------------------------------------------------------------------- +*/ + +#include <QDir> +#include <QTemporaryFile> +#include <QTimer> + +#include "pvsIncomingMulticastTransfer.h" +#include <src/net/mcast/McastReceiver.h> + +PVSIncomingMulticastTransfer::PVSIncomingMulticastTransfer(QString const& sender, qulonglong transferID, qulonglong size, QString const& filename, + ushort port, McastConfiguration const* configTemplate, QObject* parent) : + QObject(parent), + _sender(sender), + _transferID(transferID), + _bytes(0), + _size(size), + _port(port), + _file(new QFile(filename, this)), + _receiver(0), + _config(configTemplate ? + new McastConfiguration(*configTemplate) : + new McastConfiguration()), + _progressTimer(new QTimer(this)) +{ + _file->open(QIODevice::WriteOnly); + + _config->multicastUDPPortBase(port); + // _config->multicastDPort(port+1); + // _config->multicastSPort(port+2); + + connect(_progressTimer, SIGNAL(timeout()), SLOT(updateProgress())); + connect(this, SIGNAL(failed(qulonglong, QString const&)), SLOT(removeFile())); +} + +PVSIncomingMulticastTransfer::~PVSIncomingMulticastTransfer() +{ + // TODO Auto-generated destructor stub +} + +bool PVSIncomingMulticastTransfer::start() +{ + _file->open(QIODevice::WriteOnly); + _receiver = new McastReceiver(_file, new McastConfiguration(*_config), this); + connect(_receiver, SIGNAL(finished(int)), SLOT(receiverFinished(int))); + connect(_receiver, SIGNAL(progress(quint64)), SLOT(receiverProgressed(quint64))); + + if (!_receiver->start()) + { + emit retry(_sender, _transferID); + return false; + } + else + { + _progressTimer->start(333); + return true; + } +} + +void PVSIncomingMulticastTransfer::abort() +{ + delete _receiver; + _receiver = 0; + + delete _progressTimer; + _progressTimer = 0; + + if(_file) + delete _file; +} + +void PVSIncomingMulticastTransfer::updatePort(ushort port) +{ + _config->multicastUDPPortBase(port); + _config->multicastSPort(port); + _config->multicastDPort(port); +} + +void PVSIncomingMulticastTransfer::receiverProgressed(quint64 bytes) +{ + _bytes = bytes; +} + +void PVSIncomingMulticastTransfer::receiverFinished(int how) +{ + switch(how) + { + case McastReceiver::RES_OK: + emit finished(_transferID); + break; + case McastReceiver::RES_ABORTED: + emit failed(_transferID, tr("Aborted")); + break; + case McastReceiver::RES_MD5_MISMATCH: + case McastReceiver::RES_CHECKSUM_MISMATCH: + emit failed(_transferID, tr("Unrecoverable data corruption")); + break; + case McastReceiver::RES_CONNECTION_RESET: + emit failed(_transferID, tr("Connection was reset")); + break; + case McastReceiver::RES_OFFSET_MISMATCH: + emit failed(_transferID, tr("Unrecoverable data loss. Try a lower transfer rate")); + break; + } +} + +void PVSIncomingMulticastTransfer::removeFile() +{ + if(_file) + _file->remove(); +} + +void PVSIncomingMulticastTransfer::updateProgress() +{ + if (!_started) + { + emit started(_transferID); + } + emit progress(_transferID, _bytes, _size); +} diff --git a/src/net/pvsIncomingMulticastTransfer.h b/src/net/pvsIncomingMulticastTransfer.h new file mode 100644 index 0000000..f96e176 --- /dev/null +++ b/src/net/pvsIncomingMulticastTransfer.h @@ -0,0 +1,71 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/pcsIncomingMulticastTransfer.h +# - wrap McastReceiver functionality in PVS daemon +# ----------------------------------------------------------------------------- +*/ + +#ifndef PVSINCOMINGMULTICASTTRANSFER_H_ +#define PVSINCOMINGMULTICASTTRANSFER_H_ + +#include <QObject> +#include <QString> + +#include <src/net/pvsMsg.h> + +class McastConfiguration; +class McastReceiver; +class QFile; +class QTimer; + +class PVSIncomingMulticastTransfer : public QObject +{ + Q_OBJECT +public: + PVSIncomingMulticastTransfer(QString const& sender, qulonglong transferID, qulonglong size, QString const& filename, ushort port, + McastConfiguration const* configTemplate, QObject* parent = 0); + virtual ~PVSIncomingMulticastTransfer(); + + void setFinalFile(QString const& filename); + +signals: + void retry(QString const& sender, qulonglong transferID); + void started(qulonglong transferID); + void progress(qulonglong transferID, qulonglong bytes, qulonglong of); + void finished(qulonglong transferID); + void failed(qulonglong transferID, QString const& reason); + +public slots: + void updatePort(ushort port); + bool start(); + void abort(); + +private slots: + void receiverProgressed(quint64 bytes); + void receiverFinished(int reason); + void updateProgress(); + void removeFile(); + +private: + QString _sender; + qulonglong _transferID; + qulonglong _bytes; + qulonglong _size; + ushort _port; + QFile* _file; + McastReceiver* _receiver; + McastConfiguration* _config; + bool _started; + QTimer* _progressTimer; +}; + +#endif /* PVSINCOMINGMULTICASTTRANSFER_H_ */ diff --git a/src/net/pvsListenServer.cpp b/src/net/pvsListenServer.cpp index f21303e..90c2dfb 100644 --- a/src/net/pvsListenServer.cpp +++ b/src/net/pvsListenServer.cpp @@ -21,9 +21,13 @@ #include "pvsClientConnection.h" #include "src/util/consoleLogger.h" #include <QtNetwork/QSslSocket> +#include <QBuffer> +#include <QByteArray> +#include <QSettings> #include "SslServer.h" #include <cassert> //#define verbose +#include "mcast/McastConfiguration.h" // Create listener PVSListenServer::PVSListenServer(int port, int clients) @@ -36,6 +40,7 @@ PVSListenServer::PVSListenServer(int port, int clients) else _clientsMax = clients; _port = port; + _mcastConfig = 0; init(); } @@ -137,7 +142,7 @@ void PVSListenServer::timerEvent(QTimerEvent *event) } if (client->lastData() < refval) { // ping timeout - printf("Ping timeout for client %s\n", client->getNameUser().toLocal8Bit().data()); + qDebug("Ping timeout for client %s", qPrintable(client->getNameUser())); if (disconnectClient(client)) break; // list was modified, iterator not valid anymore } @@ -178,6 +183,7 @@ void PVSListenServer::onClientConnected(PVSClientConnection* connected) { connected->setServerID(_id); connected->setID(generateID()); + connected->push_back_send(mcastConfigMessage()); } void PVSListenServer::onClientDisconnected(PVSClientConnection* disconnected) @@ -227,6 +233,11 @@ PVSClientConnection* PVSListenServer::getConnectionFromID(int id) // Initialize listening socket bool PVSListenServer::init() { + if (_mcastConfig) + delete _mcastConfig; + _mcastConfig = new McastConfiguration(this); + loadMcastConfig(); + if (_listenSocket != NULL) shutdown(); @@ -283,9 +294,8 @@ void PVSListenServer::server_connectionRequest() void PVSListenServer::handleClientMsg(unsigned int clientID, PVSMsg msg) { - printf("Got Message for client %ud: [%c][%s][%s]\n", clientID, - (char) msg.getType(), msg.getIdent().toUtf8().data(), - msg.getMessage().toUtf8().data()); + qDebug("Got Message for client %ud: [%c][%s][%s]", clientID, + (char) msg.getType(), qPrintable(msg.getIdent()), qPrintable(msg.getMessage())); msg.setSndID(clientID); if (msg.getType() == PVSCOMMAND) _commandDispatcher.fire(msg.getIdent(), msg); @@ -306,3 +316,52 @@ bool PVSListenServer::isListening() { return _listenSocket != NULL && _listenSocket->isListening(); } + +void PVSListenServer::loadMcastConfig() +{ + QSettings settings; + _mcastConfig->loadFrom(&settings, "multicast-filetransfer"); +} + +void PVSListenServer::saveMcastConfig() +{ + QSettings settings; + _mcastConfig->writeTo(&settings, "multicast-filetransfer"); + settings.sync(); +} + +PVSMsg PVSListenServer::mcastConfigMessage() +{ + // If anything is changed here, do not forget to + // 1. assign a new version number + // 2. adapt PVS::onCommand(PVSMsg) in pvs.cpp + QByteArray ba; + QDataStream strm(&ba, QIODevice::WriteOnly); + strm << (quint16)1 // version + << _mcastConfig->multicastAddress() + << _mcastConfig->multicastUDPPortBase() + << _mcastConfig->multicastDPort() + << _mcastConfig->multicastSPort() + << _mcastConfig->multicastMTU() + << _mcastConfig->multicastWinSize() + << _mcastConfig->multicastRate() + << _mcastConfig->multicastUseUDP(); + + QByteArray b64 = ba.toBase64(); + QString message = QString::fromAscii(b64.constData(), b64.length()); + PVSMsg msg(PVSCOMMAND, "MCASTFTCONFIG", message); + return msg; +} + +void PVSListenServer::multicastReconfigure(McastConfiguration const* source) +{ + _mcastConfig->multicastAddress(source->multicastAddress()); + *_mcastConfig = *source; + saveMcastConfig(); + sendToAll(mcastConfigMessage()); +} + +McastConfiguration const* PVSListenServer::getMulticastConfiguration() +{ + return _mcastConfig; +} diff --git a/src/net/pvsListenServer.h b/src/net/pvsListenServer.h index ab021c7..ca9977c 100644 --- a/src/net/pvsListenServer.h +++ b/src/net/pvsListenServer.h @@ -10,6 +10,7 @@ class SslServer; class PVSClientConnection; class PVSMsg; +class McastConfiguration; class PVSListenServer : public QObject { @@ -40,6 +41,12 @@ private: bool init(); unsigned int generateID(); + McastConfiguration* _mcastConfig; + + void loadMcastConfig(); + void saveMcastConfig(); + PVSMsg mcastConfigMessage(); + protected: void timerEvent(QTimerEvent *event); @@ -60,6 +67,9 @@ public: bool disconnectClient(PVSClientConnection* delinquent); void onConnectionRemoved(PVSClientConnection* delinquent); + void multicastReconfigure(McastConfiguration const* source); + McastConfiguration const* getMulticastConfiguration(); + std::list<PVSClientConnection*>* getClientListPtr() { return &_clients; @@ -73,7 +83,7 @@ public: template<class T> void addLoginHandler(QString ident, T* who, void (T :: *func)(PVSMsg)) { - printf("Listener got added to LoginHandler\n"); + qDebug("Listener got added to LoginHandler"); _loginDispatcher.addListener(ident, who, func); }; template<class T> void removeLoginHandler(QString ident, T* who, void (T :: *func)(PVSMsg)) diff --git a/src/net/pvsLocalhostCommunicator.cpp b/src/net/pvsLocalhostCommunicator.cpp index 199b39c..20783bb 100644 --- a/src/net/pvsLocalhostCommunicator.cpp +++ b/src/net/pvsLocalhostCommunicator.cpp @@ -83,7 +83,7 @@ void PVSLocalhostCommunicator::sendCommand(QString ident, QString cmd) int len; sender.getBinaryData(data, len); QByteArray qba(data, len); - printf("Sending %d bytes to daemon...\n", qba.length()); + qDebug("Sending %d bytes to daemon...", qba.length()); qint64 result = _sock->writeDatagram(qba, localhost, localport); _sock->waitForBytesWritten(100); @@ -92,11 +92,11 @@ void PVSLocalhostCommunicator::sendCommand(QString ident, QString cmd) { if (result == -1) { - printf("Error sending PVSMsg to daemon: %s\n", _sock->errorString().toUtf8().data()); + qDebug("Error sending PVSMsg to daemon: %s", qPrintable(_sock->errorString())); } else { - printf("Sent PVSMsg was incomplete.\n"); + qDebug("Sent PVSMsg was incomplete."); } stop(); } diff --git a/src/net/pvsNetworkInterfaceListModel.cpp b/src/net/pvsNetworkInterfaceListModel.cpp new file mode 100644 index 0000000..67d0c0a --- /dev/null +++ b/src/net/pvsNetworkInterfaceListModel.cpp @@ -0,0 +1,81 @@ +/* + * pvsNetworkInterfaceListModel.cpp + * + * Created on: 04.08.2010 + * Author: brs + */ + +#include "pvsNetworkInterfaceListModel.h" +#include <QStringList> + +PVSNetworkInterfaceListModel::PVSNetworkInterfaceListModel(QObject* parent) : + QAbstractListModel(parent) +{ + reloadInterfaceList(); +} + +PVSNetworkInterfaceListModel::~PVSNetworkInterfaceListModel() +{ +} + +void PVSNetworkInterfaceListModel::reloadInterfaceList() +{ + _interfaces = QNetworkInterface::allInterfaces(); + reset(); +} + +QVariant PVSNetworkInterfaceListModel::data(QModelIndex const& index, int role) const +{ + int i = index.row(); + if(0 > i || i >= _interfaces.size()) + { + return QVariant(); + } + QNetworkInterface intf = _interfaces.at(i); + + switch(role) + { + case Qt::DisplayRole: + { + QString name = intf.humanReadableName(); + QList<QNetworkAddressEntry> addresses = intf.addressEntries(); + QStringList l; + + foreach(QNetworkAddressEntry addr, addresses) + { + l.append(addr.ip().toString()); + } + + return QString("%1 (%2)").arg(name).arg(l.join(", ")); + } + case Qt::EditRole: + case Qt::UserRole: + return intf.name(); + default: + return QVariant(); + } +} + +QVariant PVSNetworkInterfaceListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(section == 0 && orientation == Qt::Vertical && role == Qt::DisplayRole) + { + return tr("Interface"); + } + else + { + return QVariant(); + } +} + +int PVSNetworkInterfaceListModel::rowCount(QModelIndex const& parent) const +{ + if(parent.isValid()) + { + return 0; + } + else + { + return _interfaces.size(); + } +} diff --git a/src/net/pvsNetworkInterfaceListModel.h b/src/net/pvsNetworkInterfaceListModel.h new file mode 100644 index 0000000..3a9b95d --- /dev/null +++ b/src/net/pvsNetworkInterfaceListModel.h @@ -0,0 +1,35 @@ +/* + * pvsNetworkInterfaceListModel.h + * + * Created on: 04.08.2010 + * Author: brs + */ + +#ifndef PVSNETWORKINTERFACELISTMODEL_H_ +#define PVSNETWORKINTERFACELISTMODEL_H_ + +#include <QAbstractListModel> +#include <QList> +#include <QNetworkInterface> +#include <QVariant> + +class PVSNetworkInterfaceListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + PVSNetworkInterfaceListModel(QObject* parent = 0); + virtual ~PVSNetworkInterfaceListModel(); + + QVariant data(QModelIndex const& index, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + int rowCount(QModelIndex const&) const; + +private: + QList<QNetworkInterface> _interfaces; + +public slots: + void reloadInterfaceList(); +}; + +#endif /* PVSNETWORKINTERFACELISTMODEL_H_ */ diff --git a/src/net/pvsOutgoingMulticastTransfer.cpp b/src/net/pvsOutgoingMulticastTransfer.cpp new file mode 100644 index 0000000..4df4986 --- /dev/null +++ b/src/net/pvsOutgoingMulticastTransfer.cpp @@ -0,0 +1,209 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/pvsOutgoingMulticastTransfer.cpp +# - wrap McastSender functionality in PVS daemon +# ----------------------------------------------------------------------------- +*/ + +#include "pvsOutgoingMulticastTransfer.h" + +#include <QDataStream> +#include <QFile> +#include <QFileInfo> +#include <QHostInfo> +#include <QSettings> +#include <QTimer> + +#include <src/net/pvsMsg.h> +#include <src/net/mcast/McastConfiguration.h> +#include <src/net/mcast/McastPGMSocket.h> +#include <src/net/mcast/McastSender.h> +#include <src/util/consoleLogger.h> + +PVSOutgoingMulticastTransfer::PVSOutgoingMulticastTransfer(QString senderName, quint64 id, QString filename, QObject* parent) : + QObject(parent), + _file(0), + _progress(0), + _config(0), + _socket(0), + _progressTimer(0), + _prepareTimer(0), + _senderName(senderName), + _id(id), + _error(false) +{ + QFileInfo finfo(filename); + if(!finfo.exists()) + { + error("File does not exist"); + } + + if(!finfo.isReadable()) + { + error("File is not readable"); + } + + _file = new QFile(filename, this); + _length = _file->size(); +} + +PVSOutgoingMulticastTransfer::~PVSOutgoingMulticastTransfer() +{ + if(_file) + delete _file; + if(_config) + delete _config; +} + +void PVSOutgoingMulticastTransfer::prepare() +{ + if (_socket && !_socketInacceptable) + { + _prepareTimer->stop(); + delete _prepareTimer; + _prepareTimer = 0; + + QTimer::singleShot(0, this, SLOT(doStart())); + return; + } + else if (_socket) + { + delete _socket; + _socket = 0; + } + + QSettings settings; + quint16 portbase = settings.value("multicast/port-base", "6966").value<quint16>(); + quint16 portlimit = settings.value("multicast/port-limit", "7966").value<quint16>(); + + int tries_remaining = 5; + while(tries_remaining > 0) + { + quint16 port = portbase + (qrand() % (portlimit - portbase + 1)); + + if (!_config) + { + _config = new McastConfiguration(); + } + _config->loadFrom(&settings, "multicast"); + _config->multicastUDPPortBase(port); + + _socket = new McastPGMSocket(this); + if(_socket->open(_config, McastPGMSocket::PSOCK_WRITE)) + { + break; + } + else + { + delete _socket; + _socket = 0; + } + } + + if (!_socket) + { + emit failed(_id, "Could not open socket"); + delete _prepareTimer; + _prepareTimer = 0; + return; + } + else + { + _socketInacceptable = false; + // announce the transfer: + QFileInfo info(*_file); + QString message = QString("%1:%2:%3:%4:%5").arg(_senderName).arg(_id).arg(info.fileName()).arg(info.size()).arg(_config->multicastUDPPortBase()); + PVSMsg msg(PVSCOMMAND, "MCASTFTANNOUNCE", message); + emit announce(msg); + _prepareTimer->start(5000); + } +} + +void PVSOutgoingMulticastTransfer::doStart() +{ + ConsoleLog writeLine(QString("Starting multicast transfer %1").arg(_id)); + + _file->open(QIODevice::ReadOnly); + + _sender = new McastSender(_file, _config, this); + connect(_sender, SIGNAL(finished()), SLOT(senderFinished())); + connect(_sender, SIGNAL(progress(quint64)), SLOT(senderProgress(quint64))); + // connect(_sender, SIGNAL(allSent()), SIGNAL(allSent())); + _socket->setParent(_sender); + _sender->start(_socket); + + emit started(_id); + + _progressTimer = new QTimer(this); + connect(_progressTimer, SIGNAL(timeout()), SLOT(reportTimeout())); + _progressTimer->setInterval(333); + _progressTimer->start(); +} + +void PVSOutgoingMulticastTransfer::senderProgress(quint64 bytes) + +{ + _progress = bytes; +} + +void PVSOutgoingMulticastTransfer::senderFinished() +{ + if(_progressTimer) + { + _progressTimer->stop(); + delete _progressTimer; + _progressTimer = 0; + } + emit finished(_id); + _sender->close(); + delete _sender; +} + +void PVSOutgoingMulticastTransfer::reportTimeout() +{ + emit progress(_id, _progress, _length); +} + +void PVSOutgoingMulticastTransfer::retry() +{ + bool first = !_socketInacceptable; + _socketInacceptable = true; + + if(first) + { + _prepareTimer->setInterval(1000); + } +} + +void PVSOutgoingMulticastTransfer::start() +{ + if (!_prepareTimer) + { + _prepareTimer = new QTimer(this); + _prepareTimer->setSingleShot(true); + connect(_prepareTimer, SIGNAL(timeout()), SLOT(prepare())); + } + QTimer::singleShot(0, this, SLOT(prepare())); +} + +void PVSOutgoingMulticastTransfer::abort() +{ + if (_sender) + _sender->close(); +} + +void PVSOutgoingMulticastTransfer::error(QString const& reason) +{ + qCritical() << "Could not create an outgoing mcast transfer: " << reason; + _error = true; + _reason = reason; +} diff --git a/src/net/pvsOutgoingMulticastTransfer.h b/src/net/pvsOutgoingMulticastTransfer.h new file mode 100644 index 0000000..5fd6a3d --- /dev/null +++ b/src/net/pvsOutgoingMulticastTransfer.h @@ -0,0 +1,92 @@ +/* +# Copyright (c) 2009 - 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/ +# ----------------------------------------------------------------------------- +# src/net/pvsOutgoingMulticastTransfer.h +# - wrap McastSender functionality in PVS daemon +# ----------------------------------------------------------------------------- +*/ + +#ifndef PVSOUTGOINGMULTICASTTRANSFER_H_ +#define PVSOUTGOINGMULTICASTTRANSFER_H_ + +#include <QtGlobal> +#include <QObject> +#include <QString> + +#include <src/net/pvsMsg.h> + +class QFile; +class QTimer; +class McastConfiguration; +class McastPGMSocket; +class McastSender; + +class PVSOutgoingMulticastTransfer : public QObject +{ + Q_OBJECT +public: + PVSOutgoingMulticastTransfer(QString senderName, quint64 id, QString filename, QObject* parent = 0); + virtual ~PVSOutgoingMulticastTransfer(); + + quint64 id() const + { + return _id; + } + + bool isError() const + { + return _error; + } + + QString reason() const + { + return _reason; + } + +signals: + void started(qulonglong id); + void progress(qulonglong id, qulonglong bytes, qulonglong of); + void allSent(qulonglong id); + void finished(qulonglong id); + void failed(qulonglong id, QString const reason); + void announce(PVSMsg announcement); + +private slots: + void senderProgress(quint64 bytes); + void senderFinished(); + void reportTimeout(); + void doStart(); + void prepare(); + +public slots: + void start(); + void abort(); + void retry(); + +private: + QFile* _file; + quint64 _length; + quint64 _progress; + McastConfiguration* _config; + McastPGMSocket* _socket; + McastSender* _sender; + QTimer* _progressTimer; + QTimer* _prepareTimer; + QString _senderName; + quint64 _id; + bool _error; + QString _reason; + bool _socketInacceptable; + + void error(QString const& reason); +}; + +#endif /* PVSOUTGOINGMULTICASTTRANSFER_H_ */ diff --git a/src/net/pvsServerConnection.cpp b/src/net/pvsServerConnection.cpp index 04a1ef6..d187ce3 100644 --- a/src/net/pvsServerConnection.cpp +++ b/src/net/pvsServerConnection.cpp @@ -70,7 +70,7 @@ 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()); + qDebug("Connect SSL: %s", qPrintable(err.errorString())); 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()); diff --git a/src/net/pvsServerConnection.h b/src/net/pvsServerConnection.h index 0669d88..c6ef015 100644 --- a/src/net/pvsServerConnection.h +++ b/src/net/pvsServerConnection.h @@ -11,9 +11,9 @@ #define _PVSSERVERCONNECTION_H_ #include "src/util/dispatcher.h" +#include "src/net/pvsMsg.h" #include <QtNetwork/QSslSocket> -class PVSMsg; class PVS; class PVSDiscoveredServer; @@ -30,8 +30,6 @@ public: return _socket != NULL && _socket->state() == QAbstractSocket::ConnectedState; } - void sendMessage(PVSMsg newMessage); - void ping(); QString getServerName(); @@ -63,6 +61,9 @@ public: _commandDispatcher.removeListener(ident, who, func); }; +public Q_SLOTS: + void sendMessage(PVSMsg newMessage); + protected: void timerEvent(QTimerEvent *event); diff --git a/src/net/pvsServiceBroadcast.cpp b/src/net/pvsServiceBroadcast.cpp index cf15b5b..a861456 100644 --- a/src/net/pvsServiceBroadcast.cpp +++ b/src/net/pvsServiceBroadcast.cpp @@ -20,12 +20,22 @@ #include <cassert>
#include "src/util/serviceDiscoveryUtil.h"
+#include <QNetworkInterface>
+#include <QNetworkAddressEntry>
+
PVSServiceBroadcast::PVSServiceBroadcast()
{
_announce = NULL;
_timer = 0;
_broadcaster.bind(SD_PORT_CONSOLE);
- _everyone = QHostAddress(QHostAddress::Broadcast);
+
+ foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces())
+ foreach (QNetworkAddressEntry entry, interface.addressEntries())
+ if (!entry.broadcast().isNull() && entry.broadcast().toString() != "127.255.255.255")
+ _everyone.append(entry.broadcast());
+
+ if (_everyone.isEmpty())
+ qDebug("ERROR: No broadcast address found");
}
PVSServiceBroadcast::~PVSServiceBroadcast()
@@ -47,5 +57,9 @@ void PVSServiceBroadcast::setFingerprint(QByteArray sha1) void PVSServiceBroadcast::timerEvent(QTimerEvent *event)
{
if (_announce == NULL) return;
- _broadcaster.writeDatagram(*_announce, _everyone, SD_PORT_CLIENT);
+ foreach (QHostAddress bcast, _everyone)
+ {
+ qDebug("DEBUG: Broadcasting to %s:%i", qPrintable(bcast.toString()),SD_PORT_CLIENT);
+ _broadcaster.writeDatagram(*_announce, bcast, SD_PORT_CLIENT);
+ }
}
diff --git a/src/net/pvsServiceBroadcast.h b/src/net/pvsServiceBroadcast.h index cf3f63d..a23370f 100644 --- a/src/net/pvsServiceBroadcast.h +++ b/src/net/pvsServiceBroadcast.h @@ -39,7 +39,7 @@ protected: private:
QByteArray *_announce;
QUdpSocket _broadcaster;
- QHostAddress _everyone;
+ QList<QHostAddress> _everyone;
int _timer;
};
diff --git a/src/net/pvsServiceDiscovery.cpp b/src/net/pvsServiceDiscovery.cpp index 0a99802..dd6b500 100644 --- a/src/net/pvsServiceDiscovery.cpp +++ b/src/net/pvsServiceDiscovery.cpp @@ -30,7 +30,7 @@ PVSServiceDiscovery::PVSServiceDiscovery(PVS* client) bool ret = _sock.bind(SD_PORT_CLIENT); if (!ret) { - printf("Could not open SERVICE DISCOVERY port\n"); + qDebug("Could not open SERVICE DISCOVERY port"); exit(1); } connect(&_sock, SIGNAL(readyRead()), this, SLOT(sock_dataArrival())); diff --git a/src/pvs.cpp b/src/pvs.cpp index 911ed0d..eda63f5 100644..100755 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -10,6 +10,10 @@ # General information about OpenSLX can be found at http://openslx.org/ */ +#include <QCryptographicHash> +#include <QDataStream> +#include <QDateTime> + #include "pvs.h" #include "src/util/dispatcher.h" #include "src/net/pvsMsg.h" @@ -18,6 +22,9 @@ #include "src/input/inputEvent.h" #include "src/input/inputHandlerChain.h" #include "src/input/x11InputUtils.h" +#include "src/net/mcast/McastConfiguration.h" +#include "src/net/pvsOutgoingMulticastTransfer.h" +#include "src/net/pvsIncomingMulticastTransfer.h" // D-Bus #include "pvsadaptor.h" @@ -39,12 +46,17 @@ PVS::PVS() : _vncRequested = false; readPolicyFiles(); loadCommands(); - _blankScreen = NULL; + /*#ifndef __WIN32__*/ + _blankScreen = NULL; + /*#endif*/ _vncPort = -1; + _masterMcastConfig = new McastConfiguration(this); + _masterMcastConfig->loadFrom(&_settings, "multicast"); + // add a notify to the allow file, so we get informed when the file is changed - QString watchPath("/home/"); - watchPath.append(getUserName().append(QString("/.pvs/.allow"))); + QString watchPath(getPolicyDir()); + watchPath.append(QString(".allow")); _notify = new QFileSystemWatcher(this); _notify->addPath(QString(watchPath.toUtf8().data())); @@ -54,8 +66,10 @@ PVS::PVS() : // connect to D-Bus new PvsAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/", this); - dbus.registerService("org.openslx.pvs"); + if (!dbus.registerObject("/", this)) + qDebug("[ERROR] DBus: Could not register object"); + if (!dbus.registerService("org.openslx.pvs")) + qDebug("[ERROR] DBus: Could not register service"); _sdClient = new PVSServiceDiscovery(this); @@ -67,6 +81,7 @@ PVS::PVS() : _timerLockTest = 0; _timerLockDelay = 0; + #ifndef __WIN32__ //add signalhandling for sigterm signals struct sigaction act; act.sa_handler = &PVS::signalHandler; @@ -80,6 +95,7 @@ PVS::PVS() : sigaction(SIGQUIT, &act, 0); initializeInputEventHandling(); + #endif /*__WIN32__*/ } PVS::~PVS() @@ -186,6 +202,74 @@ void PVS::onCommand(PVSMsg cmdMessage) eventFromString(message, evt); handleInputEvent(evt); } + if (ident.compare("MCASTFTRETRY") == 0) + { + QStringList fields = message.split(':'); + if (fields[0].compare(getUserName()) == 0) + { + quint64 id = fields[1].toULongLong(); + PVSOutgoingMulticastTransfer* transfer = _outgoingTransfers.value(id, 0); + if (transfer) + transfer->retry(); + } + } + if (ident.compare("MCASTFTANNOUNCE") == 0) + { + QStringList fields = message.split(':'); + bool ok; + QString sender; + qulonglong transferID; + QString basename; + qulonglong size; + ushort port; + + if (!fields.size() == 5) + { + goto malformedAnnounce; + } + sender = fields[0]; + transferID = fields[1].toULongLong(&ok); + if (!ok) + { + goto malformedAnnounce; + } + basename = fields[2]; + size = fields[3].toULongLong(&ok); + if (!ok) + { + goto malformedAnnounce; + } + port = fields[4].toUShort(&ok); + if (!ok) + { + goto malformedAnnounce; + } + + onIncomingMulticastTransfer(sender, transferID, basename, size, port); + return; + + malformedAnnounce: + qDebug() << "Ignoring malformed MCASTFTANNOUNCE command: " << message; + return; + } + if (ident.compare("MCASTFTCONFIG") == 0) + { + loadMcastConfig(message); + return; + } + if (ident.compare("SHOWPROCESSES") == 0) + { + // do stuff to show processes + // to test if SHOWPROCESSES command is submitted correct uncomment following lines + // a messagebox will appear on the client + // emit showMessage("Show Processes", "", true); + return; + } + if (ident.compare("KILLPROCESS") == 0) + { + // do stuff to kill a process + return; + } #ifdef never // prototype @@ -327,24 +411,9 @@ bool PVS::allowExists() */ bool PVS::getVNCAllow() { - if (allowExists()) - { - if (getAllowed()) - { - _vncAllowed = true; - } - else - { - _vncAllowed = false; - } - } - else - { - ConsoleLog writeError("No .allow file found."); - _vncAllowed = false; - //make sure the vncsever is off - ConsoleLog writeError("Shutting down vnc-server because we have no .allow file."); - } + + QString value = getConfigValue("Permissions/vnc_lecturer"); + _vncAllowed = (value == "rw" || value == "ro"); if (_vncAllowed && _vncRequested) { @@ -459,12 +528,13 @@ void PVS::setScriptPath(QString path) bool PVS::gotVNCScript() { - if (fileExists(_vncScriptPath)) + if (!_vncScriptPath.isEmpty() && fileExists(_vncScriptPath)) return true; - if (policyFileExists(_vncScriptName)) + + if (!_vncScriptName.isEmpty() && policyFileExists(_vncScriptName)) return true; - return false; + return false; } /** * setup password and port @@ -510,14 +580,19 @@ int PVS::startVNCScript(int port, QString pass, QString rwpass) commandLine.append(rwpass); if (!system(NULL)) ConsoleLog writeError("No Command processor available"); - int result = system(commandLine.toUtf8().data()); + #ifndef __WIN32__ +//TODO Win32 result = WEXITSTATUS(result); if (result != 0) ConsoleLog writeError(QString("VNC-Server is not running, code: ") + int2String(result)); else ConsoleLog writeLine("VNC-Server should be running"); return result; + #else + /*Code fuer VNC-Aufruf unter Windows einfuegen*/ + return 0; + #endif /*__WIN32__*/ } else { @@ -533,6 +608,7 @@ int PVS::stopVNCScript() { if (gotVNCScript()) { + #ifndef __WIN32__ ConsoleLog writeLine("Stopping VNC-Script"); QString commandLine(_vncScriptPath); commandLine.append(" "); @@ -544,6 +620,10 @@ int PVS::stopVNCScript() ConsoleLog writeLine("VNC-Server should be stopped"); int result = system(commandLine.toUtf8().data()); return WEXITSTATUS(result); + #else + /*Code fuer VNC-Server stoppen unter Windows einfuegen*/ + return 0; + #endif /*__WIN32__*/ } else { @@ -551,9 +631,10 @@ int PVS::stopVNCScript() } } -void PVS::start() +bool PVS::start() { _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PROJECTING", "YES")); + return true; } void PVS::onConnected(QString name) @@ -620,6 +701,7 @@ QString PVS::getIpByNick(QString nick) void PVS::signalHandler(int signal) { ConsoleLog writeLine(QString("Received Signal ").append (int2String(signal))); + #ifndef __WIN32__ switch (signal) { case SIGHUP: mainClient->quit(); @@ -634,9 +716,37 @@ void PVS::signalHandler(int signal) mainClient->quit(); break; } + #else + ConsoleLog writeLine("Abfang nicht definiert fuer Windows"); + #endif /*__WIN32__*/ } +bool PVS::createMulticastTransfer(QString const& objectPath, quint64& transferID, QString& errorReason) +{ + transferID = generateMcastTransferID(); + + PVSOutgoingMulticastTransfer* transfer = new PVSOutgoingMulticastTransfer(getUserName(), transferID, objectPath, this); + if (transfer->isError()) + { + errorReason = transfer->reason(); + delete transfer; + return false; + } + + _outgoingTransfers.insert(transferID, transfer); + connect(transfer, SIGNAL(started(qulonglong)), SIGNAL(outgoingMulticastTransferStarted(qulonglong))); + connect(transfer, SIGNAL(finished(qulonglong)), SIGNAL(outgoingMulticastTransferFinished(qulonglong))); + connect(transfer, SIGNAL(failed(qulonglong, QString const)), SIGNAL(outgoingMulticastTransferFailed(qulonglong, QString const))); + connect(transfer, SIGNAL(progress(qulonglong, qulonglong, qulonglong)), SIGNAL(outgoingMulticastTransferProgress(qulonglong, qulonglong, qulonglong))); + connect(transfer, SIGNAL(announce(PVSMsg)), _pvsServerConnection, SLOT(sendMessage(PVSMsg))); + connect(transfer, SIGNAL(finished(qulonglong)), SLOT(outgoingMulticastTransferDelete(qulonglong))); + connect(transfer, SIGNAL(failed(qulonglong, QString const)), SLOT(outgoingMulticastTransferDelete(qulonglong))); + QTimer::singleShot(0, transfer, SLOT(start())); + errorReason = ""; + return true; +} + // Input handling void PVS::handleInputEvent(InputEvent const& evt) @@ -651,3 +761,160 @@ void PVS::initializeInputEventHandling() X11InputUtils::setDisplay(X11Info::display()); _inputEventHandlers.initialize(); } + +void PVS::cancelOutgoingMulticastTransfer(quint64 transferID) +{ + PVSOutgoingMulticastTransfer* transfer = _outgoingTransfers.value(transferID, 0); + + if (transfer) + { + _outgoingTransfers.remove(transferID); + delete transfer; + } +} + +void PVS::cancelIncomingMulticastTransfer(qulonglong transferID) +{ + PVSIncomingMulticastTransfer* transfer = _incomingTransfers.value(transferID, 0); + + if(transfer) + { + _incomingTransfers.remove(transferID); + delete transfer; + } +} + +void PVS::onIncomingMulticastTransfer(QString const& sender, qulonglong transferID, + QString const& basename, qulonglong size, ushort port) +{ + if (_outgoingTransfers.contains(transferID)) + return; + + PVSIncomingMulticastTransfer* transfer; + if (transfer = _incomingTransfers.value(transferID, 0)) + { + transfer->updatePort(port); + QTimer::singleShot(0, transfer, SLOT(start())); + } + else + { + QString filename = QFileInfo(QDir::home(), QString("%1.part.%2").arg(basename).arg(transferID, 0, 16)).absoluteFilePath(); + transfer = new PVSIncomingMulticastTransfer(sender, transferID, size, filename, port, _masterMcastConfig, this); + _incomingTransfers.insert(transferID, transfer); + + connect(transfer, SIGNAL(retry(QString const&, qulonglong)), SLOT(onIncomingMulticastTransferRetry(QString const&, qulonglong))); + connect(transfer, SIGNAL(started(qulonglong)), SIGNAL(incomingMulticastTransferStarted(qulonglong))); + connect(transfer, SIGNAL(progress(qulonglong, qulonglong, qulonglong)), SIGNAL(incomingMulticastTransferProgress(qulonglong, qulonglong, qulonglong))); + connect(transfer, SIGNAL(finished(qulonglong)), SIGNAL(incomingMulticastTransferFinished(qulonglong))); + connect(transfer, SIGNAL(failed(qulonglong, QString const&)), SIGNAL(incomingMulticastTransferFailed(qulonglong, QString))); + connect(transfer, SIGNAL(finished(qulonglong)), SLOT(incomingMulticastTransferDelete(qulonglong))); + connect(transfer, SIGNAL(failed(qulonglong, QString const&)), SLOT(incomingMulticastTransferDelete(qulonglong))); + + emit incomingMulticastTransferNew(transferID, sender, filename, size); + QTimer::singleShot(0, transfer, SLOT(start())); + } +} + +void PVS::onIncomingMulticastTransferRetry(QString const& sender, qulonglong transferID) +{ + PVSMsg retryMessage(PVSCOMMAND, "MCASTFTRETRY", QString("%1:%2").arg(sender).arg(transferID)); + _pvsServerConnection->sendMessage(retryMessage); +} + +quint64 PVS::generateMcastTransferID() +{ + static quint64 nodeID = 0; + static quint16 counter = 0; + + if (!nodeID) + { + QDateTime t = QDateTime::currentDateTime(); + QCryptographicHash h(QCryptographicHash::Md5); + h.addData(getUserName().toLocal8Bit()); + h.addData(t.toString().toLocal8Bit()); + QDataStream(h.result()) >> nodeID; + } + + return (nodeID & Q_UINT64_C(0xffffffffffff0000)) | (quint64)(++counter); +} + +void PVS::outgoingMulticastTransferDelete(qulonglong transferID) +{ + PVSOutgoingMulticastTransfer* transfer = _outgoingTransfers.value(transferID, 0); + if (!transfer) + return; + + _outgoingTransfers.remove(transferID); + transfer->deleteLater(); +} + +void PVS::incomingMulticastTransferDelete(qulonglong transferID) +{ + PVSIncomingMulticastTransfer* transfer = _incomingTransfers.value(transferID, 0); + if (!transfer) + { + return; + } + + _incomingTransfers.remove(transferID); + transfer->deleteLater(); +} + +void PVS::loadMcastConfig(QString const& message) +{ + QByteArray ba = QByteArray::fromBase64(message.toAscii()); + QDataStream d(&ba, QIODevice::ReadOnly); + quint16 ver, udpp, dp, sp, mtu, wsz; + quint32 rate; + QString addr; + bool useudp; + + d >> ver; + if(ver != 1) + { + ConsoleLog writeLine(QString("Unable to decode multicast configuration message: Unknown version %1").arg(ver)); + return; + } + + d >> addr + >> udpp + >> dp + >> sp + >> mtu + >> wsz + >> rate + >> useudp; + if(d.status() != QDataStream::Ok) + { + ConsoleLog writeLine(QString("Unable to decode multicast configuration message: There was an error reading")); + return; + } + + _masterMcastConfig->multicastUDPPortBase(udpp); + _masterMcastConfig->multicastDPort(dp); + _masterMcastConfig->multicastSPort(sp); + _masterMcastConfig->multicastMTU(mtu); + _masterMcastConfig->multicastWinSize(wsz); + _masterMcastConfig->multicastRate(rate); + _masterMcastConfig->multicastAddress(addr); + _masterMcastConfig->multicastUseUDP(useudp); + + QSettings settings; + _masterMcastConfig->writeTo(&settings, "multicast"); + settings.sync(); + + ConsoleLog writeLine(QString("Reconfigured multicast filetransfer to IP %1, UDP port base %2, destination port %3, source port %4, MTU %5, Window Size %6, rate %7, %8using UDP") + .arg(addr).arg(udpp).arg(dp).arg(sp).arg(mtu).arg(wsz).arg(rate).arg(useudp ? "" : "not ")); +} + +void PVS::setConfigValue(QString key, QString value) +{ + _settings.setValue(key, value); + _settings.sync(); + getVNCAllow(); +} + +QString PVS::getConfigValue(QString key) +{ + return _settings.value(key).toString(); +} diff --git a/src/pvs.h b/src/pvs.h index f4e53c0..c18e9a3 100644..100755 --- a/src/pvs.h +++ b/src/pvs.h @@ -13,8 +13,10 @@ #define PVSCLIENT_H_ #include <QtCore> -#include <X11/Xlib.h> -#include <X11/cursorfont.h> +#ifndef __WIN32__ + #include <X11/Xlib.h> + #include <X11/cursorfont.h> +#endif #include <signal.h> #include "setup.h" @@ -26,10 +28,12 @@ #include "src/util/clientGUIUtils.h" #include "src/input/inputHandlerChain.h" - class PVSServiceDiscovery; class PVSDiscoveredServer; class InputEvent; +class McastConfiguration; +class PVSOutgoingMulticastTransfer; +class PVSIncomingMulticastTransfer; /** * PVSClient @@ -70,7 +74,7 @@ public: void guiDelHost(QString host); public Q_SLOTS: - void start(); + bool start(); void quit(); void chat_send(QString nick_to, QString nick_from, QString msg); QString chat_getNickname(); @@ -82,6 +86,14 @@ public Q_SLOTS: QStringList getAvailableHosts(); QString getIpByNick(QString nick); + // Multicast File Transfer + bool createMulticastTransfer(QString const& objectPath, quint64& transferID, QString& errorReason); + void cancelOutgoingMulticastTransfer(quint64 transferID); + void cancelIncomingMulticastTransfer(qulonglong transferID); + + void setConfigValue(QString key, QString value); + QString getConfigValue(QString key); + Q_SIGNALS: void project(QString host, int port, QString passwd, bool fullscreen, bool smoothTransformation, int quality); @@ -95,6 +107,17 @@ Q_SIGNALS: void addHost(QString host); void delHost(QString host); + // Multicast File Transfer + void outgoingMulticastTransferStarted(qulonglong transferID); + void outgoingMulticastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of); + void outgoingMulticastTransferFinished(qulonglong transferID); + void outgoingMulticastTransferFailed(qulonglong transferID, QString reason); + void incomingMulticastTransferNew(qulonglong transferID, QString sender, QString filename, qulonglong size); + void incomingMulticastTransferStarted(qulonglong transferID); + void incomingMulticastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of); + void incomingMulticastTransferFinished(qulonglong transferID); + void incomingMulticastTransferFailed(qulonglong transferID, QString reason); + protected: void timerEvent(QTimerEvent *event); @@ -115,7 +138,9 @@ private: bool _locked; ///< are we locked? QString _lockMsg; ///< message to display while we're locked bool _vncAllowed; ///< whether vncConnections to this client are allowed (dup?) - BlankScreen *_blankScreen;///< obhject to blank the screen + /*#ifndef __WIN32__*/ + BlankScreen *_blankScreen;///< object to blank the screen + /*#endif*/ QFileSystemWatcher* _notify; ///< used to get notifies about file changes //vnc-server @@ -133,8 +158,6 @@ private: PVSServerConnection* _pvsServerConnection; ///< our tcp connection object to the pvsserver - QSettings _settings; - PVSServiceDiscovery *_sdClient; PVSChatClient *_chat; @@ -148,5 +171,23 @@ private: unprivileged_handler_chain _inputEventHandlers; void handleInputEvent(InputEvent const& evt); void initializeInputEventHandling(); + + // multicast transfer + McastConfiguration* _masterMcastConfig; + QHash<quint64, PVSOutgoingMulticastTransfer*> _outgoingTransfers; + QHash<quint64, PVSIncomingMulticastTransfer*> _incomingTransfers; + + void loadMcastConfig(QString const& encoded); + void onIncomingMulticastTransfer(QString const& sender, qulonglong transferID, QString const& basename, qulonglong size, ushort port); + static quint64 generateMcastTransferID(); + +private Q_SLOTS: + // housekeeping + void outgoingMulticastTransferDelete(qulonglong transferID); + void incomingMulticastTransferDelete(qulonglong transferID); + void onIncomingMulticastTransferRetry(QString const& sender, qulonglong transferID); + +private: + QSettings _settings; }; #endif /* PVSCLIENT_H_ */ diff --git a/src/pvsDaemon.cpp b/src/pvsDaemon.cpp index 591d43b..1784a14 100644 --- a/src/pvsDaemon.cpp +++ b/src/pvsDaemon.cpp @@ -3,21 +3,18 @@ #include <stdlib.h> #include "pvs.h" #include "src/net/pvsLocalhostCommunicator.h" -#include "src/util/pvsSettingsManager.h" #include "setup.h" #include "src/net/pvsMsg.h" #include "src/core/pvsChatClient.h" PVS *mainClient = NULL; - -// This define works as a switch whether to run as deamon or regular app -#define as_daemon +QTextStream qout(stdout); /// VERSION_STRING is defined in src/version.h void printVersion(bool doExit) { - - printf("Version:\t"VERSION_STRING"\n"); + qout << "Version:\t"VERSION_STRING"\n"; + qout.flush(); if (doExit) exit(0); } @@ -25,58 +22,52 @@ void printVersion(bool doExit) /// outputs the full help text void printHelp() { - printf("**************************************************************\n"); - printf("\nPool Video Switch Client\n"); - printf("**************************************************************\n"); - printVersion(false); - printf("**************************************************************\n"); - printf("Usage:\tpoolVSClient <<option> <value>, ... >\n\n"); - printf("Options:\n\n"); - printf("-vncScriptFile <fullpath\\filename>\n\tSpecifies a custom location for the vnc-start/stop-script.\n\tIf not specified, ~/.pvs/pvs-vncsrv is expected.\n\n"); - printf("-freq <seconds>\n\tSpecifies how long to wait until a reconnection attempt is made.\n\tDefault is 5.\n\n"); - printf("-port <port>\n\tSpecifies on which port to run.\n\tDefault is %d.\n\n", SERVER_PORT_INT); - printf("-h or --help\n\t Shows this help text and exits.\n\n"); - printf("-v or --version\n\t Shows the current version and exits.\n"); - printf( - "-c <string command>:<string value> \n\t Sends the command and the optional value to a running PVS-Client.\n\t Command and value may not contain spaces or colons.\n\t The dividing colon is mandatory.\n"); - printf("-commands: \n\tPrints out available commands to use with -c . \n "); - printf("**************************************************************\n"); + qout << "**************************************************************\n"; + qout << "Pool Video Switch Client\n"; + qout << "**************************************************************\n"; + qout << QObject::tr("Version: ") << VERSION_STRING << "\n"; + qout << "**************************************************************\n"; + qout << QObject::tr("Usage:") << "\tpoolVSClient " << QObject::tr("<<option> <value>, ... >") << "\n\n"; + qout << QObject::tr("Options:") << "\n\n"; + qout << QObject::tr("-vncScriptFile <fullpath\\filename>") << "\n\t" << QObject::tr("Specifies a custom location for the vnc-start/stop-script.")<< "\n\t" << QObject::tr("If not specified, /usr/bin/pvs-vncsrv is expected.") << "\n\n"; + qout << QObject::tr("-freq <seconds>") << "\n\t" << QObject::tr("Specifies how long to wait until a reconnection attempt is made.") << "\n\t" << QObject::tr("Default is 5.") << "\n\n"; + qout << QObject::tr("-port <port>") << "\n\t" << QObject::tr("Specifies on which port to run.") << "\n\t" << QObject::tr("Default is ") << SERVER_PORT_INT << ".\n\n"; + qout << QObject::tr("-h or --help") << "\n\t" << QObject::tr("Shows this help text and exits.") << "\n\n"; + qout << QObject::tr("-v or --version") << "\n\t" << QObject::tr("Shows the current version and exits.") << "\n"; + qout << QObject::tr("-d or --daemon") << "\n\t" << QObject::tr("Start as daemon.") << "\n"; + qout << QObject::tr("-c <string command>:<string value>") << "\n\t" << QObject::tr("Sends the command and the optional value to a running PVS-Client.") << "\n\t" << QObject::tr("Command and value may not contain spaces or colons.") << "\n\t" << QObject::tr("The dividing colon is mandatory.") << "\n"; + qout << "--commands: \n\t" << QObject::tr("Prints out available commands to use with -c.") << "\n"; + qout << "**************************************************************\n"; + qout.flush(); exit(0); } /// outputs a brief help text void printNotice() { - printf( - "Use -h or --help to get a listing of all options.\n-v or --version gives you the current version.\n\n"); + qout << QObject::tr("Use -h or --help to get a listing of all options.\n-v or --version gives you the current version.\n\n"); + qout.flush(); } void printCommands() { - printf("**************************************************************\n"); - printf("chat:<on/ off/ 1/ 2/ 3>\n "); - printf("on = turns that chat option on\n off = turns the chat option off\n 1 = bossmode\n 2 = community\n 3 = private\n"); - printf("stop \n\t Stops the running PVS-Client.\n"); - printf("**************************************************************\n"); + qout << "**************************************************************\n"; + qout << "stop \n\t Stops the running PVS-Client.\n"; + qout << "**************************************************************\n"; + qout.flush(); exit(0); } /// int main(int argc, char** argv) { + bool _daemon = false; int frequency = 5; int port = -1; #ifdef as_daemon bool no_fork = false; #endif - QFileInfo script; - script.setFile("/usr/bin/pvs-vncsrv"); - if (!script.exists()) - script.setFile("/usr/local/bin/pvs-vncsrv"); - if (!script.exists()) - script.setFile("/home/" + getUserName() + "/.pvs/pvs-vncsrv"); - QCoreApplication app(argc, argv); app.setOrganizationName("openslx"); app.setOrganizationDomain("openslx.org"); @@ -86,17 +77,37 @@ int main(int argc, char** argv) translator.load(":pvs"); app.installTranslator(&translator); + QFileInfo script; +#ifdef __WIN32__ + //TODO Win32 + if (!script.exists()) + script.setFile(getHomeDir() + "/.pvs/pvs-vncsrv_win32.bat"); +#else + QSettings settings; + if (!QFile::exists(settings.fileName())) + { + QDir::root().mkpath(QFileInfo(settings.fileName()).path()); + QFile::copy("/etc/openslx/pvs.conf", settings.fileName()); + } + QString s = settings.value("VNC/script").toString(); + script.setFile(s); + if (!script.exists()) + script.setFile("/usr/bin/pvs-vncsrv"); + if (!script.exists()) + script.setFile("/usr/local/bin/pvs-vncsrv"); + if (!script.exists()) + script.setFile(getHomeDir() + "/.pvs/pvs-vncsrv"); +#endif //__WIN32__ PVSLocalhostCommunicator com(getPolicyFilePath(QString( ".comfile"))); com.run(); if (!(com.running())) { - printf("Error. UDS Communicator is not running. Exiting.\n"); + qDebug("Error. UDS Communicator is not running. Exiting."); exit(0); } - printf("UDS Communicator is running.\n"); int option_index = 0; while (1) @@ -106,6 +117,7 @@ int main(int argc, char** argv) { "help", no_argument, 0, 'h' }, { "commands", no_argument, 0, 'o' }, { "version", no_argument, 0, 'v' }, + { "daemon", no_argument, 0, 'd' }, { "port", required_argument, 0, 'p' }, { "freq", required_argument, 0, 'f' }, { "client", required_argument, 0, 'e' }, @@ -117,7 +129,7 @@ int main(int argc, char** argv) }; /* getopt_long stores the option index here. */ - int c = getopt_long(argc, argv, "hvoFc:f:e:s:p:", long_options, + int c = getopt_long(argc, argv, "hvodc:f:e:s:p:", long_options, &option_index); option_index++; if (c == -1) @@ -134,6 +146,9 @@ int main(int argc, char** argv) case 'v': printVersion(true); break; + case 'd': + _daemon = true; + break; case 'c': { if (option_index + 1 < argc) @@ -141,78 +156,22 @@ int main(int argc, char** argv) if (com.server()) { // wont work, no daemon running - printf("Error. No running PVS-Client found. Exiting.\n"); + qDebug("No running PVS-Client found. Exiting."); com.stop(); } else { - QStringList line = QString::fromLocal8Bit(argv[option_index - + 1]).split(":"); - QString &ident = line[0]; - QString message; - if (line.size() > 1) - message = line[1]; - if (ident.size() > 0) // no use sending empty idents... not even sure if this COULD happen - { - bool flag = false; - if (ident == "make") - PVSSettingsManager::getManager()->setConfigs(); - else if (ident == "chat" && message == "boss") - { - PVSSettingsManager::getManager()->reWriteConfigs("chatmode", "bossmode"); - flag = true; - - } - else if (ident == "chat" && message == "all") - { - PVSSettingsManager::getManager()->reWriteConfigs("chatmode", "community"); - flag = true; - } - else if (ident == "chat" && message == "private") - { - PVSSettingsManager::getManager()->reWriteConfigs("chatmode", "private"); - flag = true; - } - else if (ident == "chat" && message == "on") - { - PVSSettingsManager::getManager()->reWriteConfigs("chatstate", "on"); - flag = true; - } - else if (ident == "chat" && message == "off") - { - PVSSettingsManager::getManager()->reWriteConfigs("chatstate", "off"); - flag = true; - } - else if (ident == "room") - { - //PVSSettingsManager::getManager()->reWriteConfigs(ident, message); - flag = true; - } - else if (ident == "stop" && message == NULL) - flag = true; - else - printf("option %s doesn't exist\n", ident.toUtf8().data()); - - if (flag) - { - qDebug("Will send i: %s, m: %s\n", ident.toUtf8().data(), message.toUtf8().data()); - com.sendCommand(ident, message); - QCoreApplication::processEvents(QEventLoop::AllEvents); - printf("Sent command. Exiting.\n"); - } - } - - else - printf("Something went horribly wrong, since the ident is empty.\n"); - - } + qDebug("Will send i: %s, m: %s\n", argv[option_index + 1], ""); + com.sendCommand(QString(argv[option_index + 1]), ""); + QCoreApplication::processEvents(QEventLoop::AllEvents); + qDebug("Sent command. Exiting."); + } } else { - printf("Error. No command issued. Exiting.\n"); + qDebug("Error. No command issued. Exiting."); } exit(0); // and gone - break; } case 'f': { @@ -257,7 +216,7 @@ int main(int argc, char** argv) { if (option_index + 1 < argc) { - printf("WARNING: -e is deprecated\n"); + qDebug("WARNING: -e is deprecated"); option_index++; continue; } @@ -296,7 +255,7 @@ int main(int argc, char** argv) if (!com.server()) { - printf("Error. PoolVSClient already running. Exiting\n"); + qDebug("Error. PoolVSClient already running. Exiting"); com.stop(); exit(0); } @@ -304,66 +263,14 @@ int main(int argc, char** argv) ConsoleLog setLogName(QString("log.client")); ConsoleLog writeLine(QString("PVS-Client started.")); -#ifdef as_daemon - - if (!no_fork) + if (_daemon) { - /* Our process ID and Session ID */ - pid_t pid, sid; - - /* Fork off the parent process */ - pid = fork(); - if (pid < 0) - { - exit(-1); - } - /* If we got a good PID, then - we can exit the parent process. */ - if (pid > 0) - { - exit(0); - } - - /* Change the file mode mask */ - umask(0); - - /* Open any logs here */ - - /* Create a new SID for the child process */ - sid = setsid(); - if (sid < 0) - { - /* Log the failure */ - exit(-1); - } - - /* Change the current working directory */ - if ((chdir("/")) < 0) - { - /* Log the failure */ - exit(-1); - } - - /* Close out the standard file descriptors */ - close(STDIN_FILENO); - freopen ((QString("/home/").append(getUserName().append(QString("/.pvs/dump")))).toUtf8().data(),"w",stdout); - //close(STDOUT_FILENO); - close(STDERR_FILENO); - - /* Daemon-specific initialization goes here */ - - /* The Big Loop */ + #ifndef __WIN32__ + daemon(1, 1); + #endif /*__WIN32__*/ } - else - { - /* just the umask(), please */ - umask(0); - } - -#endif mainClient = new PVS(); - PVSSettingsManager::getManager()->setConfigFile(getPolicyFilePath("clientconf")); com.getDispatcher()->addListener("*", mainClient, &PVS::onDaemonCommand); if (port <= 0) @@ -374,11 +281,6 @@ int main(int argc, char** argv) createPolicyDir(); createPolicyFiles(); - // long int gr = 0; - mainClient->setScriptPath(script.filePath()); - app.exec(); - delete mainClient; - - return 0; + return app.exec(); } diff --git a/src/pvsgui.cpp b/src/pvsgui.cpp index 25f1cd6..eb1383b 100644 --- a/src/pvsgui.cpp +++ b/src/pvsgui.cpp @@ -17,13 +17,25 @@ # ----------------------------------------------------------------------------- */ +#include <getopt.h> #include "pvsgui.h" +#include "version.h" PVSGUI::PVSGUI(QWidget *parent) : QWidget(parent) { setupUi(this); + if (!QFile::exists(_settings.fileName())) + { + QDir::root().mkpath(QFileInfo(_settings.fileName()).path()); + QFile::copy("/etc/openslx/pvsgui.conf", _settings.fileName()); + } + + // stop running pvs + qDebug("[%s] Stopping pvs daemon.", metaObject()->className()); + QProcess::execute("pvs -c stop"); + _menu = new QMenu(this); _hostMenu = new QMenu(tr("Connect"), this); _hosts = new QHash<QString, QAction*> (); @@ -38,62 +50,52 @@ PVSGUI::PVSGUI(QWidget *parent) : setupMenu(); - if (QSystemTrayIcon::isSystemTrayAvailable()) - { - qDebug("[%s] System tray available.", metaObject()->className()); - _trayIcon = new QSystemTrayIcon(QIcon(":cam_off32.svg"), this); - _trayIcon->setContextMenu(_menu); - _trayIcon->setVisible(true); - _chatDialog->setTrayIcon(_trayIcon); - } - else - _trayIcon = NULL; + _trayIcon = new QSystemTrayIcon(QIcon(":cam_off32.svg"), this); + _trayIcon->setContextMenu(_menu); + _trayIcon->setVisible(true); + _chatDialog->setTrayIcon(_trayIcon); // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/", this); - dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); - _ifaceDBus->start(); // start pvs if not running + if (dbus.isConnected()) + qDebug("[%s] Connection to DBus successful.", metaObject()->className()); + else + qDebug("[%s] ERROR: Could not connect to DBus!", metaObject()->className()); - // get available hosts - QDBusPendingReply<QStringList> reply0 = _ifaceDBus->getAvailableHosts(); + // start pvs daemon + qDebug("[%s] Starting pvs daemon.", metaObject()->className()); + QDBusPendingReply<bool> reply0 = _ifaceDBus->start(); reply0.waitForFinished(); - QStringList hosts = reply0.value(); - if (reply0.isValid() && !hosts.isEmpty()) + if (reply0.isValid() && reply0.value()) + qDebug("[%s] Connection to PVS daemon successful.", metaObject()->className()); + else + qDebug("[%s] ERROR: Could not connect to PVS daemon!", metaObject()->className()); + + // get available hosts + QDBusPendingReply<QStringList> reply1 = _ifaceDBus->getAvailableHosts(); + reply1.waitForFinished(); + QStringList hosts = reply1.value(); + if (reply1.isValid() && !hosts.isEmpty()) foreach (QString host, hosts) addHost(host); // already connected? - QDBusPendingReply<QString> reply1 = _ifaceDBus->isConnected(); - reply1.waitForFinished(); - QString host = reply1.value(); - if (reply1.isValid() && host != "") + QDBusPendingReply<QString> reply2 = _ifaceDBus->isConnected(); + reply2.waitForFinished(); + QString host = reply2.value(); + if (reply2.isValid() && host != "") connected(host); else disconnected(); - if (dbus.isConnected()) - qDebug("[%s] Connection to DBus successful!", metaObject()->className()); - - // TODO: perhaps this can go if fadi does his work - // check if vnc is allowed and setup checkbox - QFile file(QDir::toNativeSeparators(QDir::homePath() + "/.pvs/.allow")); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) - { - QTextStream in(&file); - QString line = in.readLine(); - if (line == "1") - vncCheckBox->setChecked(true); - file.close(); - } - // listen on port 29481 for incoming file transfers _serverSocket = new QTcpServer(); _serverSocket->listen(QHostAddress::Any, 29481); connect(_serverSocket, SIGNAL(newConnection()), this, SLOT(receiveFile())); // signals & slots - menu + connect(_showAction, SIGNAL(toggled(bool)), this, SLOT(setVisible(bool))); connect(_disconnectAction, SIGNAL(triggered()), this, SLOT(pvsDisconnect())); connect(_startChatAction, SIGNAL(triggered()), _chatDialog, SLOT(open())); connect(_sendFileAction, SIGNAL(triggered()), this, SLOT(sendFile())); @@ -108,8 +110,6 @@ PVSGUI::PVSGUI(QWidget *parent) : connect(_hostMenu, SIGNAL(aboutToHide()), this, SLOT(hide())); connect(_hostMenu, SIGNAL(triggered(QAction*)), this, SLOT(pvsConnect(QAction*))); - connect(vncCheckBox, SIGNAL(stateChanged(int)), this, - SLOT(setVncAllow(int))); // signals & slots - dbus connect(_ifaceDBus, SIGNAL(showMessage(QString, QString, bool)), this, @@ -119,13 +119,11 @@ PVSGUI::PVSGUI(QWidget *parent) : connect(_ifaceDBus, SIGNAL(disconnected()), this, SLOT(disconnected())); connect(_ifaceDBus, SIGNAL(addHost(QString)), this, SLOT(addHost(QString))); connect(_ifaceDBus, SIGNAL(delHost(QString)), this, SLOT(delHost(QString))); + connect(_ifaceDBus, SIGNAL(incomingMulticastTransferNew(qulonglong, QString, QString, qulonglong)), SLOT(incomingMulticastFile(qulonglong, QString, QString, qulonglong))); // show toolbar - setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint); setAttribute(Qt::WA_AlwaysShowToolTips); - updateConfig(); - setVisible(true); - hide(); } PVSGUI::~PVSGUI() @@ -139,9 +137,52 @@ PVSGUI::~PVSGUI() void PVSGUI::updateConfig() { if (_settings.value("Display/location").isNull()) - setLocation(POSITION_TOP_CENTER); + setPosition(POSITION_TOP_CENTER); else - setLocation(_settings.value("Display/location").toInt()); + setPosition(_settings.value("Display/location").toInt()); +} + + +void PVSGUI::setVisible(bool visible) +{ + QWidget::setVisible(visible); + _showAction->setChecked(isVisible()); +} + +void PVSGUI::setPosition(int position) +{ + _position = position; + switch (_position) + { + case POSITION_TOP_LEFT: + move(0, 0); + break; + case POSITION_TOP_CENTER: + move((QApplication::desktop()->width() - width()) / 2, 0); + break; + case POSITION_TOP_RIGHT: + move(QApplication::desktop()->width() - width(), 0); + break; + case POSITION_BOTTOM_LEFT: + move(0, QApplication::desktop()->height() - height()); + break; + case POSITION_BOTTOM_CENTER: + move((QApplication::desktop()->width() - width()) / 2, + QApplication::desktop()->height() - height()); + break; + case POSITION_BOTTOM_RIGHT: + move(QApplication::desktop()->width() - width(), + QApplication::desktop()->height() - height()); + break; + default: + updateConfig(); + } +} + +void PVSGUI::hide() +{ + if (!_menu->isVisible() && !_hostMenu->isVisible()) + hide(true); } //////////////////////////////////////////////////////////////////////////////// @@ -186,6 +227,8 @@ void PVSGUI::mouseMoveEvent(QMouseEvent *event) void PVSGUI::setupMenu() { // setup actions + _showAction = new QAction(tr("Show &toolbar"), this); + _showAction->setCheckable(true); _disconnectAction = new QAction(tr("&Disconnect"), this); _startChatAction = new QAction(tr("C&hat"), this); _sendFileAction = new QAction(tr("&Send File"), this); @@ -195,6 +238,7 @@ void PVSGUI::setupMenu() _quitAction = new QAction(tr("&Quit"), this); // setup menu + _menu->addAction(_showAction); _menu->addMenu(_hostMenu); _menu->addAction(_disconnectAction); _menu->addAction(_showInfoAction); @@ -211,60 +255,24 @@ void PVSGUI::setupMenu() hostButton->setMenu(_hostMenu); } -void PVSGUI::setLocation(int location) -{ - _location = location; - switch (_location) - { - case POSITION_TOP_LEFT: - move(0, 0); - break; - case POSITION_TOP_CENTER: - move((QApplication::desktop()->width() - width()) / 2, 0); - break; - case POSITION_TOP_RIGHT: - move(QApplication::desktop()->width() - width(), 0); - break; - case POSITION_BOTTOM_LEFT: - move(0, QApplication::desktop()->height() - height()); - break; - case POSITION_BOTTOM_CENTER: - move((QApplication::desktop()->width() - width()) / 2, - QApplication::desktop()->height() - height()); - break; - case POSITION_BOTTOM_RIGHT: - move(QApplication::desktop()->width() - width(), - QApplication::desktop()->height() - height()); - break; - default: - break; - } -} - void PVSGUI::hide(bool b) { if (b) { - if (_location <= POSITION_TOP_RIGHT) + if (_position <= POSITION_TOP_RIGHT) move(x(), 2 - height()); else move(x(), QApplication::desktop()->height() - 2); } else { - if (_location <= POSITION_TOP_RIGHT) + if (_position <= POSITION_TOP_RIGHT) move(x(), 0); else move(x(), QApplication::desktop()->height() - height()); } } -void PVSGUI::hide() -{ - if (!_menu->isVisible() && !_hostMenu->isVisible()) - hide(true); -} - void PVSGUI::pvsConnect(QAction *action) { QString host = action->text(); @@ -392,22 +400,6 @@ void PVSGUI::delHost(QString host) } } -// TODO: perhaps this can go if fadi does his work -void PVSGUI::setVncAllow(int i) -{ - QFile file(QDir::toNativeSeparators(QDir::homePath() + "/.pvs/.allow")); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) - return; - - QTextStream out(&file); - if (i == 0) - out << 0; - else - out << 1; - - file.close(); -} - void PVSGUI::sendFile() { ClientFileSendDialog *d = new ClientFileSendDialog(); @@ -421,24 +413,103 @@ void PVSGUI::receiveFile() d->open(); } +void PVSGUI::incomingMulticastFile(qulonglong transferID, QString sender, QString basename, qulonglong size) +{ + ClientFileReceiveDialog *d = new ClientFileReceiveDialog(sender, transferID, basename, size, _ifaceDBus, this); + d->open(); +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Main +void printHelp() +{ + QTextStream qout(stdout); + qout << QObject::tr("Usage: pvsgui [OPTIONS]...") << endl; + qout << QObject::tr("Start the Pool Video Switch GUI.") << endl; + qout << QObject::tr("Options:") << endl << endl; + qout << "-b or --toolbar" << "\t\t" << QObject::tr("Start with toolbar.") << endl; + qout << "-p or --position" << "\t" << QObject::tr("Set toolbar position (0-5)") << endl; + qout << "-h or --help" << "\t\t" << QObject::tr("Show this help text and quit.") << endl; + qout << "-v or --version" << "\t\t" << QObject::tr("Show version and quit.") << endl; + qout << endl; + qout.flush(); + exit(0); +} + +void printVersion() +{ + QTextStream qout(stdout); + qout << QObject::tr("Version: ") << VERSION_STRING << endl; + qout << endl; + qout.flush(); + exit(0); +} + int main(int argc, char *argv[]) { - QApplication app(argc, argv); + QtSingleApplication app(argc, argv); + app.setQuitOnLastWindowClosed(false); app.setOrganizationName("openslx"); app.setOrganizationDomain("openslx.org"); app.setApplicationName("pvsgui"); + // only one instance should be allowed + if (app.sendMessage("")) + { + qDebug("[PVSGUI] ERROR: Already running. Exiting"); + return 0; + } + // use system locale as language to translate gui QTranslator translator; translator.load(":pvsgui"); app.installTranslator(&translator); + bool visible = false; + int position = -1; + + // parse command line arguments + int opt = 0; + int longIndex = 0; + static const char *optString = "hvp:b?"; + static const struct option longOpts[] = + { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { "position", required_argument, NULL, 'p' }, + { "toolbar", no_argument, NULL, 'b' } + }; + + opt = getopt_long( argc, argv, optString, longOpts, &longIndex ); + while( opt != -1 ) + { + switch( opt ) + { + case 'h': + printHelp(); + break; + case 'v': + printVersion(); + break; + case 'p': + position = atoi(optarg); + break; + case 'b': + visible = true; + break; + case '?': + exit(1); + } + opt = getopt_long( argc, argv, optString, longOpts, &longIndex ); + } + PVSGUI pvsgui; + pvsgui.setPosition(position); + pvsgui.setVisible(visible); + pvsgui.hide(); return app.exec(); } diff --git a/src/pvsgui.h b/src/pvsgui.h index f9a0ab8..b96d73c 100644 --- a/src/pvsgui.h +++ b/src/pvsgui.h @@ -16,6 +16,7 @@ #include <QtGui> #include <QtNetwork> +#include "3rdparty/qtsingleapplication/qtsingleapplication.h" #include "ui_clientToolbar.h" #include "src/gui/clientConfigDialog.h" #include "src/gui/clientChatDialog.h" @@ -30,7 +31,6 @@ class PVSGUI: public QWidget, private Ui_ClientToolbarClass { Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "org.openslx.pvsgui") public: PVSGUI(QWidget *parent = 0); @@ -45,6 +45,9 @@ public: public Q_SLOTS: void updateConfig(); + void setVisible(bool visible); + void setPosition(int position); + void hide(); protected: void enterEvent(QEvent *e); @@ -55,20 +58,18 @@ protected: private Q_SLOTS: void showMessage(QString title, QString msg, bool useDialog = false); - void hide(); void connected(QString host); void disconnected(); void addHost(QString host); void delHost(QString host); void pvsConnect(QAction *action); void pvsDisconnect(); - void setVncAllow(int i); void sendFile(); void receiveFile(); + void incomingMulticastFile(qulonglong, QString sender, QString basename, qulonglong size); private: void setupMenu(); - void setLocation(int location); void hide(bool b); QMenu *_menu; @@ -82,6 +83,7 @@ private: ClientVNCViewer *_vncViewer; AboutDialog *_aboutDialog; + QAction *_showAction; QAction *_disconnectAction; QAction *_startChatAction; QAction *_sendFileAction; @@ -90,7 +92,7 @@ private: QAction *_aboutAction; QAction *_quitAction; - int _location; + int _position; QPoint _clickPoint; QString _passwd; diff --git a/src/pvsmgr.cpp b/src/pvsmgr.cpp index 83f5fe0..dd00c0e 100644 --- a/src/pvsmgr.cpp +++ b/src/pvsmgr.cpp @@ -18,7 +18,6 @@ #include <QtGui/QDesktopServices> #include "gui/mainWindow.h" #include "util/consoleLogger.h" -#include "util/pvsSettingsManager.h" #include "util/CertManager.h" QApplication *qtApp; @@ -47,7 +46,6 @@ int main(int argc, char** argv) exit(123); } */ - PVSSettingsManager::getManager()->setConfigFile(getPolicyFilePath("serverconf")); MainWindow w; w.show(); return qtApp->exec(); diff --git a/src/pvsmgrtouch.cpp b/src/pvsmgrtouch.cpp index fa34294..d14ea56 100644 --- a/src/pvsmgrtouch.cpp +++ b/src/pvsmgrtouch.cpp @@ -16,9 +16,7 @@ #include <QtGui> #include <QtGui/QDesktopServices> -#include "gui/touchgui.h" #include "util/consoleLogger.h" -#include "util/pvsSettingsManager.h" #include "util/CertManager.h" QApplication *qtApp; @@ -47,7 +45,6 @@ int main(int argc, char** argv) exit(123); } */ - PVSSettingsManager::getManager()->setConfigFile(getPolicyFilePath("serverconf")); pvsMainWindow w; w.show(); return qtApp->exec(); diff --git a/src/util/clientGUIUtils.cpp b/src/util/clientGUIUtils.cpp index a8a9487..ff002d3 100644 --- a/src/util/clientGUIUtils.cpp +++ b/src/util/clientGUIUtils.cpp @@ -143,13 +143,3 @@ bool BlankScreen::unlock() return !(locked = false); } -static Display* _dpy = 0; - -Display* X11Info::display() -{ - if(!_dpy) - { - _dpy = XOpenDisplay(0); - } - return _dpy; -} diff --git a/src/util/clientGUIUtils.h b/src/util/clientGUIUtils.h index 4da0a99..7f7ea47 100644..100755 --- a/src/util/clientGUIUtils.h +++ b/src/util/clientGUIUtils.h @@ -1,21 +1,20 @@ +#ifndef _BLANKSCREEN_H_ +#define _BLANKSCREEN_H_ + #include "src/util/consoleLogger.h" -#include <X11/Xlib.h> // Every Xlib program must include this -#include <X11/cursorfont.h> #include <assert.h> #include <unistd.h> #include <stdio.h> - #define REFRESH_RATE 0.15 - -#ifndef _BLANKSCREEN_H_ -#define _BLANKSCREEN_H_ +class BlankScreen_Sysdep; class BlankScreen { public: BlankScreen(); + virtual ~BlankScreen(); void draw(bool force = false); bool lock(); bool unlock(); @@ -23,23 +22,17 @@ public: bool lock_inputs(); private: - Display *dpy; - Window win; - XEvent ev; - int scr; - - bool locked; - - - QString lockMsg; - int blackColor, whiteColor; - int offX, offY; + BlankScreen_Sysdep* _sysdep; }; +#ifndef __WIN32__ +# include <X11/Xlib.h> + class X11Info { public: static Display* display(); }; +#endif /* !__WIN32__ */ #endif diff --git a/src/util/clientGUIUtils_Win32.cpp b/src/util/clientGUIUtils_Win32.cpp new file mode 100755 index 0000000..1b4d2ae --- /dev/null +++ b/src/util/clientGUIUtils_Win32.cpp @@ -0,0 +1,46 @@ +
+#include "clientGUIUtils.h"
+#include <qwidget.h>
+
+struct BlankScreen_Sysdep {
+
+ bool locked;
+ QWidget* blankwin;
+
+ QString lockMsg;
+ int blackColor, whiteColor;
+ int offX, offY;
+};
+
+BlankScreen::BlankScreen()
+{
+ _sysdep = new BlankScreen_Sysdep;
+ _sysdep->blankwin = new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
+ _sysdep->blankwin->setWindowState(Qt::WindowFullScreen);
+ _sysdep->blankwin->show();
+}
+
+BlankScreen::~BlankScreen()
+{
+ delete _sysdep;
+}
+
+void BlankScreen::draw(bool force)
+{
+
+}
+
+bool BlankScreen::lock()
+{
+ return true;
+}
+
+bool BlankScreen::lock_inputs()
+{
+ return true;
+}
+
+bool BlankScreen::unlock()
+{
+ return true;
+}
diff --git a/src/util/clientGUIUtils_X11.cpp b/src/util/clientGUIUtils_X11.cpp new file mode 100755 index 0000000..4b5afe0 --- /dev/null +++ b/src/util/clientGUIUtils_X11.cpp @@ -0,0 +1,179 @@ +#include "clientGUIUtils.h" +#include <X11/Xlib.h> +#include <X11/cursorfont.h> + + +struct BlankScreen_Sysdep { + + Display *dpy; + Window win; + XEvent ev; + int scr; + + bool locked; + + + QString lockMsg; + int blackColor, whiteColor; + int offX, offY; +}; + +BlankScreen::BlankScreen() +{ + _sysdep = new BlankScreen_Sysdep; + _sysdep->dpy = XOpenDisplay(NULL); + _sysdep->scr = DefaultScreen(_sysdep->dpy); + assert(_sysdep->dpy); + _sysdep->blackColor = BlackPixel(_sysdep->dpy, DefaultScreen(_sysdep->dpy)); + _sysdep->whiteColor = WhitePixel(_sysdep->dpy, DefaultScreen(_sysdep->dpy)); +// win = XCreateSimpleWindow(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), 0, 0, 200, 100, 0, blackColor, whiteColor); + _sysdep->win = XCreateSimpleWindow(_sysdep->dpy, RootWindow(_sysdep->dpy, _sysdep->scr), 10, 10, 200, 200, 1, WhitePixel(_sysdep->dpy, _sysdep->scr), BlackPixel(_sysdep->dpy, _sysdep->scr)); + + XSelectInput(_sysdep->dpy, _sysdep->win, ExposureMask | KeyPressMask); + _sysdep->locked = false; + _sysdep->offX = _sysdep->offY = 0; +} + +BlankScreen::~BlankScreen() +{ + delete _sysdep; +} + +void BlankScreen::draw(bool force) +{ + if (_sysdep->locked)// no need to draw if we're not showing the window + { + XWindowAttributes xwa; + XGetWindowAttributes(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), &xwa); + int hx = (xwa.width)>>2, hy = (xwa.height)>>2; + + if (XCheckTypedEvent(_sysdep->dpy, Expose, &_sysdep->ev) || force ) + { + hx += _sysdep->offX; + hy += _sysdep->offY; + + GC gcc = XCreateGC(_sysdep->dpy, _sysdep->win, 0, NULL); + XSetForeground(_sysdep->dpy, gcc, _sysdep->whiteColor); +// XClearArea(_sysdep->dpy, _sysdep->win, 0, 0, xwa.width, xwa.height, false); + if (_sysdep->lockMsg.size() > 0) + { + char *msg = const_cast<char*>(_sysdep->lockMsg.toUtf8().data()); + XDrawString(_sysdep->dpy, _sysdep->win, gcc/*DefaultGC(dpy, scr)*/, hx, hy, msg, strlen(msg)); + } + else + { + } + } + } +} + +bool BlankScreen::lock() +{ +#define lock_test + + if (_sysdep->locked) + return _sysdep->locked; + + // We want to get MapNotify events + XSelectInput(_sysdep->dpy, _sysdep->win, StructureNotifyMask); + + // "Map" the window (that is, make it appear on the screen) + XMapWindow(_sysdep->dpy, _sysdep->win); + + // Create a "Graphics Context" + //GC gc = XCreateGC(dpy, win, 0, NULL); + + XEvent xev; + Atom wm_state = XInternAtom(_sysdep->dpy, "_NET_WM_STATE", False); + Atom fullscreen = XInternAtom(_sysdep->dpy, "_NET_WM_STATE_FULLSCREEN", False); + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = _sysdep->win; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = fullscreen; + xev.xclient.data.l[2] = 0; + + XSendEvent(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), False, + SubstructureNotifyMask, &xev); + + + + + // Wait for the MapNotify event + for (;;) + { + XEvent e; + XNextEvent(_sysdep->dpy, &e); + if (e.type == MapNotify) + break; + } + //Flush it! + //XFlush(_sysdep->dpy); + +#ifndef lock_test + // load the locked cursor, so people dont think they can click anything + // TODO: Use some kind of invisible cursor instead of the wait-cursor + Cursor _sysdep->locked_cur = XCreateFontCursor(_sysdep->dpy, XC_watch); + XDefineCursor(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy),_sysdep->locked_cur); +#endif + + // grabbing of keyboard and mouse and hide the cursor + XGrabKeyboard(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabPointer(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime); + + if (!_sysdep->locked) + ConsoleLog writeLine(QString("Locked")); + + // see header for more information on this switch + return _sysdep->locked = true; +} + +bool BlankScreen::lock_inputs() +{ + // grabbing of keyboard and mouse and hide the cursor + XGrabKeyboard(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabPointer(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime); + return true; +} + +bool BlankScreen::unlock() +{ + + if (_sysdep->dpy) + { + + int retval = -1; + + //reset cursor to arrow (no *real* default here...) + Cursor normal_cur = XCreateFontCursor(_sysdep->dpy, XC_arrow); + XDefineCursor(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), normal_cur); + + // ungrabbing of keyboard and mouse + XUngrabPointer(_sysdep->dpy, CurrentTime); + XUngrabKeyboard(_sysdep->dpy, CurrentTime); + + + retval = XUnmapWindow(_sysdep->dpy,_sysdep->win); + if (retval == BadWindow) + ConsoleLog writeError(QString("Bad window while unmapping. Badwindow: ").append(int2String(retval))); + XFlush(_sysdep->dpy); + } + if (_sysdep->locked) + ConsoleLog writeLine(QString("Unlocked")); + + _sysdep->lockMsg.clear(); + return !(_sysdep->locked = false); +} + +static Display* _dpy = 0; + +Display* X11Info::display() +{ + if(!_dpy) + { + _dpy = XOpenDisplay(0); + } + return _dpy; +} diff --git a/src/util/consoleLogger.cpp b/src/util/consoleLogger.cpp index b523b40..9189543 100644..100755 --- a/src/util/consoleLogger.cpp +++ b/src/util/consoleLogger.cpp @@ -226,21 +226,17 @@ void ConsoleLogger::_prepareLog() _logFileGood = false; _readLog(); - mkdir(getPolicyFilePath(QString()).toUtf8().data(), 0777); + createPolicyDir(); QString fullpath; fullpath.append(_logPath); //TODO: handle wether path/ or path were entered? fullpath.append(_logName); _logFile.open(fullpath.toUtf8().data(), std::ofstream::out | std::ofstream::app); if (_logFile.good()) - { _logFileGood = true; - writeTerminal(QString("LogPath/Name changed to: ").append(fullpath)); - } else - { - printf("ERROR: Logfile ( %s ) not accessible/found. Logs will not be available.\n", _logPath.toUtf8().data()); - } + qDebug("ERROR: Logfile ( %s ) not accessible/found. Logs will not be available.", qPrintable(_logPath)); + _logFile.close(); } diff --git a/src/util/consoleLogger.h b/src/util/consoleLogger.h index 3a0950d..e4cb291 100644 --- a/src/util/consoleLogger.h +++ b/src/util/consoleLogger.h @@ -116,7 +116,7 @@ public: _line.push_back('\n'); // add an explicit newline char, so it looks better in the logfile //#ifndef as_daemon if (_level == LOG_TERMINAL) // may look strange here, but its quite central :-) - printf("%s\n", _line.toUtf8().data()); + qDebug("%s", qPrintable(_line)); //#endif }; LOG_LEVEL getLevel() diff --git a/src/util/pvsSettingsManager.cpp b/src/util/pvsSettingsManager.cpp deleted file mode 100644 index a6a742b..0000000 --- a/src/util/pvsSettingsManager.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include "pvsSettingsManager.h" -#include "TextFile.h" - -PVSSettingsManager* PVSSettingsManager::getManager() -{ - if (myself) - return myself; - else - return myself = new PVSSettingsManager; -} - -void PVSSettingsManager::setConfigFile(QString path) -{ - if (path.size() && fileExists(path)) - { - _path = path; - _parseFile(_path); - - } - else - ConsoleLog writeError(QString("Can't open config file \"").append(QString(path).append("\""))); -} - -bool PVSSettingsManager::hasEntry(QString name) -{ - for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++) - { - if ((*it).first.compare(name) == 0) - { - return true; - } - } - return false; -} - -QString PVSSettingsManager::getEntryString(QString name) -{ - for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++) - { - if ((*it).first.compare(name) == 0) - { - return (*it).second; - } - } - return QString(); -} - -void PVSSettingsManager::writeEntry(QString name, QString value) -{ - if (name.size() && value.size()) - return; - bool unique = true; - for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++) - { - if ((*it).first.compare(name) == 0) - { - unique = false; - (*it).second = value; - break; - } - } - if (unique) - { - SettingsEntry tmp(name, value); - settingsList.push_back(tmp); - } -} - - -PVSSettingsManager* PVSSettingsManager::myself = NULL; - -PVSSettingsManager::PVSSettingsManager() -{ - -} - -void PVSSettingsManager::setConfigs() -{ - //default settings - _configs.setValue("Chat/chatstate", "on"); - _configs.setValue("Chat/chatmode", "bossmode"); - _configs.setValue("Room/roomId", "0"); - _configs.setValue("VNC/permit", "off"); - _configs.setValue("VNC/quality", "high"); - _configs.sync(); -} -void PVSSettingsManager::reWriteConfigs(QString set, QString val) -{ - _configs.setValue(set, val); - _configs.sync(); -} - -void PVSSettingsManager::readConfigs(QString sett, QString vall) -{ - //TODO: read the config file.. - _configs.value("Chat/chatstate").toBool(); - _configs.value("Chat/chatmode").toString(); - _configs.value("Room/room").toInt(); - _configs.value("VNC/permit").toBool(); - _configs.value("VNC/quality").toString(); -} - -void PVSSettingsManager::_parseFile(QString path) -{ - QString line; - TextFile file(path); - - SettingsList tmpList; - - if (file.good()) - { - while (!file.eof()) - { - line = file.readLine(); - if (!(line.length() <=1)) // ignore blank - { - if (!(line[0] == '#' || line[0] == '/' || line[0] == '[')) // ignore comments and section headers - { - SettingsEntry tmp = _parseLine(line); - if (tmp.first.size() && tmp.second.size()) - { - bool unique = true; - for (SettingsIter it = tmpList.begin(); it != tmpList.end(); it++) - { - if ((*it).first.compare(tmp.first) == 0) - { - unique = false; - break; - } - } - if (unique) - tmpList.push_back(tmp); - } - } - } - } - } - else - { - ConsoleLog writeError(QString("No configfile \"").append(QString(path).append("\" found or file corrupt."))); - } - - if (tmpList.size()) - settingsList = tmpList; -} -#ifdef verbose -ConsoleLog writeLine(QString("Dumping Config Content of ").append(QString(path).append(" : "))); -for (SettingsIter it = settingsList.begin(); it != settingsList.end(); it++) -{ - ConsoleLog writeLine(QString("Option: ").append(QString((*it).first).append(QString(" | Value: ").append((*it).second)))); -} -ConsoleLog writeLine(QString("End of ").append(QString(path).append("."))); -#endif - -SettingsEntry PVSSettingsManager::_parseLine(QString line) -{ - QString name; - QString value; - - name = lineSplitter(line, "=\n\t", true); - value = lineSplitter(line, "=\n\t", false); - - if (!(name.size() && value.size())) - return SettingsEntry("",""); - - - // remove whitespaces in front of option name - for (int i = 0; i < name.size(); i++) - { - if (name[i] == '\t' || name[i] == ' ') - { - name.remove(i, 1); - i--; - } - else - break; - } - // whitespaces after the value are trimmed by the lineSplitter - - SettingsEntry tmp(name, value); - return tmp; -} - - - diff --git a/src/util/pvsSettingsManager.h b/src/util/pvsSettingsManager.h deleted file mode 100644 index 78607eb..0000000 --- a/src/util/pvsSettingsManager.h +++ /dev/null @@ -1,50 +0,0 @@ -/// documentation test 1 -/// line 2 -/// line 3 -#ifndef _PVSSETTINGSMANGER_H_ -#define _PVSSETTINGSMANGER_H_ - -#include <list> -#include <map> -#include <src/util/util.h> -#include <src/util/consoleLogger.h> -#include <QSettings> - - -/// documentation test 1.1 -/// line 2.1 -/// line 3.1 - -typedef std::pair<QString, QString> SettingsEntry; ///< first = option name, second = option value -typedef std::list<SettingsEntry> SettingsList; ///< obvious -typedef std::list<SettingsEntry>::iterator SettingsIter; - - -class PVSSettingsManager; -/// documentation test 1.2 -/// line 2.2 -/// line 3.2 -class PVSSettingsManager -{ -public: - static PVSSettingsManager* getManager(); - void setConfigFile(QString path); - bool hasEntry(QString name); - QString getEntryString(QString name); - void writeEntry(QString name, QString value); - void setConfigs(); - void reWriteConfigs(QString set, QString val); - void readConfigs(QString sett, QString vall); -private: - static PVSSettingsManager* myself; - PVSSettingsManager(); - void _parseFile(QString path); - SettingsEntry _parseLine(QString line); - QString _path; - SettingsList settingsList; - QSettings _configs; - -}; - - -#endif diff --git a/src/util/util.cpp b/src/util/util.cpp index 946168e..05a209f 100644..100755 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -6,7 +6,11 @@ #include <cstdlib> #include <QStringList> #include <iostream> - +#include <QDir> +#ifdef __WIN32__ + #include <windows.h> + #include <Lmcons.h> +#endif //__WIN32__ PVSServerEntry::PVSServerEntry(QString name) { @@ -45,7 +49,11 @@ int getRandom(int min, int max) if (init) { init = false; + #ifndef __WIN32__ srand ( time(NULL) + getpid() ); + #else + srand ( time(NULL) ); /*might be solved by another random factor*/ + #endif } if (min >= max) return rand(); return rand() % (max-min+1) + min; @@ -184,15 +192,28 @@ QString colonSplitter(QString line, bool first) QString getUserName() { - struct passwd* passUser = getpwuid(getuid()); QString username; - if (passUser) - { - username = QString(passUser->pw_name); - } + #ifdef __WIN32__ + WCHAR* lpszSystemInfo; // pointer to system information + DWORD cchBuff = 256; // size of user name + WCHAR tchBuffer[UNLEN + 1]; // buffer for expanded string + + lpszSystemInfo = tchBuffer; + + // Get and display the user name. + GetUserNameW(lpszSystemInfo, &cchBuff); + + //Unicode string needs to be converted + username = QString::fromWCharArray(lpszSystemInfo); + #else + struct passwd* passUser = getpwuid(getuid()); + if (passUser) + username = QString(passUser->pw_name); + + #endif //#ifdef __WIN32__ if (username.isEmpty()) { - printf("USERNAME COULDNT BE RETRIEVED!\n"); + qDebug("USERNAME COULDNT BE RETRIEVED!"); username = QString("USERNAMEERROR"); } return username; @@ -202,19 +223,21 @@ QString getUserName() QString getFullUsername() { QString fullname = getUserName(); - struct passwd *pd; + #ifndef __WIN32__ + struct passwd *pd; - if (NULL == (pd = getpwuid(getuid()))) - {ConsoleLog writeError("getpwuid() error.");} - else - { - QString tmp = pd->pw_gecos; - QStringList userData = tmp.split(","); - if(userData[0].length() > 0 ) + if (NULL == (pd = getpwuid(getuid()))) + {ConsoleLog writeError("getpwuid() error.");} + else { - fullname = userData[0]; + QString tmp = pd->pw_gecos; + QStringList userData = tmp.split(","); + if(userData[0].length() > 0 ) + { + fullname = userData[0]; + } } - } + #endif //__WIN32__ //might be completed some time to a full solution for WIN32 return fullname; } @@ -266,7 +289,8 @@ bool policyFileExists(QString fileName) void createPolicyDir() { - mkdir(getPolicyDir().toUtf8().data(), 0777); + QDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)).mkdir(".pvs"); + //assuming PolicyDir is defined like in getPolicyDir() } void createPolicyFiles() @@ -299,7 +323,7 @@ QString readPassFromPassFile() } bool getAllowed() { - printf("Checking %s\n", getPolicyFilePath(QString(".allow")).toUtf8().data()); + qDebug("Checking %s", qPrintable(getPolicyFilePath(QString(".allow")))); TextFile file(getPolicyFilePath(".allow")); if (file.good()) // should have been checked via exists before, but better be safe { @@ -314,7 +338,7 @@ bool getAllowed() (allowed.compare(QString("TRUE")) == 0) ) return true; } - printf("...negative\n"); + qDebug("...negative"); return false; } diff --git a/src/util/util.h b/src/util/util.h index 6ddefc6..4f2d0ee 100644..100755 --- a/src/util/util.h +++ b/src/util/util.h @@ -4,7 +4,11 @@ #include <list> #include <fstream> #include <iostream> -#include <pwd.h> +#ifndef __WIN32__ + #include <pwd.h> +#else + /*#include "pwd_win32.h"*/ +#endif /*__WIN32*/ #include <sys/types.h> #include <sys/stat.h> diff --git a/src/version.h b/src/version.h index ac24ac2..de5c6aa 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,2 @@ -#define VERSION_STRING "2.0.1.0" -#define VERSION_NUMBER 2010 +#define VERSION_STRING "2.0.5" +#define VERSION_NUMBER 205 |
