summaryrefslogtreecommitdiffstats
path: root/src/net/pvsOutgoingMulticastTransfer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/pvsOutgoingMulticastTransfer.cpp')
-rw-r--r--src/net/pvsOutgoingMulticastTransfer.cpp209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/net/pvsOutgoingMulticastTransfer.cpp b/src/net/pvsOutgoingMulticastTransfer.cpp
new file mode 100644
index 0000000..2f24d49
--- /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.baseName()).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;
+}