mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Per XLS-0095, we are taking steps to rename ripple(d) to xrpl(d). C++ include guards are used to prevent the contents of a header file from being included multiple times in a single compilation unit. This change renames all `RIPPLE_` and `RIPPLED_` definitions, primarily include guards, to `XRPL_`. It also provides a script to allow developers to replicate the changes in their local branch or fork to avoid conflicts.
259 lines
7.7 KiB
C++
259 lines
7.7 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of rippled: https://github.com/ripple/rippled
|
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#ifndef XRPL_TEST_CSF_BASICNETWORK_H_INCLUDED
|
|
#define XRPL_TEST_CSF_BASICNETWORK_H_INCLUDED
|
|
|
|
#include <test/csf/Digraph.h>
|
|
#include <test/csf/Scheduler.h>
|
|
|
|
namespace ripple {
|
|
namespace test {
|
|
namespace csf {
|
|
/** Peer to peer network simulator.
|
|
|
|
The network is formed from a set of Peer objects representing
|
|
vertices and configurable connections representing edges.
|
|
The caller is responsible for creating the Peer objects ahead
|
|
of time.
|
|
|
|
Peer objects cannot be destroyed once the BasicNetwork is
|
|
constructed. To handle peers going online and offline,
|
|
callers can simply disconnect all links and reconnect them
|
|
later. Connections are directed, one end is the inbound
|
|
Peer and the other is the outbound Peer.
|
|
|
|
Peers may send messages along their connections. To simulate
|
|
the effects of latency, these messages can be delayed by a
|
|
configurable duration set when the link is established.
|
|
Messages always arrive in the order they were sent on a
|
|
particular connection.
|
|
|
|
A message is modeled using a lambda function. The caller
|
|
provides the code to execute upon delivery of the message.
|
|
If a Peer is disconnected, all messages pending delivery
|
|
at either end of the connection will not be delivered.
|
|
|
|
When creating the Peer set, the caller needs to provide a
|
|
Scheduler object for managing the timing and delivery
|
|
of messages. After constructing the network, and establishing
|
|
connections, the caller uses the scheduler's step_* functions
|
|
to drive messages through the network.
|
|
|
|
The graph of peers and connections is internally represented
|
|
using Digraph<Peer,BasicNetwork::link_type>. Clients have
|
|
const access to that graph to perform additional operations not
|
|
directly provided by BasicNetwork.
|
|
|
|
Peer Requirements:
|
|
|
|
Peer should be a lightweight type, cheap to copy
|
|
and/or move. A good candidate is a simple pointer to
|
|
the underlying user defined type in the simulation.
|
|
|
|
Expression Type Requirements
|
|
---------- ---- ------------
|
|
P Peer
|
|
u, v Values of type P
|
|
P u(v) CopyConstructible
|
|
u.~P() Destructible
|
|
u == v bool EqualityComparable
|
|
u < v bool LessThanComparable
|
|
std::hash<P> class std::hash is defined for P
|
|
! u bool true if u is not-a-peer
|
|
|
|
*/
|
|
template <class Peer>
|
|
class BasicNetwork
|
|
{
|
|
using peer_type = Peer;
|
|
|
|
using clock_type = Scheduler::clock_type;
|
|
|
|
using duration = typename clock_type::duration;
|
|
|
|
using time_point = typename clock_type::time_point;
|
|
|
|
struct link_type
|
|
{
|
|
bool inbound = false;
|
|
duration delay{};
|
|
time_point established{};
|
|
link_type() = default;
|
|
link_type(bool inbound_, duration delay_, time_point established_)
|
|
: inbound(inbound_), delay(delay_), established(established_)
|
|
{
|
|
}
|
|
};
|
|
|
|
Scheduler& scheduler;
|
|
Digraph<Peer, link_type> links_;
|
|
|
|
public:
|
|
BasicNetwork(BasicNetwork const&) = delete;
|
|
BasicNetwork&
|
|
operator=(BasicNetwork const&) = delete;
|
|
|
|
BasicNetwork(Scheduler& s);
|
|
|
|
/** Connect two peers.
|
|
|
|
The link is directed, with `from` establishing
|
|
the outbound connection and `to` receiving the
|
|
incoming connection.
|
|
|
|
Preconditions:
|
|
|
|
from != to (self connect disallowed).
|
|
|
|
A link between from and to does not
|
|
already exist (duplicates disallowed).
|
|
|
|
Effects:
|
|
|
|
Creates a link between from and to.
|
|
|
|
@param `from` The source of the outgoing connection
|
|
@param `to` The recipient of the incoming connection
|
|
@param `delay` The time delay of all delivered messages
|
|
@return `true` if a new connection was established
|
|
*/
|
|
bool
|
|
connect(
|
|
Peer const& from,
|
|
Peer const& to,
|
|
duration const& delay = std::chrono::seconds{0});
|
|
|
|
/** Break a link.
|
|
|
|
Effects:
|
|
|
|
If a connection is present, both ends are
|
|
disconnected.
|
|
|
|
Any pending messages on the connection
|
|
are discarded.
|
|
|
|
@return `true` if a connection was broken.
|
|
*/
|
|
bool
|
|
disconnect(Peer const& peer1, Peer const& peer2);
|
|
|
|
/** Send a message to a peer.
|
|
|
|
Preconditions:
|
|
|
|
A link exists between from and to.
|
|
|
|
Effects:
|
|
|
|
If the link is not broken when the
|
|
link's `delay` time has elapsed,
|
|
the function will be invoked with
|
|
no arguments.
|
|
|
|
@note Its the caller's responsibility to
|
|
ensure that the body of the function performs
|
|
activity consistent with `from`'s receipt of
|
|
a message from `to`.
|
|
*/
|
|
template <class Function>
|
|
void
|
|
send(Peer const& from, Peer const& to, Function&& f);
|
|
|
|
/** Return the range of active links.
|
|
|
|
@return A random access range over Digraph::Edge instances
|
|
*/
|
|
auto
|
|
links(Peer const& from)
|
|
{
|
|
return links_.outEdges(from);
|
|
}
|
|
|
|
/** Return the underlying digraph
|
|
*/
|
|
Digraph<Peer, link_type> const&
|
|
graph() const
|
|
{
|
|
return links_;
|
|
}
|
|
};
|
|
//------------------------------------------------------------------------------
|
|
template <class Peer>
|
|
BasicNetwork<Peer>::BasicNetwork(Scheduler& s) : scheduler(s)
|
|
{
|
|
}
|
|
|
|
template <class Peer>
|
|
inline bool
|
|
BasicNetwork<Peer>::connect(
|
|
Peer const& from,
|
|
Peer const& to,
|
|
duration const& delay)
|
|
{
|
|
if (to == from)
|
|
return false;
|
|
time_point const now = scheduler.now();
|
|
if (!links_.connect(from, to, link_type{false, delay, now}))
|
|
return false;
|
|
auto const result = links_.connect(to, from, link_type{true, delay, now});
|
|
(void)result;
|
|
assert(result);
|
|
return true;
|
|
}
|
|
|
|
template <class Peer>
|
|
inline bool
|
|
BasicNetwork<Peer>::disconnect(Peer const& peer1, Peer const& peer2)
|
|
{
|
|
if (!links_.disconnect(peer1, peer2))
|
|
return false;
|
|
bool r = links_.disconnect(peer2, peer1);
|
|
(void)r;
|
|
assert(r);
|
|
return true;
|
|
}
|
|
|
|
template <class Peer>
|
|
template <class Function>
|
|
inline void
|
|
BasicNetwork<Peer>::send(Peer const& from, Peer const& to, Function&& f)
|
|
{
|
|
auto link = links_.edge(from, to);
|
|
if (!link)
|
|
return;
|
|
time_point const sent = scheduler.now();
|
|
scheduler.in(
|
|
link->delay, [from, to, sent, f = std::forward<Function>(f), this] {
|
|
// only process if still connected and connection was
|
|
// not broken since the message was sent
|
|
if (auto l = links_.edge(from, to); l && l->established <= sent)
|
|
{
|
|
f();
|
|
}
|
|
});
|
|
}
|
|
|
|
} // namespace csf
|
|
} // namespace test
|
|
} // namespace ripple
|
|
|
|
#endif
|