/* # 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 #include #include #include #include #include #include #include #include #include #include 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 portlimit = settings.value("multicast/port-limit", "7966").value(); 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; }