Files
opendht/include/opendht/request.h
T
Simon Désaulniers faf23195a4 dht: standardize announce status check
Fixes a bug where some callbacks wouldn't be called when a dummy request was
inserted to cancel some operation while not using the
net::Request::State::COMPLETED flag as per 19c47ec.
2017-02-16 16:29:21 -05:00

141 lines
4.6 KiB
C++

/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "net.h"
namespace dht {
namespace net {
class NetworkEngine;
struct ParsedMessage;
/*!
* @class Socket
* @brief Open route to a node for continous incoming packets.
* @details
* A socket lets a remote node send us continuous packets treated using a
* given callback. This is intended to provide an easy management of
* specific updates nodes can send. For e.g, this is used in the case of the
* "listen" operation for treating updates a node has for a given storage.
*/
struct Socket {
Socket() {}
Socket(std::shared_ptr<Node> node,
TransId id,
std::function<void(const std::shared_ptr<Node>&, ParsedMessage&&)> on_receive) :
node(node), id(id), on_receive(on_receive) {}
std::shared_ptr<Node> node;
TransId id;
std::function<void(const std::shared_ptr<Node>&, ParsedMessage&&)> on_receive {};
};
/*!
* @class Request
* @brief An atomic request destined to a node.
* @details
* A request contains data used by the NetworkEngine to process a request
* desitned to specific node and std::function callbacks to execute when the
* request is done.
*/
struct Request {
friend class dht::net::NetworkEngine;
std::shared_ptr<Node> node {}; /* the node to whom the request is destined. */
time_point reply_time {time_point::min()}; /* time when we received the response to the request. */
enum class State
{
PENDING,
CANCELLED,
EXPIRED,
COMPLETED
};
bool expired() const { return state_ == State::EXPIRED; }
bool completed() const { return state_ == State::COMPLETED; }
bool cancelled() const { return state_ == State::CANCELLED; }
bool pending() const { return state_ == State::PENDING; }
bool over() const { return not pending(); }
State getState() const { return state_; }
Request(State state = State::PENDING) : state_(state) {}
Request(TransId tid,
std::shared_ptr<Node> node,
Blob&& msg,
std::function<void(const Request&, ParsedMessage&&)> on_done,
std::function<void(const Request&, bool)> on_expired,
std::shared_ptr<Socket> socket = {}) :
node(node), on_done(on_done), on_expired(on_expired), tid(tid), msg(std::move(msg)), socket(socket) { }
void setExpired() {
if (pending()) {
state_ = Request::State::EXPIRED;
on_expired(*this, true);
clear();
}
}
void setDone(ParsedMessage&& msg) {
if (pending()) {
state_ = Request::State::COMPLETED;
on_done(*this, std::forward<ParsedMessage>(msg));
clear();
}
}
void cancel() {
if (pending()) {
state_ = State::CANCELLED;
clear();
}
}
private:
static const constexpr size_t MAX_ATTEMPT_COUNT {3};
bool isExpired(time_point now) const {
return pending() and now > last_try + Node::MAX_RESPONSE_TIME and attempt_count >= Request::MAX_ATTEMPT_COUNT;
}
void clear() {
on_done = {};
on_expired = {};
msg.clear();
}
State state_ {State::PENDING};
unsigned attempt_count {0}; /* number of attempt to process the request. */
time_point start {time_point::min()}; /* time when the request is created. */
time_point last_try {time_point::min()}; /* time of the last attempt to process the request. */
std::function<void(const Request&, ParsedMessage&&)> on_done {};
std::function<void(const Request&, bool)> on_expired {};
const TransId tid; /* the request id. */
Blob msg {}; /* the serialized message. */
std::shared_ptr<Socket> socket; /* the socket used for further reponses. */
};
} /* namespace net */
}