Add PeerFinder peer discovery logic and unit test

This commit is contained in:
Vinnie Falco
2013-09-11 11:37:03 -07:00
parent 45eccf2ccf
commit 27f0cae812
11 changed files with 625 additions and 8 deletions

View File

@@ -784,13 +784,19 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\ripple_core.cpp" />
<ClCompile Include="..\..\src\ripple_core\test\TestOverlay.cpp">
<ClCompile Include="..\..\modules\ripple_core\test\TestOverlay.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\peerfinder\ripple_PeerFinder.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\ripple_core.cpp" />
<ClCompile Include="..\..\src\ripple_core\validator\ValidatorSourceFile.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -1512,6 +1518,7 @@
<ClInclude Include="..\..\src\ripple_core\node\NodeObject.h" />
<ClInclude Include="..\..\src\ripple_core\node\NodeStore.h" />
<ClInclude Include="..\..\src\ripple_core\node\NullBackendFactory.h" />
<ClInclude Include="..\..\src\ripple_core\peerfinder\ripple_PeerFinder.h" />
<ClInclude Include="..\..\src\ripple_core\ripple_core.h" />
<ClInclude Include="..\..\src\ripple_core\test\ConnectionType.h" />
<ClInclude Include="..\..\src\ripple_core\test\InitPolicy.h" />

View File

@@ -154,6 +154,9 @@
<Filter Include="[2] doc">
<UniqueIdentifier>{c69b07a2-44e5-4b06-99a9-81f5d137ea15}</UniqueIdentifier>
</Filter>
<Filter Include="[1] Ripple\ripple_core\peerfinder">
<UniqueIdentifier>{d1648d3f-7d71-495d-afc9-576ed00d7185}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ripple_basics\containers\ripple_RangeSet.cpp">
@@ -219,9 +222,6 @@
<ClCompile Include="..\..\src\ripple_core\functional\ripple_LoadMonitor.cpp">
<Filter>[1] Ripple\ripple_core\functional</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\ripple_core.cpp">
<Filter>[1] Ripple\ripple_core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_data\crypto\ripple_Base58.cpp">
<Filter>[1] Ripple\ripple_data\crypto</Filter>
</ClCompile>
@@ -840,9 +840,6 @@
<ClCompile Include="..\..\src\ripple_core\validator\Validators.cpp">
<Filter>[1] Ripple\ripple_core\validator</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\test\TestOverlay.cpp">
<Filter>[1] Ripple\ripple_core\test</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\validator\ValidatorsUtilities.cpp">
<Filter>[1] Ripple\ripple_core\validator</Filter>
</ClCompile>
@@ -876,6 +873,13 @@
<ClCompile Include="..\..\src\beast\modules\beast_sqlite\beast_sqlite.c">
<Filter>[0] src\beast</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\ripple_core\test\TestOverlay.cpp" />
<ClCompile Include="..\..\src\ripple_core\ripple_core.cpp">
<Filter>[1] Ripple\ripple_core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\peerfinder\ripple_PeerFinder.cpp">
<Filter>[1] Ripple\ripple_core\peerfinder</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ripple_app\ripple_app.h">
@@ -1728,6 +1732,9 @@
<Filter>[1] Ripple\ripple_core\validator</Filter>
</ClInclude>
<ClInclude Include="..\..\src\BeastConfig.h" />
<ClInclude Include="..\..\src\ripple_core\peerfinder\ripple_PeerFinder.h">
<Filter>[1] Ripple\ripple_core\peerfinder</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\ripple_data\protocol\ripple.proto">

View File

@@ -173,4 +173,12 @@
#define RIPPLE_APPLICATION_CLEAN_EXIT 0
#endif
// This is only here temporarily. Use it to turn off the sending of
// "ANNOUNCE" messages if you suspect that you're having problems
// because of it.
#ifndef RIPPLE_USE_MT_ANNOUNCE
#define RIPPLE_USE_MT_ANNOUNCE 0
#endif
#endif

View File

@@ -17,6 +17,7 @@ class ApplicationImp
, public SharedSingleton <ApplicationImp>
, public NodeStore::Scheduler
, LeakChecked <ApplicationImp>
, PeerFinder::Callback
{
public:
// RAII container for a boost::asio::io_service run by beast threads
@@ -175,6 +176,7 @@ public:
, mUNL (UniqueNodeList::New ())
, mProofOfWorkFactory (ProofOfWorkFactory::New ())
, m_loadManager (LoadManager::New ())
, mPeerFinder (PeerFinder::New (*this))
// VFALCO End new stuff
// VFALCO TODO replace all NULL with nullptr
, mRpcDB (NULL)
@@ -366,6 +368,11 @@ public:
return *m_peers;
}
PeerFinder& getPeerFinder ()
{
return *mPeerFinder;
}
// VFALCO TODO Move these to the .cpp
bool running ()
{
@@ -698,6 +705,8 @@ private:
void startNewLedger ();
bool loadOldLedger (const std::string&, bool);
void onAnnounceAddress ();
private:
Application::LockType mMasterLock;
@@ -735,6 +744,7 @@ private:
ScopedPointer <PeerDoor> m_peerProxyDoor;
ScopedPointer <WSDoor> m_wsPublicDoor;
ScopedPointer <WSDoor> m_wsPrivateDoor;
ScopedPointer <PeerFinder> mPeerFinder;
// VFALCO End Clean stuff
DatabaseCon* mRpcDB;
@@ -1189,6 +1199,11 @@ void ApplicationImp::updateTables ()
}
}
void ApplicationImp::onAnnounceAddress ()
{
// NIKB CODEME
}
//------------------------------------------------------------------------------
Application& getApp ()

View File

@@ -28,6 +28,7 @@ class SerializedLedgerEntry;
class TransactionMaster;
class TxQueue;
class LocalCredentials;
class PeerFinder;
class DatabaseCon;
@@ -95,6 +96,7 @@ public:
virtual TransactionMaster& getMasterTransaction () = 0;
virtual TxQueue& getTxQueue () = 0;
virtual LocalCredentials& getLocalCredentials () = 0;
virtual PeerFinder& getPeerFinder () = 0;
virtual DatabaseCon* getRpcDB () = 0;
virtual DatabaseCon* getTxnDB () = 0;

View File

@@ -335,6 +335,7 @@ private:
void sendPacketForce (const PackedMessage::pointer & packet);
void sendHello ();
void SendAnnounce ();
void recvHello (protocol::TMHello & packet);
void recvCluster (protocol::TMCluster & packet);
@@ -345,6 +346,7 @@ private:
void recvGetContacts (protocol::TMGetContacts & packet);
void recvGetPeers (protocol::TMGetPeers & packet, Application::ScopedLockType& masterLockHolder);
void recvPeers (protocol::TMPeers & packet);
void recvAnnounce (protocol::TMAnnounce & packet);
void recvGetObjectByHash (const boost::shared_ptr<protocol::TMGetObjectByHash>& packet);
void recvPing (protocol::TMPing & packet);
void recvErrorMessage (protocol::TMErrorMsg & packet);
@@ -834,6 +836,17 @@ void PeerImp::processReadBuffer ()
}
break;
case protocol::mtANNOUNCE:
{
event->reName ("PeerImp::announce");
protocol::TMAnnounce msg;
if(msg.ParseFromArray (&mReadbuf[PackedMessage::kHeaderBytes], mReadbuf.size() - PackedMessage::kHeaderBytes))
recvAnnounce (msg);
else
WriteLog (lsWARNING, Peer) << "parse error: " << type;;
}
case protocol::mtSEARCH_TRANSACTION:
{
event->reName ("PeerImp::searchtransaction");
@@ -1606,6 +1619,15 @@ void PeerImp::recvPeers (protocol::TMPeers& packet)
}
}
void PeerImp::recvAnnounce (protocol::TMAnnounce& packet)
{
// NIKB TODO: First we need to push this announcement to peerfinder
// and then this is not a private peer, we need to "adjust" this
// announcement (i.e. the hop count) and push it out to all our
// other peers. We must be careful to avoid cycles (that is to
// never send an ANNOUNCE back to the peer we got it from).
}
void PeerImp::recvGetObjectByHash (const boost::shared_ptr<protocol::TMGetObjectByHash>& ptr)
{
protocol::TMGetObjectByHash& packet = *ptr;
@@ -2362,6 +2384,32 @@ void PeerImp::sendHello ()
sendPacket (packet, true);
}
void PeerImp::SendAnnounce ()
{
protocol::TMAnnounce a;
std::string selfID = getApp().getLocalCredentials ().getNodePublic ().humanNodePublic ();
a.set_serverid(selfID);
// Since we are announcing ourselves, the hopcount is one and the "via" peer is us.
// If hopcount is anything else, the "via" peer must be different from the "serverid".
a.set_viapeerid(selfID);
a.set_hopcount(1); // A direct connection
// Announce whether we're a private peer or not. Should we even send an ANNOUNCE
// for private peers?
a.set_privatepeer(getConfig ().PEER_PRIVATE);
protocol::TMIPv4EndPoint *ep = a.add_connectpoints();
ep->set_ipv4(inet_addr (getNativeSocket ().local_endpoint ().address ().to_string ().c_str()));
ep->set_ipv4port(getConfig ().peerListeningPort);
PackedMessage::pointer packet = boost::make_shared<PackedMessage> (a, protocol::mtANNOUNCE);
sendPacket (packet, true);
}
void PeerImp::sendGetPeers ()
{
// Ask peer for known other peers.

View File

@@ -0,0 +1,369 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
/*
PeerFinder
----------
Implements the logic for announcing and discovering IP addresses for
for connecting into the Ripple network.
Introduction
------------
Each Peer (a computer running rippled) on the Ripple network requires a certain
number of connections to other peers. These connections form an "overlay
network." When a new peer wants to join the network, they need a robust source
of network addresses (IP adresses) in order to establish outgoing connections.
Once they have joined the network, they need a method of announcing their
availaibility of accepting incoming connections.
The Ripple network, like all peer to peer networks, defines a "directed graph"
where each node represents a computer running the rippled software, and each
vertex indicates a network connection. The direction of the connection tells
us whether it is an outbound or inbound connection (from the perspective of
a particular node).
Fact #1:
The total inbound and outbound connections of any overlay must be equal.
This follows that for each node that has an established outbound connection,
there must exist another node that has received the corresponding inbound
connection.
When a new peer joins the network it may or may not wish to receive inbound
connections. Some peers are unable to accept incoming connections for various.
For security reasons they may be behind a firewall that blocks accept requests.
The administers may decide they don't want the connection traffic. Or they
may wish to connect only to specific peers. Or they may simply be misconfigured.
If a peer decides that it wishes to receive incoming connections, it needs
a method to announce its IP address and port number, the features that it
offers (for example, that it also services client requests), and the number
of available connection slots. This is to handle the case where the peer
reaches its desired number of peer connections, but may still want to inform
the network that it will service clients. It may also be desired to indicate
the number of free client slots.
Pong
----
Once a peer is connected to the network we need a way both to inform our
neighbors of our status with respect to accepting connections, and also to
learn about new fresh addresses to connect to. For this we will define the "Pong"
message.
"Connection Strategy"
---------------------
This is the overall strategy a peer uses to maintain its position in the Ripple
network graph
We define these values:
PeerCount (calculated)
The number of currently connected and established peers
OutCount (calculated)
The number of peers in PeerCount that are outbound connections.
MinOutCount (hard-coded constant)
The minimum number of OutCount we want. This also puts a floor
on PeerCount. This protects against sybil attacks and makes
sure that ledgers can get retrieved reliably.
10 is the proposed value.
MaxPeerCount (a constant set in the rippled.cfg)
The maximum number of peer connections, inbound or outbound,
that a peer wishes to maintain. Setting MaxPeerCount equal to
or below MinOutCount would disallow incoming connections.
OutDesiredPercent (a baked-in program constant for now)
The peer's target value for OutCount. When the value of OutCount
is below this number, the peer will employ the Outgoing Strategy
to raise its value of OutCount. This value is initially a constant
in the program, defined by the developers. However, it
may be changed through the consensus process.
15% is a proposed value.
However, lets consider the case where OutDesired is exactly equal to MaxPeerCount / 2.
In this case, a stable state will be reached when every peer is full, and
has exactly the same number of inbound and outbound connections. The problem
here is that there are now no available incoming connection slots. No new
peers can enter the network.
Lets consider the case where OutDesired is exactly equal to (MaxPeerCount / 2) - 1.
The stable state for this network (assuming all peers can accept incoming) will
leave us with network degree equal to MaxPeerCount - 2, with all peers having two
available incoming connection slots. The global number of incoming connection slots
will be equal to twice the number of nodes on the network. While this might seem to
be a desirable outcome, note that the connectedness (degree of the overlay) plays
a large part in determining the levels of traffic and ability to receive validations
from desired nodes. Having every node with available incoming connections also
means that entries in pong caches will continually fall out with new values and
information will become less useful.
For this reason, we advise that the value of OutDesired be fractional. Upon startup,
a node will use its node ID (its 160 bit unique ID) to decide whether to round the
value of OutDesired up or down. Using this method, we can precisely control the
global number of available incoming connection slots.
"Outgoing Strategy"
-------------------
This is the method a peer uses to establish outgoing connections into the
Ripple network.
A peer whose PeerCount is zero will use these steps:
1. Attempt addresses from a local database of addresses
2. Attempt addresses from a set of "well known" domains in rippled.cfg
This is the method used by a peer that is already connected to the Ripple network,
to adjust the number of outgoing connections it is maintaining.
"Incoming Strategy"
------------------------------
This is the method used by a peer to announce its ability and desire to receive
incoming connections both for the purpose of obtaining additional peer connections
and also for receiving requests from clients.
Terms
Overlay Network
http://en.wikipedia.org/wiki/Overlay_network
Directed Graph
http://en.wikipedia.org/wiki/Directed_graph
References:
Gnutella 0.6 Protocol
2.2.2 Ping (0x00)
2.2.3 Pong (0x01)
2.2.4 Use of Ping and Pong messages
2.2.4.1 A simple pong caching scheme
2.2.4.2 Other pong caching schemes
http://rfc-gnutella.sourceforge.net/src/rfc-0_6-draft.html
Revised Gnutella Ping Pong Scheme
By Christopher Rohrs and Vincent Falco
http://rfc-gnutella.sourceforge.net/src/pong-caching.html
*/
//------------------------------------------------------------------------------
class PeerFinderImp
: public PeerFinder
, private ThreadWithCallQueue::EntryPoints
, private DeadlineTimer::Listener
, LeakChecked <PeerFinderImp>
{
public:
// Tunable constants
enum
{
// How often our timer goes off to consult outside sources for IPs
secondsPerUpdate = 1 * 60 * 60, // once per hour
// How often we announce our IP
secondsPerBroadcast = 5 * 60,
// The minimum number of peers we want
numberOfPeersMinimum = 4,
numberOfPeersMaximum = 10,
// The minimum number of seconds a connection ought to be sustained
// before we consider it "stable"
secondsForStability = 60, // one minute
};
//--------------------------------------------------------------------------
/** The Logic for maintaining the list of Peer addresses.
We keep this in a separate class so it can be instantiated
for unit tests.
*/
class Logic
{
Callback &m_callback;
public:
explicit Logic (Callback& callback)
: m_callback (callback)
{
}
// Called on the PeerFinder thread
void onUpdateConnectionsStatus (
Connections const& connections)
{
if (connections.numberTotal () < numberOfPeersMinimum)
{
// do something
}
else
{
// do something?
}
}
void onPeerConnected (
const PeerId& id)
{
}
void onPeerDisconnected (
const PeerId& id)
{
}
void onAcceptTimer()
{
m_callback.onAnnounceAddress ();
}
};
//--------------------------------------------------------------------------
public:
explicit PeerFinderImp (Callback& callback)
: m_logic (callback)
, m_thread ("PeerFinder")
, m_acceptTimer (this)
, m_updateTimer (this)
{
m_thread.start (this);
}
~PeerFinderImp ()
{
}
void updateConnectionsStatus (Connections& connections)
{
// Queue the call to the logic
m_thread.call (&Logic::onUpdateConnectionsStatus,
&m_logic, connections);
}
void onPeerConnected(const PeerId& id)
{
m_thread.call (&Logic::onPeerConnected,
&m_logic, id);
}
void onPeerDisconnected(const PeerId& id)
{
m_thread.call (&Logic::onPeerDisconnected,
&m_logic, id);
}
//--------------------------------------------------------------------------
void onAcceptTimer ()
{
#if 0
static int x = 0;
if(x == 0)
Debug::breakPoint ();
x++;
#endif
}
void onDeadlineTimer (DeadlineTimer& timer)
{
// This will make us fall into the idle proc as needed
//
if (timer == m_updateTimer)
m_thread.interrupt ();
else if (timer == m_acceptTimer)
m_thread.call (&Logic::onAcceptTimer, &m_logic);
}
void threadInit ()
{
m_updateTimer.setRecurringExpiration (secondsPerUpdate);
m_acceptTimer.setRecurringExpiration (secondsPerBroadcast);
}
void threadExit ()
{
}
bool threadIdle ()
{
bool interrupted = false;
// This is where you can go into a loop and do stuff
// like process the lists, and what not. Just be
// sure to call:
//
// @code
// interrupted = interruptionPoint ();
// @encode
//
// From time to time. If it returns true then you
// need to exit this function so that Thread can
// process its asynchronous call queue and then come
// back into threadIdle()
return interrupted;
}
private:
Logic m_logic;
ThreadWithCallQueue m_thread;
DeadlineTimer m_acceptTimer;
DeadlineTimer m_updateTimer;
};
//------------------------------------------------------------------------------
PeerFinder* PeerFinder::New (PeerFinder::Callback& callback)
{
return new PeerFinderImp (callback);
}
//------------------------------------------------------------------------------
class PeerFinderTests : public UnitTest,
public PeerFinder::Callback
{
public:
void testValidityChecks ()
{
beginTestCase ("ip validation");
fail ("there's no code!");
}
void runTest ()
{
PeerFinderImp::Logic logic (*this);
beginTestCase ("logic");
logic.onAcceptTimer ();
}
void onAnnounceAddress ()
{
}
PeerFinderTests () : UnitTest ("PeerFinder", "ripple", runManual)
{
}
};
static PeerFinderTests peerFinderTests;

View File

@@ -0,0 +1,145 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
#ifndef RIPPLE_PEERFINDER_H_INCLUDED
#define RIPPLE_PEERFINDER_H_INCLUDED
/** The identifier we use to track peers in peerfinder
*/
typedef uint160 PeerId;
/** Maintains a set of IP addresses used for getting into the network.
*/
class PeerFinder : public Uncopyable
{
public:
//--------------------------------------------------------------------------
/** Describes the state of our currently connected peers
*/
struct Connections
{
int numberIncoming; // number of inbound Peers
int numberOutgoing; // number of outbound Peers
inline int numberTotal () const noexcept
{
return numberIncoming + numberOutgoing;
}
};
//--------------------------------------------------------------------------
/** An abstract address that can be turned into a socket endpoint.
*/
struct Address
{
virtual String asString () = 0;
};
/** An IPv4 address.
*/
struct AddressIPv4 : Address
{
AddressIPv4 (InputParser::IPv4Address const& address, uint16 port)
: m_address (address)
, m_port (port)
{
}
String asString ()
{
return String () +
String (m_address.value [0]) + "." +
String (m_address.value [1]) + "." +
String (m_address.value [2]) + "." +
String (m_address.value [3]) + ":" +
String (m_port);
}
private:
InputParser::IPv4Address m_address;
uint16 m_port;
};
//--------------------------------------------------------------------------
/** The Callback receives Peerfinder notifications.
The notifications are sent on a thread owned by the PeerFinder,
so it is best not to do too much work in here. Just post functor
to another worker thread or job queue and return.
*/
struct Callback
{
/** Announces our listening ip/port combinations to the network.
@param address The address to broadcast.
*/
virtual void onAnnounceAddress () = 0;
/** Indicates whether or not incoming connections should be accepted.
When we are full on incoming connections, future incoming
connections from valid peers should be politely turned away,
after giving them a random sample of other addresses to try
from our cache.
*/
//virtual void onSetAcceptStatus (bool shouldAcceptIncoming) = 0;
/** Called periodically to update the callback's list of eligible addresses.
This is used for making new outgoing connections, for
handing out addresses to peers, and for periodically seeding the
network wth hop-limited broadcasts of IP addresses.
*/
//virtual void onNewAddressesAvailable (std::vector <Address> const& list) = 0;
};
//--------------------------------------------------------------------------
/** Create a new PeerFinder object.
*/
static PeerFinder* New (Callback& callback);
/** Destroy the object.
Any pending source fetch operations are aborted.
There may be some listener calls made before the
destructor returns.
*/
virtual ~PeerFinder () { }
/** Inform the PeerFinder of the status of our connections.
This call queues an asynchronous operation to the PeerFinder's thread
and returns immediately. Normally this is called by the Peer code
when the counts change.
Thread-safety:
Safe to call from any thread
@see Peer
*/
virtual void updateConnectionsStatus (Connections& connections) = 0;
/** Called when a new peer connection is established.
Internally, we add the peer to our tracking table, validate that
we can connect to it, and begin advertising it to others after
we are sure that its connection is stable.
*/
virtual void onPeerConnected(const PeerId& id) = 0;
/** Called when an existing peer connection drops for whatever reason.
Internally, we mark the peer as no longer connected, calculate
stability metrics, and consider whether we should try to reconnect
to it or drop it from our list.
*/
virtual void onPeerDisconnected(const PeerId& id) = 0;
};
#endif

View File

@@ -8,6 +8,9 @@
#include "ripple_core.h"
// Needed for InputParser
#include "beast/modules/beast_asio/beast_asio.h"
#include <fstream>
#include "beast/modules/beast_core/system/BeforeBoost.h" // must come first
@@ -71,4 +74,7 @@ namespace ripple
#include "validator/ValidatorSourceTrustedURL.cpp"
#include "validator/Validators.cpp"
#include "peerfinder/ripple_PeerFinder.h" // private (for now)
#include "peerfinder/ripple_PeerFinder.cpp"
}

View File

@@ -38,6 +38,7 @@ namespace ripple
#include "node/NodeObject.h"
#include "node/NodeStore.h"
#include "peerfinder/ripple_PeerFinder.h"
#include "validator/Validators.h"
}

View File

@@ -14,6 +14,7 @@ enum MessageType
mtCONTACT = 11;
mtGET_PEERS = 12;
mtPEERS = 13;
mtANNOUNCE = 14;
// operations for 'small' nodes
mtSEARCH_TRANSACTION = 20;
@@ -228,6 +229,14 @@ message TMPeers
repeated TMIPv4EndPoint nodes = 1;
}
message TMAnnounce
{
required bytes serverID = 1; // The ID of this server
required bool privatePeer = 2; // This peer is private - the announce will not be propagated
required uint32 hopCount = 3; // The hop count of this server
required bytes viaPeerID = 4; // The ID of the peer through which we know this server
repeated TMIPv4EndPoint connectPoints = 5; // Addresses on which this server accepts connections (can be empty)
};
message TMSearchTransaction
{