Skip to content

Commit

Permalink
get() retransmit implemented.
Browse files Browse the repository at this point in the history
  • Loading branch information
romixlab committed Sep 14, 2015
1 parent bc47d89 commit 1c32624
Show file tree
Hide file tree
Showing 15 changed files with 226 additions and 53 deletions.
2 changes: 2 additions & 0 deletions .qmake.conf
@@ -0,0 +1,2 @@
TOP_SRCDIR=$$PWD
TOP_BUILDDIR=$$shadowed($$PWD)
6 changes: 3 additions & 3 deletions examples/client/client.pro
Expand Up @@ -11,10 +11,10 @@ TARGET = client
CONFIG += console
CONFIG -= app_bundle
QMAKE_CXXFLAGS += -std=c++11
DESTDIR = $$PWD/../../bin
DESTDIR = $$TOP_SRCDIR/bin

LIBS += -L"$$PWD/../../lib" -lqcoap
INCLUDEPATH += $$PWD/../../src/lib
LIBS += -L"$$TOP_SRCDIR/bin" -lqcoap
INCLUDEPATH += $$TOP_SRCDIR/src/lib

TEMPLATE = app

Expand Down
14 changes: 8 additions & 6 deletions examples/client/main.cpp
Expand Up @@ -63,21 +63,23 @@ void add()
{
CoapExchange *exchange = new CoapExchange;
CoapUri uri;
uri.setHost(QHostAddress("134.102.218.16"));
uri.setHost(QHostAddress("127.0.0.1"));
uri.setPort(5683);
uri.setPath("test");
uri.setPath("hello");
exchange->setUri(uri);
exchange->onCompleted([](){qDebug() << "Lambda!";});
exchange->onCompleted([=](){qDebug() << "Answer:" << exchange->answer();});
exchange->onError([](){qDebug() << "Timeout";});
exchange->get();
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

// CoapEndpoint endpoint(CoapEndpoint::ClientServer);
CoapTimerQueue q;
// endpoint.bind(QHostAddress::Any, 5683);
CoapEndpoint endpoint(CoapEndpoint::ClientServer);
endpoint.bind(QHostAddress::Any, 5688);

add();

// add();
// endpoint.bind(QHostAddress::LocalHost);
Expand Down
2 changes: 2 additions & 0 deletions src/lib/coapendpoint_p.h
Expand Up @@ -5,6 +5,7 @@
#include <QHostAddress>

#include "coapendpoint.h"
#include "coaptimerqueue.h"

class QUdpSocket;
class CoapExchange;
Expand Down Expand Up @@ -37,6 +38,7 @@ class CoapEndpointPrivate
CoapEndpoint *q_ptr;
quint16 currentMessageId;
CoapEndpoint::Type type;
CoapTimerQueue timerQueue;

QHash<QByteArray, CoapExchange *> token2exchange; // on pdu rx used to find exchange
QHash<CoapExchange *, QByteArray> exchange2token; // on pdu tx used to find token
Expand Down
51 changes: 30 additions & 21 deletions src/lib/coapexchange.cpp
Expand Up @@ -6,12 +6,7 @@
#include "coapendpoint_p.h"

CoapExchangePrivate::CoapExchangePrivate()
: flags(Flags(0)), timeout(10000)
{
}

CoapExchangePrivate::CoapExchangePrivate(const CoapExchangePrivate &other) :
QSharedData(other)
: flags(Flags(0))
{
}

Expand Down Expand Up @@ -43,38 +38,30 @@ void CoapExchangePrivate::incoming_pdu(const CoapPDU &pdu)
qDebug() << "Observed:" << pdu.payload();
} else {
status = CoapExchange::Completed;
endpoint->d_ptr->timerQueue.removeTimers(q);
if (on_completed)
on_completed();
q->deleteLater();
}
}

CoapExchange::CoapExchange() :
d(new CoapExchangePrivate)

CoapExchange::CoapExchange(QObject *parent) :
QObject(parent), d(new CoapExchangePrivate)
{
d->q = this;
d->endpoint = Coap::defaultEndpoint();
d->status = Invalid;
}

CoapExchange::CoapExchange(CoapEndpoint *throughEndpoint) :
d(new CoapExchangePrivate)
CoapExchange::CoapExchange(CoapEndpoint *throughEndpoint, QObject *parent) :
QObject(parent), d(new CoapExchangePrivate)
{
d->q = this;
d->endpoint = throughEndpoint;
d->status = Invalid;
}

CoapExchange::CoapExchange(const CoapExchange &other) :
d(other.d)
{
}

CoapExchange &CoapExchange::operator =(const CoapExchange &other)
{
d = other.d;
return *this;
}

CoapExchange::~CoapExchange()
{
d->endpoint->d_ptr->remove_exchange(this);
Expand Down Expand Up @@ -105,6 +92,23 @@ void CoapExchange::get()
pdu.setType(Coap::Type::CONFIRMABLE);
d->pdus.push_back(pdu);
d->endpoint->d_ptr->send_pdu(this, pdu);
d->retransmitCount = 0;
d->endpoint->d_ptr->timerQueue.addTimer(2000, this, "timeout");
}

void CoapExchange::timeout()
{
if (++d->retransmitCount == 4) {
if (d->on_error)
d->on_error();
deleteLater();
return;
}
d->endpoint->d_ptr->send_pdu(this, d->pdus[0]);
quint32 nextRetransmission = 1000 * (1 << d->retransmitCount);
nextRetransmission += rand() % 100;
qDebug() << "next retransmission in" << nextRetransmission;
d->endpoint->d_ptr->timerQueue.addTimer(nextRetransmission, this, "timeout");
}

void CoapExchange::observe()
Expand Down Expand Up @@ -157,3 +161,8 @@ void CoapExchange::onCompleted(std::function<void ()> lambda)
{
d->on_completed = lambda;
}

void CoapExchange::onError(std::function<void ()> lambda)
{
d->on_error = lambda;
}
22 changes: 13 additions & 9 deletions src/lib/coapexchange.h
Expand Up @@ -3,8 +3,6 @@

#include <functional>

#include <QExplicitlySharedDataPointer>

#include "coaplib_global.h"
#include "coapuri.h"

Expand All @@ -17,11 +15,12 @@ class CoapPDU;
/**
* @brief The CoapExchange class
*/
class CoapExchange
class CoapExchange : public QObject
{
Q_OBJECT
public:
CoapExchange();
CoapExchange(CoapEndpoint *throughEndpoint);
CoapExchange(QObject *parent = 0);
CoapExchange(CoapEndpoint *throughEndpoint, QObject *parent = 0);

~CoapExchange();

Expand Down Expand Up @@ -78,14 +77,19 @@ class CoapExchange
* @param lambda called when status is changed to Completed
*/
void onCompleted(std::function<void ()> lambda);
void onError(std::function<void ()> lambda);

private slots:
void timeout();

friend class CoapEndpoint;
friend class CoapEndpointPrivate;
friend class CoapTimerQueue;
private:
CoapExchange(const CoapExchange &other);
CoapExchange &operator =(const CoapExchange &other);
QExplicitlySharedDataPointer<CoapExchangePrivate> d;
CoapExchangePrivate *d;

friend class CoapEndpoint;
friend class CoapEndpointPrivate;
friend class CoapTimerQueue;
};

#endif // COAPEXCHANGE_H
8 changes: 3 additions & 5 deletions src/lib/coapexchange_p.h
Expand Up @@ -3,18 +3,15 @@

#include <functional>

#include <QSharedData>

#include "coapexchange.h"
#include "coapuri.h"
#include "coappdu.h"

class CoapEndpoint;
class CoapExchangePrivate : public QSharedData
class CoapExchangePrivate
{
public:
CoapExchangePrivate();
CoapExchangePrivate(const CoapExchangePrivate &other);
~CoapExchangePrivate();

void incoming_pdu(const CoapPDU &pdu);
Expand All @@ -24,15 +21,16 @@ class CoapExchangePrivate : public QSharedData
CoapExchange::Status status;
CoapUri uri;
QVector<CoapPDU> pdus;
quint8 retransmitCount = 0;

enum Flag {
Observe = 1,
};
Q_DECLARE_FLAGS(Flags, Flag)
Flags flags;

quint32 timeout;
std::function<void ()> on_completed;
std::function<void ()> on_error;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(CoapExchangePrivate::Flags)
Expand Down
22 changes: 16 additions & 6 deletions src/lib/coaptimerqueue.cpp
Expand Up @@ -6,20 +6,20 @@

typedef struct {
QDateTime dt;
quint8 id;
QObject *object;
const char *method;
} coap_timer_t;

class CoapTimerQueuePrivate {
public:
QBasicTimer timer;
QList<coap_timer_t> queue;
quint32 delta;
};

CoapTimerQueue::CoapTimerQueue(QObject *parent) :
QObject(parent), d(new CoapTimerQueuePrivate)
{
d->delta = 100;

}

CoapTimerQueue::~CoapTimerQueue()
Expand All @@ -30,7 +30,7 @@ CoapTimerQueue::~CoapTimerQueue()
}
}

void CoapTimerQueue::addTimer(quint32 msec, quint8 id)
void CoapTimerQueue::addTimer(quint32 msec, QObject *receiver, const char *method)
{
QDateTime dt = QDateTime::currentDateTime().addMSecs(msec);
int idx = 0;
Expand All @@ -40,15 +40,25 @@ void CoapTimerQueue::addTimer(quint32 msec, quint8 id)
if (idx == d->queue.size() - 1)
idx += 1; // after last one
}
coap_timer_t timer{dt, id};
coap_timer_t timer{dt, receiver, method};
d->queue.insert(idx, timer);
if (idx == 0)
d->timer.start(msec, this);
}

void CoapTimerQueue::removeTimers(QObject *receiver)
{
for (int i = 0; i < d->queue.size(); ++i)
if (d->queue[i].object == receiver)
d->queue[i].object = 0;
}

void CoapTimerQueue::timerEvent(QTimerEvent *e)
{
qDebug() << "timeout" << d->queue.front().id;
Q_UNUSED(e);
coap_timer_t &timer = d->queue.front();
if (timer.object)
QMetaObject::invokeMethod(timer.object, timer.method);
d->timer.stop();
d->queue.pop_front();
if (!d->queue.isEmpty()) {
Expand Down
5 changes: 4 additions & 1 deletion src/lib/coaptimerqueue.h
@@ -1,6 +1,8 @@
#ifndef COAPTIMERQUEUE_H
#define COAPTIMERQUEUE_H

#include <functional>

#include <QObject>

class CoapTimerQueuePrivate;
Expand All @@ -16,7 +18,8 @@ class CoapTimerQueue : public QObject
* @brief addTimer adds timer with msec timeout after current time
* @param msec
*/
void addTimer(quint32 msec, quint8 id);
void addTimer(quint32 msec, QObject *receiver, const char *method);
void removeTimers(QObject *receiver);

signals:

Expand Down
4 changes: 2 additions & 2 deletions src/lib/lib.pro
Expand Up @@ -4,8 +4,8 @@ QT -= gui
TARGET = qcoap
TEMPLATE = lib
DEFINES += MAKE_COAPLIB
QMAKE_CXXFLAGS += -std=c++11
DESTDIR = $$PWD/../../lib
CONFIG += c++11
DESTDIR = $$TOP_SRCDIR/bin

SOURCES += \
coap.cpp \
Expand Down
21 changes: 21 additions & 0 deletions tests/complex/complex.pro
@@ -0,0 +1,21 @@
#-------------------------------------------------
#
# Project created by QtCreator 2015-09-12T18:25:16
#
#-------------------------------------------------

QT += core

QT -= gui

TARGET = complex
CONFIG += console
CONFIG -= app_bundle
CONFIG += c++11

TEMPLATE = app

INCLUDEPATH += $$TOP_SRCDIR/src/lib
LIBS += -L"$$TOP_SRCDIR/bin" -lqcoap

SOURCES += main.cpp

0 comments on commit 1c32624

Please sign in to comment.