Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

remoteIOdevice <- QIODevice

  • Loading branch information...
commit c733733e5c03fc92bb2227d48f023e6d546d072c 1 parent ee46fa1
@RJ authored
View
14 src/library/library.cpp
@@ -76,6 +76,20 @@ void Library::addDir( const QString& url, int mtime)
query.exec();
}
+QVariantMap Library::file(int fid)
+{
+ QVariantMap m;
+ query.exec(QString("SELECT url, size FROM file WHERE id = ?").arg(fid));
+ if(query.next())
+ {
+ QString url = query.value(0).toString();
+ int size= query.value(2).toInt();
+ m["url"] = url;
+ m["size"] = size;
+ }
+ return m;
+}
+
int Library::addFile( QVariantMap m )
{
View
1  src/library/library.h
@@ -41,6 +41,7 @@ class Library : public QObject
QVariantMap artist(int id);
QVariantMap album(int id);
QVariantMap track(int id);
+ QVariantMap file(int fid);
public slots:
int addFile( QVariantMap m );
View
15 src/remotecollection.cpp
@@ -1,5 +1,5 @@
#include "remotecollection.h"
-//#include "httpd.h"
+#include "remoteioconnection.h"
RemoteCollection::RemoteCollection(Servent * s, RemoteCollectionConnection * conn) :
QDaap::Collection(conn->name(), conn), m_servent(s), m_rcconn(conn)
@@ -43,3 +43,16 @@ QList<QDaap::Track> RemoteCollection::loadTracks()
qDebug() << "all tracks received";
return m_tmp_tracks;
}
+
+QIODevice * RemoteCollection::getTrack(quint32 id)
+{
+ if(!m_tracks.contains(id))
+ {
+ return 0;
+ //Q_ASSERT(false);
+ }
+ QDaap::Track t = m_tracks[id];
+ RemoteIOConnection * ioc = new RemoteIOConnection(t.id, m_servent);
+ m_servent->createParallelConnection(m_rcconn->cc(), ioc, QString("FILE_REQUEST_KEY:%1").arg(id));
+ return ioc->iodevice();
+};
View
94 src/remotecollection.h
@@ -10,7 +10,11 @@
#include "library/library.h"
#include "conjist.h"
#include "httpd.h"
+
+#include "remotecollectionconnection.h"
+
class RemoteCollectionConnection;
+
class RemoteCollection : public QDaap::Collection
{
Q_OBJECT
@@ -35,6 +39,9 @@ public slots:
int port() const { return m_port; };
+ QIODevice * getTrack(quint32 id);
+
+
private:
Servent * m_servent;
RemoteCollectionConnection * m_rcconn;
@@ -51,93 +58,6 @@ public slots:
-class RemoteCollectionConnection : public Connection
-{
- Q_OBJECT
-public:
- RemoteCollectionConnection(Library * lib, Servent * s = 0 )
- : Connection(s), m_library(lib)
- {
- qDebug() << "CTOR " << id();
- };
-
- ~RemoteCollectionConnection()
- {
- qDebug() << "DTOR " << id();
- };
-
- QString id() const { return "RemoteCollectionConnection::" + name(); };
-
- Connection * clone() { Q_ASSERT(false); return 0; };
-
- void setup()
- {
- m_rc = new RemoteCollection(m_servent, this);
- };
-
- RemoteCollection * remoteCollection() const { return m_rc; };
-
- void handleMsg(QByteArray msg)
- {
- if(msg == "ALLTRACKSREQUEST")
- {
- // send all tracks
- QVariantList /*QList<QVariantMap>*/ all = m_library->allTracks();
- qDebug() << "Sending our library of " << all.length() << " tracks...";
-
- QVariantMap response;
- response["method"] = "alltracks";
- response["tracks"] = all;
-
- QJson::Serializer serializer;
- const QByteArray serialized = serializer.serialize( response );
- sendMsg(serialized);
- return;
- }
-
- bool ok;
- QVariantMap m = parser.parse(msg, &ok).toMap();
- if(ok)
- {
- if(m.value("method").toString() == "alltracks")
- {
- QList<QDaap::Track> tracks;
-
- QList<QVariant> all = m.value("tracks").toList();
- foreach(QVariant v, all)
- {
- QVariantMap m = v.toMap();
- QDaap::Track t;
- t.perid = t.id = m.value("id").toInt();
- t.genre = m.value("genre").toString();
- t.artist = m.value("artist").toString();
- t.album = m.value("album").toString();
- t.track = m.value("track").toString();
- t.comment = m.value("comment").toString();
- t.extension = m.value("extension").toString();
- t.bitrate = m.value("bitrate").toInt();
- t.duration = m.value("duration").toInt() * 1000;
- t.filesize = m.value("filesize").toInt();
- t.year = m.value("year").toInt();
- t.albumdiscnumber = m.value("albumdiscnumber").toInt();
- t.albumposition = m.value("albumposition").toInt();
- tracks.append(t);
- }
- emit allTracks(tracks);
- return;
- }
- }
-
- qDebug() << "UNHANDLED msg in rcc: " << QString::fromAscii(msg);
- };
-
-signals:
- void allTracks(QList<QDaap::Track>);
-private:
- Library * m_library;
- QJson::Parser parser;
- RemoteCollection * m_rc;
-};
View
7 src/remotecollectionconnection.cpp
@@ -0,0 +1,7 @@
+#include "remotecollectionconnection.h"
+
+
+void RemoteCollectionConnection::setup()
+{
+ m_rc = new RemoteCollection(m_servent, this);
+}
View
98 src/remotecollectionconnection.h
@@ -0,0 +1,98 @@
+#ifndef REMOTECOLLECTIONCONNECTION_H
+#define REMOTECOLLECTIONCONNECTION_H
+#include "connection.h"
+#include "remotecollection.h"
+#include "library/library.h"
+#include "remotecollection.h"
+
+class RemoteCollection;
+
+class RemoteCollectionConnection : public Connection
+{
+ Q_OBJECT
+public:
+ RemoteCollectionConnection(Library * lib, ControlConnection * cc, Servent * s = 0 )
+ : Connection(s), m_library(lib), m_cc(cc)
+ {
+ qDebug() << "CTOR " << id();
+ };
+
+ ~RemoteCollectionConnection()
+ {
+ qDebug() << "DTOR " << id();
+ };
+
+ QString id() const { return "RemoteCollectionConnection::" + name(); };
+
+ Connection * clone() { Q_ASSERT(false); return 0; };
+
+ void setup();
+
+ RemoteCollection * remoteCollection() const { return m_rc; };
+
+ void handleMsg(QByteArray msg)
+ {
+ if(msg == "ALLTRACKSREQUEST")
+ {
+ // send all tracks
+ QVariantList /*QList<QVariantMap>*/ all = m_library->allTracks();
+ qDebug() << "Sending our library of " << all.length() << " tracks...";
+
+ QVariantMap response;
+ response["method"] = "alltracks";
+ response["tracks"] = all;
+
+ QJson::Serializer serializer;
+ const QByteArray serialized = serializer.serialize( response );
+ sendMsg(serialized);
+ return;
+ }
+
+ bool ok;
+ QVariantMap m = parser.parse(msg, &ok).toMap();
+ if(ok)
+ {
+ if(m.value("method").toString() == "alltracks")
+ {
+ QList<QDaap::Track> tracks;
+
+ QList<QVariant> all = m.value("tracks").toList();
+ foreach(QVariant v, all)
+ {
+ QVariantMap m = v.toMap();
+ QDaap::Track t;
+ t.perid = t.id = m.value("id").toInt();
+ t.genre = m.value("genre").toString();
+ t.artist = m.value("artist").toString();
+ t.album = m.value("album").toString();
+ t.track = m.value("track").toString();
+ t.comment = m.value("comment").toString();
+ t.extension = m.value("extension").toString();
+ t.bitrate = m.value("bitrate").toInt();
+ t.duration = m.value("duration").toInt() * 1000;
+ t.filesize = m.value("filesize").toInt();
+ t.year = m.value("year").toInt();
+ t.albumdiscnumber = m.value("albumdiscnumber").toInt();
+ t.albumposition = m.value("albumposition").toInt();
+ tracks.append(t);
+ }
+ emit allTracks(tracks);
+ return;
+ }
+ }
+
+ qDebug() << "UNHANDLED msg in rcc: " << QString::fromAscii(msg);
+ };
+
+ ControlConnection * cc() const { return m_cc; };
+
+signals:
+ void allTracks(QList<QDaap::Track>);
+private:
+ Library * m_library;
+ QJson::Parser parser;
+ RemoteCollection * m_rc;
+ ControlConnection * m_cc;
+};
+
+#endif // REMOTECOLLECTIONCONNECTION_H
View
3  src/remoteioconnection.cpp
@@ -0,0 +1,3 @@
+#include "remoteioconnection.h"
+
+
View
154 src/remoteioconnection.h
@@ -0,0 +1,154 @@
+#ifndef REMOTEIOCONNECTION_H
+#define REMOTEIOCONNECTION_H
+
+#include <QIODevice>
+#include <QMutex>
+#include <QWaitCondition>
+#include <QDebug>
+#include "controlconnection.h"
+#include "library/library.h"
+#include "conjist.h"
+
+class RemoteIODevice : public QIODevice
+{
+ Q_OBJECT
+public:
+
+ RemoteIODevice() :
+ m_eof(false), m_headers(false), m_filesize(0)
+ {};
+
+ // abuse this to only block until headers are available:
+ bool waitForReadyRead ( int msecs )
+ {
+ if(!m_headers) m_wait.wait(&m_mut);
+ return true;
+ }
+
+ qint64 size () const
+ {
+ return m_filesize;
+ };
+
+ qint64 readData ( char * data, qint64 maxSize )
+ {
+ m_mut_recv.lock();
+ if(m_eof && m_buffer.length() == 0) return 0;
+ if(!m_buffer.length())
+ {
+ m_mut_recv.unlock();
+ m_wait.wait(&m_mut);
+ m_mut_recv.lock();
+ }
+ int len;
+ if(maxSize>=m_buffer.length()) // whole buffer
+ {
+ len = m_buffer.length();
+ memcpy(data, m_buffer.constData(), len);
+ m_buffer.clear();
+ } else { // partial
+ len = maxSize;
+ memcpy(data, m_buffer.constData(), len);
+ m_buffer.remove(0,len);
+ }
+ m_mut_recv.unlock();
+ return len;
+ };
+
+ qint64 writeData ( const char * data, qint64 maxSize )
+ {
+ Q_ASSERT(false);
+ return 0;
+ };
+
+ void addData(QByteArray msg)
+ {
+ m_mut_recv.lock();
+ if(msg.length()==0) m_eof=true;
+ else
+ {
+ if(!m_headers)
+ {
+ m_filesize = QString::fromAscii(msg).toInt();
+ m_headers = true;
+ qDebug() << "RemIODev, filesize: " << m_filesize;
+ }
+ else m_buffer.append(msg);
+ }
+ m_mut_recv.unlock();
+ m_wait.wakeAll();
+ qDebug() << "just read: " << msg.length();
+ //emit QIODevice::readyRead();
+ }
+
+private:
+ QByteArray m_buffer;
+ QMutex m_mut, m_mut_recv;
+ QWaitCondition m_wait;
+ bool m_eof, m_headers;
+ int m_filesize;
+};
+
+class RemoteIOConnection : public Connection
+{
+ Q_OBJECT
+public:
+ RemoteIOConnection(int fid, Servent * s)
+ : Connection(s), m_fid(fid), m_servent(s)
+ {
+ //setName(QString("%1[%2]").arg(conn->name()).arg(fid));
+ m_dev = new RemoteIODevice();
+ qDebug() << "CTOR " << id();
+ };
+
+ ~RemoteIOConnection()
+ {
+ qDebug() << "DTOR " << id();
+ };
+
+ RemoteIODevice * iodevice() { return m_dev; };
+
+ void setup()
+ {
+ if(m_fid)
+ {
+ qDebug() << "We are the sender, for fid " << m_fid;
+ Library * lib = ((conjist*)QCoreApplication::instance())->library();
+ QVariantMap t = lib->file(m_fid);
+ Q_ASSERT(!t.isEmpty()); // TODO
+ QString url = t.value("url").toString();
+ qDebug() << "Opening " << url;
+ QFile f(url);
+ f.open(QIODevice::ReadOnly);
+ sendMsg(QString("%1").arg(f.size()).toAscii());
+ char buf[4096];
+ int i=0;
+ while((i=f.read((char*)&buf, 4096))>0)
+ {
+ sendMsg(QByteArray((char*)&buf, i));
+ }
+ }
+ else
+ {
+ qDebug() << "We are the receiver";
+ }
+
+ };
+
+ void handleMsg(QByteArray msg)
+ {
+ Q_ASSERT(m_fid == 0); // only one end sends!
+ m_dev->addData(msg);
+ };
+
+
+ Connection * clone() { Q_ASSERT(false); return 0; };
+
+private:
+ int m_fid;
+ Servent * m_servent;
+ RemoteIODevice * m_dev;
+
+};
+
+#endif // REMOTEIOCONNECTION_H
View
32 src/servent.cpp
@@ -2,8 +2,8 @@
#include "controlconnection.h"
#include "proxylistener.h"
#include "proxyconnection.h"
-
#include "remotecollection.h"
+#include "remoteioconnection.h"
// TODO auth timeout check
@@ -49,7 +49,7 @@ void Servent::registerControlConnection(ControlConnection * conn)
qDebug() << "Sending invite for library sharing...";
QString key = uuid();
Library * lib = ((conjist*)QCoreApplication::instance())->library();
- RemoteCollectionConnection * rcconn = new RemoteCollectionConnection(lib, this);
+ RemoteCollectionConnection * rcconn = new RemoteCollectionConnection(lib, conn, this);
rcconn->setName(conn->name());
connect(rcconn, SIGNAL(ready()), this, SLOT(advertiseCollection()));
connect(rcconn, SIGNAL(finished()), rcconn, SLOT(deleteLater()));
@@ -134,19 +134,29 @@ void Servent::readyRead()
// the connected to us and want something we are offering
if(conntype == "accept-offer" || "push-offer")
{
- if(!m_offers.contains(key))
+ Connection * conn;
+ if(key.startsWith("FILE_REQUEST_KEY:"))
+ {
+ int fid = key.right(key.length()-17).toInt();
+ qDebug() << "Got a request for fid: " << fid;
+ conn = new RemoteIOConnection(fid, this);
+ }
+ else if(!m_offers.contains(key))
{
qDebug() << "Invalid offer key on new connection";
goto closeconnection;
}
- Connection * conn = m_offers[key];
- if(conn->onceOnly())
+ else
{
- // just use this object
- m_offers.remove(key);
- } else {
- // use a copy, leave original there - offer can be reused.
- conn = conn->clone();
+ conn = m_offers[key];
+ if(conn->onceOnly())
+ {
+ // just use this object
+ m_offers.remove(key);
+ } else {
+ // use a copy, leave original there - offer can be reused.
+ conn = conn->clone();
+ }
}
//conn->setName("Incoming-"+key);
conn->setPeerPort(pport);
@@ -341,7 +351,7 @@ void Servent::createRemoteCollection(ControlConnection * conn, QString key, QStr
qDebug() << "Accepting an offer of a library from remote peer";
Library * lib = ((conjist*)QCoreApplication::instance())->library();
- RemoteCollectionConnection * rcconn = new RemoteCollectionConnection(lib, this);
+ RemoteCollectionConnection * rcconn = new RemoteCollectionConnection(lib, conn, this);
rcconn->setName(conn->name());
connect(rcconn, SIGNAL(ready()), this, SLOT(advertiseCollection()));
connect(rcconn, SIGNAL(finished()), rcconn, SLOT(deleteLater()));
View
11 src/src.pro
@@ -20,13 +20,16 @@ HEADERS += servent.h \
zeroconf/bonjourserviceresolver.h \
library/library.h \
library/scanner.h \
- collection.h \
+ collection.h \ #qdaap
+ httpd.h \ #qdaap
conjist.h \
jabberclient.h \
portfwd.h \
getopt_helper.h \
cjuuid.h \
- remotecollection.h
+ remotecollection.h \
+ remotecollectionconnection.h \
+ remoteioconnection.h
SOURCES += servent.cpp \
connection.cpp \
main.cpp \
@@ -43,7 +46,9 @@ SOURCES += servent.cpp \
jabberclient.cpp \
portfwd.cpp \
getopt_helper.cpp \
- remotecollection.cpp
+ remotecollection.cpp \
+ remotecollectionconnection.cpp \
+ remoteioconnection.cpp
LIBPATH += ../qxmpp/
LIBPATH += ../miniupnp/
LIBPATH += ../qdaapd/
Please sign in to comment.
Something went wrong with that request. Please try again.