[telepathy-qt4/master] IncomingFileTransferChannel: Added specialized class for incoming file transfer channels.
Andre Moreira Magalhaes (andrunko)
andre.magalhaes at collabora.co.uk
Wed Sep 16 18:50:40 PDT 2009
---
TelepathyQt4/IncomingFileTransferChannel | 13 +
TelepathyQt4/incoming-file-transfer-channel.cpp | 266 +++++++++++++++++++++++
TelepathyQt4/incoming-file-transfer-channel.h | 75 +++++++
3 files changed, 354 insertions(+), 0 deletions(-)
create mode 100644 TelepathyQt4/IncomingFileTransferChannel
create mode 100644 TelepathyQt4/incoming-file-transfer-channel.cpp
create mode 100644 TelepathyQt4/incoming-file-transfer-channel.h
diff --git a/TelepathyQt4/IncomingFileTransferChannel b/TelepathyQt4/IncomingFileTransferChannel
new file mode 100644
index 0000000..4392d3e
--- /dev/null
+++ b/TelepathyQt4/IncomingFileTransferChannel
@@ -0,0 +1,13 @@
+#ifndef _TelepathyQt4_IncomingFileTransferChannel_HEADER_GUARD_
+#define _TelepathyQt4_IncomingFileTransferChannel_HEADER_GUARD_
+
+#ifndef IN_TELEPATHY_QT4_HEADER
+#define IN_TELEPATHY_QT4_HEADER
+#endif
+
+#include <TelepathyQt4/incoming-file-transfer-channel.h>
+
+#undef IN_TELEPATHY_QT4_HEADER
+
+#endif
+// vim:set ft=cpp:
diff --git a/TelepathyQt4/incoming-file-transfer-channel.cpp b/TelepathyQt4/incoming-file-transfer-channel.cpp
new file mode 100644
index 0000000..8eda25c
--- /dev/null
+++ b/TelepathyQt4/incoming-file-transfer-channel.cpp
@@ -0,0 +1,266 @@
+/*
+ * This file is part of TelepathyQt4
+ *
+ * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <TelepathyQt4/IncomingFileTransferChannel>
+
+#include "TelepathyQt4/_gen/incoming-file-transfer-channel.moc.hpp"
+
+#include "TelepathyQt4/debug-internal.h"
+
+#include <TelepathyQt4/Connection>
+#include <TelepathyQt4/PendingFailure>
+#include <TelepathyQt4/PendingVariant>
+#include <TelepathyQt4/Types>
+
+#include <QIODevice>
+#include <QTcpSocket>
+
+namespace Tp
+{
+
+struct IncomingFileTransferChannel::Private
+{
+ Private(IncomingFileTransferChannel *parent);
+ ~Private();
+
+ // Public object
+ IncomingFileTransferChannel *parent;
+
+ QIODevice *output;
+ QTcpSocket *socket;
+ SocketAddressIPv4 addr;
+};
+
+IncomingFileTransferChannel::Private::Private(IncomingFileTransferChannel *parent)
+ : parent(parent),
+ output(0),
+ socket(0)
+{
+}
+
+IncomingFileTransferChannel::Private::~Private()
+{
+}
+
+/**
+ * \class IncomingFileTransferChannel
+ * \ingroup clientchannel
+ * \headerfile <TelepathyQt4/incoming-file-transfer-channel.h> <TelepathyQt4/IncomingFileTransferChannel>
+ *
+ * High-level proxy object for accessing remote %Channel objects of the
+ * FileTransfer channel type. These channels can be used to transfer one file
+ * to or from a contact.
+ *
+ * This subclass of Channel will eventually provide a high-level API for the
+ * FileTransfer interface. Until then, it's just a Channel.
+ */
+
+const Feature IncomingFileTransferChannel::FeatureCore = Feature(IncomingFileTransferChannel::staticMetaObject.className(), 0);
+
+IncomingFileTransferChannelPtr IncomingFileTransferChannel::create(
+ const ConnectionPtr &connection, const QString &objectPath,
+ const QVariantMap &immutableProperties)
+{
+ return IncomingFileTransferChannelPtr(new IncomingFileTransferChannel(
+ connection, objectPath, immutableProperties));
+}
+
+/**
+ * Creates a IncomingFileTransferChannel associated with the given object on
+ * the same service as the given connection.
+ *
+ * \param connection Connection owning this IncomingFileTransferChannel,
+ * and specifying the service.
+ * \param objectPath Path to the object on the service.
+ * \param immutableProperties The immutable properties of the channel, as
+ * signalled by NewChannels or returned by
+ * CreateChannel or EnsureChannel
+ */
+IncomingFileTransferChannel::IncomingFileTransferChannel(
+ const ConnectionPtr &connection, const QString &objectPath,
+ const QVariantMap &immutableProperties)
+ : FileTransferChannel(connection, objectPath, immutableProperties),
+ mPriv(new Private(this))
+{
+}
+
+/**
+ * Class destructor.
+ */
+IncomingFileTransferChannel::~IncomingFileTransferChannel()
+{
+ delete mPriv;
+}
+
+/**
+ * Accept a file transfer that's in the %FileTransferStatePending state().
+ * The state will change to %FileTransferStateOpen as soon as the transfer
+ * starts.
+ * The given output device should not be closed/destroyed until the state()
+ * changes to %FileTransferStateCompleted or %FileTransferStateCancelled.
+ *
+ * \param offset The desired offset in bytes where the file transfer should
+ * start. The offset is taken from the beginning of the file.
+ * Specifying an offset of zero will start the transfer from the
+ * beginning of the file. The offset that is actually given in the
+ * initialOffset() method can differ from this argument where the
+ * requested offset is not supported. (For example, some
+ * protocols do not support offsets at all so the initialOffset()
+ * will always be 0.).
+ * \param output A QIODevice object where the data will be written to. The
+ * device should be ready to use when the state() changes to
+ * %FileTransferStateCompleted.
+ * If the transfer is cancelled, state() becomes
+ * %FileTransferStateCancelled, the data in \a output should be
+ * ignored
+ * \return A PendingOperation object which will emit PendingOperation::finished
+ * when the call has finished.
+ * \sa stateChanged(), state(), stateReason(), initialOffset()
+ */
+PendingOperation *IncomingFileTransferChannel::acceptFile(qulonglong offset,
+ QIODevice *output)
+{
+ // let's fail here direclty as we may only have one device to handle
+ if (mPriv->output) {
+ warning() << "File transfer can only be started once in the same "
+ "channel";
+ return new PendingFailure(this, TELEPATHY_ERROR_NOT_AVAILABLE,
+ "File transfer can only be started once in the same channel");
+ }
+
+ if ((!output->isOpen() && !output->open(QIODevice::WriteOnly)) &&
+ (!output->isWritable())) {
+ warning() << "Unable to open IO device for writing";
+ return new PendingFailure(this, TELEPATHY_ERROR_PERMISSION_DENIED,
+ "Unable to open IO device for writing");
+ }
+
+ mPriv->output = output;
+
+ PendingVariant *pv = new PendingVariant(
+ fileTransferInterface(BypassInterfaceCheck)->AcceptFile(SocketAddressTypeIPv4,
+ SocketAccessControlLocalhost, QDBusVariant(QVariant(QString())),
+ offset),
+ this);
+ connect(pv,
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(onAcceptFileFinished(Tp::PendingOperation*)));
+ return pv;
+}
+
+void IncomingFileTransferChannel::onAcceptFileFinished(PendingOperation *op)
+{
+ if (op->isError()) {
+ warning() << "Error accepting file transfer " <<
+ op->errorName() << ":" << op->errorMessage();
+ return;
+ }
+
+ PendingVariant *pv = qobject_cast<PendingVariant *>(op);
+ mPriv->addr = qdbus_cast<SocketAddressIPv4>(pv->result());
+ debug().nospace() << "Got address " << mPriv->addr.address <<
+ ":" << mPriv->addr.port;
+
+ if (state() == FileTransferStateOpen) {
+ // now we have the address and we are already opened,
+ // connect to host
+ connectToHost();
+ }
+}
+
+void IncomingFileTransferChannel::connectToHost()
+{
+ if (isConnected() || mPriv->addr.address.isNull()) {
+ return;
+ }
+
+ mPriv->socket = new QTcpSocket(this);
+
+ connect(mPriv->socket, SIGNAL(connected()),
+ SLOT(onSocketConnected()));
+ connect(mPriv->socket, SIGNAL(disconnected()),
+ SLOT(onSocketDisconnected()));
+ connect(mPriv->socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ SLOT(onSocketError(QAbstractSocket::SocketError)));
+ connect(mPriv->socket, SIGNAL(readyRead()),
+ SLOT(doTransfer()));
+
+ debug().nospace() << "Connecting to host " <<
+ mPriv->addr.address << ":" << mPriv->addr.port << "...";
+ mPriv->socket->connectToHost(mPriv->addr.address, mPriv->addr.port);
+}
+
+void IncomingFileTransferChannel::onSocketConnected()
+{
+ debug() << "Connected to host!";
+ setConnected();
+
+ doTransfer();
+}
+
+void IncomingFileTransferChannel::onSocketDisconnected()
+{
+ debug() << "Disconnected from host!";
+ setFinished();
+}
+
+void IncomingFileTransferChannel::onSocketError(QAbstractSocket::SocketError error)
+{
+ debug() << "Socket error" << error;
+ setFinished();
+}
+
+void IncomingFileTransferChannel::doTransfer()
+{
+ QByteArray data;
+ while (mPriv->socket->bytesAvailable()) {
+ data = mPriv->socket->readAll();
+ mPriv->output->write(data); // never fails
+ }
+}
+
+void IncomingFileTransferChannel::setFinished()
+{
+ if (isFinished()) {
+ // it shouldn't happen but let's make sure
+ return;
+ }
+
+ if (mPriv->socket) {
+ disconnect(mPriv->socket, SIGNAL(connected()),
+ this, SLOT(onSocketConnected()));
+ disconnect(mPriv->socket, SIGNAL(disconnected()),
+ this, SLOT(onSocketDisconnected()));
+ disconnect(mPriv->socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(onSocketError(QAbstractSocket::SocketError)));
+ disconnect(mPriv->socket, SIGNAL(readyRead()),
+ this, SLOT(doTransfer()));
+ mPriv->socket->close();
+ }
+
+ if (mPriv->output) {
+ mPriv->output->close();
+ }
+
+ FileTransferChannel::setFinished();
+}
+
+} // Tp
diff --git a/TelepathyQt4/incoming-file-transfer-channel.h b/TelepathyQt4/incoming-file-transfer-channel.h
new file mode 100644
index 0000000..c293dc9
--- /dev/null
+++ b/TelepathyQt4/incoming-file-transfer-channel.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of TelepathyQt4
+ *
+ * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _TelepathyQt4_incoming_file_transfer_channel_h_HEADER_GUARD_
+#define _TelepathyQt4_incoming_file_transfer_channel_h_HEADER_GUARD_
+
+#ifndef IN_TELEPATHY_QT4_HEADER
+#error IN_TELEPATHY_QT4_HEADER
+#endif
+
+#include <TelepathyQt4/FileTransferChannel>
+
+#include <QAbstractSocket>
+
+namespace Tp
+{
+
+class IncomingFileTransferChannel : public FileTransferChannel
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(IncomingFileTransferChannel)
+
+public:
+ static const Feature FeatureCore;
+
+ static IncomingFileTransferChannelPtr create(const ConnectionPtr &connection,
+ const QString &objectPath, const QVariantMap &immutableProperties);
+
+ virtual ~IncomingFileTransferChannel();
+
+ PendingOperation *acceptFile(qulonglong offset, QIODevice *output);
+
+protected:
+ IncomingFileTransferChannel(const ConnectionPtr &connection,
+ const QString &objectPath,
+ const QVariantMap &immutableProperties);
+
+private Q_SLOTS:
+ void onAcceptFileFinished(Tp::PendingOperation *op);
+
+ void onSocketConnected();
+ void onSocketDisconnected();
+ void onSocketError(QAbstractSocket::SocketError error);
+ void doTransfer();
+
+private:
+ void connectToHost();
+ void setFinished();
+
+ struct Private;
+ friend struct Private;
+ Private *mPriv;
+};
+
+} // Tp
+
+#endif
--
1.5.6.5
More information about the telepathy-commits
mailing list