summaryrefslogblamecommitdiffstats
path: root/src/gui/serverFileTransfert.cpp
blob: 22e268b840b8cef74e740a68757334c9ea1c2b17 (plain) (tree)








































































































































































































































































                                                                                  
/*
# 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/gui/serverFileTransfert.cpp
#	This class manage any file transfert from and to server.
# -----------------------------------------------------------------------------
*/

#include "serverFileTransfert.h"

ServerFileTransfert::ServerFileTransfert(QWidget *parent):
		QDialog(parent)
{
	setupUi(this);
	_file = NULL;
	_socket = NULL;

	connect(this, SIGNAL(finished(int)), this, SLOT(deleteLater()));
}

ServerFileTransfert::~ServerFileTransfert()
{
}

void ServerFileTransfert::sendFileToHost(QString host)
{
    QString filename = QFileDialog::getOpenFileName(this, tr("Open File"),
            QDir::homePath(), "");
    if (filename == "")
    {
        reject();
        return;
    }
    sendFileToHost(host, filename);
}

void ServerFileTransfert::sendFileToHost(QString host, QString filename)
{
    // open file
    _file = new QFile(filename);
    _file->open(QIODevice::ReadOnly);
    _bytesToWrite = _file->size();
    div = 1 + _bytesToWrite / 1000000000; // bc. progressBar supports only int

    // get host from backend

    // gui
   filenameLabel->setText(filename);
   progressBar->setValue(0);
   progressBar->setMaximum(_bytesToWrite/div);
   labelB->setText(formatSize(_bytesToWrite));
   connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));

    // open socket
    _socket = new QTcpSocket();
    _socket->connectToHost(host, 29481);
    if (_socket->isOpen())
       	qDebug("connection open");
       else
           qDebug("connection closed");
    qDebug("[%s] Remote host: %s", metaObject()->className(), qPrintable(host));

    connect(_socket, SIGNAL(connected()), this, SLOT(sendHeader()));
    connect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
    connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(error(QAbstractSocket::SocketError)));
    qDebug("connect is set");
}

void ServerFileTransfert::receiveFileFromHost(QTcpSocket* socket)
{

    _bytesToRead = 0;
    _socket = socket;

    connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveHeader()));
    connect(_socket, SIGNAL(disconnected()), this, SLOT(close()));
    connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)),
                this, SLOT(error(QAbstractSocket::SocketError)));

    qDebug("[%s] New Connection: %s", metaObject()->className(),
            qPrintable(_socket->peerAddress().toString()));
}

void ServerFileTransfert::sendHeader()
{
	qDebug("[%s] Sending header(1)...", metaObject()->className());
    QFileInfo info(_file->fileName());
    QString size = QString::number(_bytesToWrite);
    QString header = "PVSMGR;"  + info.fileName() + ";" + size  + "\n";
    _socket->write(header.toLocal8Bit());
    connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck()));
    qDebug("[%s] Sending header...", metaObject()->className());
}

void ServerFileTransfert::receiveHeader()
{
	// parse header
	QString header = QString::fromUtf8(_socket->readLine());
	QStringList args = header.split(";");
	QString nick = args[0];
	QString filename = args[1];
	_bytesToRead = args[2].toLongLong();
	div = 1 + _bytesToRead / 1000000000; // bc. progressBar supports only int

	qDebug("[%s] Received header.", metaObject()->className());

	// ask user
	QMessageBox::StandardButton result = QMessageBox::question(0,
			tr("PVS File Transfer"),tr("User '") + nick +
			tr("' would like to send you a file: ") + filename +
			" (" + formatSize(_bytesToRead) + ").",
			QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);

	if (result !=  QMessageBox::Ok)
	{
		sendAck(false);
		return;
	}

	// open file
	QString saveAs = QFileDialog::getSaveFileName(this, tr("Open File"),
			QDir::homePath() + QDir::separator() + filename, "");
	if (saveAs == "")
	{
		sendAck(false);
		return;
	}
	_file = new QFile(saveAs);
	_file->open(QIODevice::WriteOnly);

	// gui
	filenameLabel->setText(saveAs);
	progressBar->setValue(0);
	progressBar->setMaximum(_bytesToRead/div);
	labelB->setText(formatSize(_bytesToRead));
	connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));

	sendAck(true);
	show();
}

void ServerFileTransfert::sendAck(bool b)
{
	disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveHeader()));

	if (b)
	{
		QString ack = QString("ok\n");
		_socket->write(ack.toUtf8());
		qDebug("[%s] Sending ack...", metaObject()->className());
		connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveFile()));
	}
	else
	{
		QString ack = QString("no\n");
		_socket->write(ack.toUtf8());
		qDebug("[%s] Sending nack!!!", metaObject()->className());
		close();
	}
}

void ServerFileTransfert::receiveAck()
{
	QString ack = QString::fromUtf8(_socket->readLine());
	if (ack != "ok\n")
	{
		qDebug("[%s] Received nack!", metaObject()->className());
		close();
		return;
	}
    qDebug("[%s] Received ack.", metaObject()->className());

	disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck()));
	connect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile()));
	this->show();
	qDebug("[%s] Sending file...", metaObject()->className());
	sendFile();
}

void ServerFileTransfert::sendFile()
{
    if (_bytesToWrite == 0)
    {
    	qDebug("[%s] Transfer completed.", metaObject()->className());
        close(); // finished
    }
    else
    {
    	qint64 bytesWritten = _socket->write(_file->read(1024)); // data left
    	_bytesToWrite -= bytesWritten;
    	progressBar->setValue(progressBar->value() + bytesWritten/div);
    	labelA->setText(formatSize(progressBar->value()*div));
    }
}

void ServerFileTransfert::receiveFile()
{
	qint64 bytesRead = _file->write(_socket->readAll());
	_bytesToRead -= bytesRead;
	progressBar->setValue(progressBar->value() + bytesRead/div);
	labelA->setText(formatSize(progressBar->value()*div));
}

void ServerFileTransfert::close()
{
    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());
    }

    disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));

    if (_bytesToWrite == 0)
    {
    	accept();
    	QMessageBox::information(0, tr("PVS - File Transfer"),
    	        tr("File Transfer complete."));
    }
    else
    {
    	reject();
    	QMessageBox::warning(0, tr("PVS - File Transfer"),
    	        tr("File Transfer canceled!"));
    }
}

void ServerFileTransfert::error(QAbstractSocket::SocketError error)
{
    qDebug("[%s] Socket error: %i", metaObject()->className(), error);
    close();
}

QString ServerFileTransfert::formatSize(qint64 size)
{
    if (size >= 1000000000) // GB
        return QString("%1GB").arg((qreal)size / 1000000000, 0, 'f',1);
    else if (size >= 1000000) // MB
        return QString("%1MB").arg((qreal)size / 1000000, 0, 'f',1);
    else if (size >= 1000) // KB
        return QString("%1KB").arg((qreal)size / 1000, 0, 'f',1);
    else // B
        return QString("%1B").arg((qreal)size, 0, 'f',1);
}