Skip to content

Commit

Permalink
jingle-ft: Make file sending working
Browse files Browse the repository at this point in the history
  • Loading branch information
Ri0n committed May 15, 2019
1 parent f3408e4 commit 3df933f
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 4 deletions.
64 changes: 60 additions & 4 deletions src/xmpp/xmpp-im/jingle-ft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,18 +385,51 @@ class Application::Private
QSharedPointer<Pad> pad;
QString contentName;
File file;
File acceptFile; // as it comes with "accept" response
Origin creator;
Origin senders;
QSharedPointer<Transport> transport;
Connection::Ptr connection;
QStringList availableTransports;
bool transportFailed = false;
QIODevice *device = nullptr;
quint64 bytesLeft = 0;

void setState(State s)
{
state = s;
emit q->stateChanged(s);
}

void writeNextBlockToTransport()
{
if (!bytesLeft) {
return; // everything is written
}
auto sz = transport->blockSize();
sz = sz? sz : 8192;
if (sz > bytesLeft) {
sz = bytesLeft;
}
QByteArray data = device->read(sz);
if (data.isEmpty()) {
// TODO d->lastError = Condition::FailedApplication
connection.reset();
setState(State::Finished);
return;
}
if (connection->write(data) == -1) {
// TODO d->lastError = Condition::FailedApplication
connection.reset();
setState(State::Finished);
return;
}
}

void readNextBlockFromTransport()
{
// TODO
}
};

Application::Application(const QSharedPointer<Pad> &pad, const QString &contentName, Origin creator, Origin senders) :
Expand Down Expand Up @@ -479,13 +512,25 @@ bool Application::setTransport(const QSharedPointer<Transport> &transport)
connect(transport.data(), &Transport::updated, this, &Application::updated);
connect(transport.data(), &Transport::connected, this, [this](){
d->connection = d->transport->connection();
if (d->acceptFile.range().isValid()) {
d->bytesLeft = d->acceptFile.range().length;
emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft);
} else {
d->bytesLeft = d->file.size();
emit deviceRequested(0, d->bytesLeft);
}
connect(d->connection.data(), &Connection::readyRead, this, [this](){
// TODO read data
if (!d->device) {
return;
}
if (d->pad->session()->role() != d->senders) {
d->readNextBlockFromTransport();
}
});
connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes){
if (d->pad->session()->role() == d->senders) {
// write next port of data

Q_UNUSED(bytes)
if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) {
d->writeNextBlockToTransport();
}
});
d->setState(State::Active);
Expand Down Expand Up @@ -646,6 +691,7 @@ bool Application::accept(const QDomElement &el)
if (!f.isValid()) {
return false;
}
d->acceptFile = f;
// TODO validate if accept file matches to the offer
setState(State::Accepted);
return true;
Expand All @@ -657,6 +703,16 @@ bool Application::isValid() const
(d->senders == Origin::Initiator || d->senders == Origin::Responder);
}

void Application::setDevice(QIODevice *dev)
{
d->device = dev;
if (d->senders == d->pad->session()->role()) {
d->writeNextBlockToTransport();
} else {
d->readNextBlockFromTransport();
}
}

Pad::Pad(Manager *manager, Session *session) :
_manager(manager),
_session(session)
Expand Down
4 changes: 4 additions & 0 deletions src/xmpp/xmpp-im/jingle-ft.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ class Application : public XMPP::Jingle::Application

bool isValid() const;

void setDevice(QIODevice *dev);

signals:
void deviceRequested(quint64 offset, quint64 size);

private:
class Private;
Expand Down
16 changes: 16 additions & 0 deletions src/xmpp/xmpp-im/jingle-s5b.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class Connection : public XMPP::Jingle::Connection
mode(mode)
{
connect(client, &SocksClient::readyRead, this, &Connection::readyRead);
connect(client, &SocksClient::bytesWritten, this, &Connection::bytesWritten);
connect(client, &SocksClient::aboutToClose, this, &Connection::aboutToClose);
if (client->isOpen()) {
setOpenMode(client->openMode());
} else {
Expand Down Expand Up @@ -404,6 +406,7 @@ class Transport::Private
Transport::Mode mode = Transport::Tcp;
QTimer probingTimer;
QElapsedTimer lastConnectionStart;
size_t blockSize = 8129;

QSharedPointer<Connection> connection;

Expand Down Expand Up @@ -845,6 +848,13 @@ bool Transport::update(const QDomElement &transportEl)
{
// we can just on type of elements in transport-info
// so return as soon as any type handled. Though it leaves a room for remote to send invalid transport-info
auto bs = transportEl.attribute(QString::fromLatin1("block-size"));
if (!bs.isEmpty()) {
size_t bsn = bs.toULongLong();
if (bsn && bsn <= d->blockSize) {
d->blockSize = bsn;
}
}
QString candidateTag(QStringLiteral("candidate"));
int candidatesAdded = 0;
for(QDomElement ce = transportEl.firstChildElement(candidateTag);
Expand Down Expand Up @@ -967,6 +977,7 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate()
if (d->meCreator && d->mode != Tcp) {
tel.setAttribute(QStringLiteral("mode"), "udp");
}
tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(d->blockSize));

if (d->pendingActions & Private::NewCandidate) {
d->pendingActions &= ~Private::NewCandidate;
Expand Down Expand Up @@ -1091,6 +1102,11 @@ Connection::Ptr Transport::connection() const
return d->connection.staticCast<XMPP::Jingle::Connection>();
}

size_t Transport::blockSize() const
{
return d->blockSize;
}

bool Transport::incomingConnection(SocksClient *sc)
{
if (!d->connection) {
Expand Down
1 change: 1 addition & 0 deletions src/xmpp/xmpp-im/jingle-s5b.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class Transport : public XMPP::Jingle::Transport

QString sid() const;
Connection::Ptr connection() const;
size_t blockSize() const;
private:
friend class S5BServer;
bool incomingConnection(SocksClient *sc);
Expand Down
1 change: 1 addition & 0 deletions src/xmpp/xmpp-im/jingle.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ class Transport : public QObject {
virtual Features features() const = 0;
virtual TransportManagerPad::Ptr pad() const = 0;
virtual Connection::Ptr connection() const = 0; // returns established QIODevice-based connection
virtual size_t blockSize() const = 0;
signals:
void updated(); // found some candidates and they have to be sent. takeUpdate has to be called from this signal handler.
// if it's just always ready then signal has to be sent at least once otherwise session-initiate won't be sent.
Expand Down

0 comments on commit 3df933f

Please sign in to comment.