diff --git a/Builds/QtCreator/rippled.pro b/Builds/QtCreator/rippled.pro
index a7b6aa401..64414a370 100644
--- a/Builds/QtCreator/rippled.pro
+++ b/Builds/QtCreator/rippled.pro
@@ -68,6 +68,7 @@ SOURCES += \
../../src/ripple/http/ripple_http.cpp \
../../src/ripple/json/ripple_json.cpp \
../../src/ripple/peerfinder/ripple_peerfinder.cpp \
+ ../../src/ripple/resource/ripple_resource.cpp \
../../src/ripple/rpc/ripple_rpc.cpp \
../../src/ripple/sophia/ripple_sophia.c \
../../src/ripple/sslutil/ripple_sslutil.cpp \
diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj
index 9b4c8d5e9..7875c6daf 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj
+++ b/Builds/VisualStudio2012/RippleD.vcxproj
@@ -121,6 +121,43 @@
true
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
true
true
@@ -1656,6 +1693,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1836,7 +1891,6 @@
-
diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters
index 4b895c075..497d9fa51 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters
@@ -238,6 +238,15 @@
{cd1585a6-bc32-477d-88cd-275159dafa83}
+
+ {ec26c9d0-ff17-466b-bf23-a36b8aa60717}
+
+
+ {555d2128-108e-4afa-abe5-48d1508edb1e}
+
+
+ {28a8ede0-743b-4a9a-bae1-5b2bc03ee44e}
+
@@ -1092,6 +1101,30 @@
[1] Ripple\types\impl
+
+ [2] Old Ripple\ripple_app\main
+
+
+ [1] Ripple\resource
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
@@ -1649,9 +1682,6 @@
[2] Old Ripple\ripple_core\functional
-
- [2] Old Ripple\ripple_core\functional
-
[2] Old Ripple\ripple_app\main
@@ -2220,6 +2250,63 @@
[1] Ripple\types\api
+
+ [2] Old Ripple\ripple_app\main
+
+
+ [1] Ripple\resource
+
+
+ [1] Ripple\resource\api
+
+
+ [1] Ripple\resource\api
+
+
+ [1] Ripple\resource\api
+
+
+ [1] Ripple\resource\api
+
+
+ [1] Ripple\resource\api
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\api
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\api
+
+
+ [1] Ripple\resource\impl
+
+
+ [1] Ripple\resource\api
+
diff --git a/SConstruct b/SConstruct
index ba4b92814..265d38e35 100644
--- a/SConstruct
+++ b/SConstruct
@@ -159,6 +159,7 @@ COMPILED_FILES.extend([
'src/ripple/http/ripple_http.cpp',
'src/ripple/json/ripple_json.cpp',
'src/ripple/peerfinder/ripple_peerfinder.cpp',
+ 'src/ripple/resource/ripple_resource.cpp',
'src/ripple/rpc/ripple_rpc.cpp',
'src/ripple/sophia/ripple_sophia.c',
'src/ripple/sslutil/ripple_sslutil.cpp',
diff --git a/src/BeastConfig.h b/src/BeastConfig.h
index 7c6fd1920..46d9cd03e 100644
--- a/src/BeastConfig.h
+++ b/src/BeastConfig.h
@@ -178,4 +178,11 @@
#define RIPPLE_USE_RPC_SERVICE_MANAGER 0
#endif
+// Here temporarily
+// Controls whether or not the new Resource manager replaces the BlackList
+// and LoadManager for measuring and controlling access to the server
+#ifndef RIPPLE_USE_RESOURCE_MANAGER
+#define RIPPLE_USE_RESOURCE_MANAGER 0
+#endif
+
#endif
diff --git a/src/ripple/resource/api/Charge.h b/src/ripple/resource/api/Charge.h
new file mode 100644
index 000000000..053c6b39c
--- /dev/null
+++ b/src/ripple/resource/api/Charge.h
@@ -0,0 +1,60 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_CHARGE_H_INCLUDED
+#define RIPPLE_RESOURCE_CHARGE_H_INCLUDED
+
+#include
+
+namespace ripple {
+namespace Resource {
+
+/** A consumption charge. */
+class Charge
+{
+public:
+ /** The type used to hold a consumption charge. */
+ typedef int value_type;
+
+ /** Create a new charge with no cost (yet). */
+ Charge ();
+
+ /** Create a charge with the specified cost and name. */
+ Charge (value_type cost, std::string const& label = std::string());
+
+ /** Return the human readable label associated with the charge. */
+ std::string const& label() const;
+
+ /** Return the cost of the charge in Resource::Manager units. */
+ value_type cost () const;
+
+ /** Converts this charge into a human readable string. */
+ std::string to_string () const;
+
+private:
+ value_type m_cost;
+ std::string m_label;
+};
+
+std::ostream& operator<< (std::ostream& os, Charge const& v);
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/api/Consumer.h b/src/ripple/resource/api/Consumer.h
new file mode 100644
index 000000000..7fd2717e4
--- /dev/null
+++ b/src/ripple/resource/api/Consumer.h
@@ -0,0 +1,83 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_CONSUMER_H_INCLUDED
+#define RIPPLE_RESOURCE_CONSUMER_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+class Logic;
+
+/** An endpoint that consumes resources. */
+class Consumer
+{
+private:
+ friend class Logic;
+ Consumer (Logic& logic, Entry& entry);
+
+public:
+ Consumer ();
+ ~Consumer ();
+ Consumer (Consumer const& other);
+ Consumer& operator= (Consumer const& other);
+
+ /** Return a human readable string uniquely identifying this consumer. */
+ std::string label ();
+
+ /** Returns `true` if this is a privileged endpoint. */
+ bool admin () const;
+
+ /** Raise the Consumer's privilege level to a Named endpoint.
+ The reference to the original endpoint descriptor is released.
+ */
+ void elevate (std::string const& name);
+
+ /** Returns the current disposition of this consumer.
+ This should be checked upon creation to determine if the consumer
+ should be disconnected immediately.
+ */
+ Disposition disposition() const;
+
+ /** Apply a load charge to the consumer. */
+ Disposition charge (Charge const& fee);
+
+ /** Returns `true` if the consumer should be warned.
+ This consumes the warning.
+ */
+ bool warn();
+
+ /** Returns `true` if the consumer should be disconnected. */
+ bool disconnect();
+
+ /** Returns the credit balance representing consumption. */
+ int balance();
+
+ // Private: Retrieve the entry associated with the consumer
+ Entry& entry();
+
+private:
+ Logic* m_logic;
+ Entry* m_entry;
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/api/Disposition.h b/src/ripple/resource/api/Disposition.h
new file mode 100644
index 000000000..21b5b26b0
--- /dev/null
+++ b/src/ripple/resource/api/Disposition.h
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_DISPOSITION_H_INCLUDED
+#define RIPPLE_RESOURCE_DISPOSITION_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** The disposition of a consumer after applying a load charge. */
+enum Disposition
+{
+ /** No action required. */
+ ok
+
+ /** Consumer should be warned that consumption is high. */
+ ,warn
+
+ /** Consumer should be disconnected for excess consumption. */
+ ,drop
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/api/Fees.h b/src/ripple/resource/api/Fees.h
new file mode 100644
index 000000000..f9b957ea4
--- /dev/null
+++ b/src/ripple/resource/api/Fees.h
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_FEES_H_INCLUDED
+#define RIPPLE_RESOURCE_FEES_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** Schedule of fees charged for imposing load on the server. */
+/** @{ */
+extern Charge const feeInvalidRequest; // A request that we can immediately tell is invalid
+extern Charge const feeRequestNoReply; // A request that we cannot satisfy
+extern Charge const feeInvalidSignature; // An object whose signature we had to check and it failed
+extern Charge const feeUnwantedData; // Data we have no use for
+extern Charge const feeBadProofOfWork; // Proof of work not valid
+extern Charge const feeBadData; // Data we have to verify before rejecting
+
+// RPC loads
+extern Charge const feeInvalidRPC; // An RPC request that we can immediately tell is invalid.
+extern Charge const feeReferenceRPC; // A default "reference" unspecified load
+extern Charge const feeExceptionRPC; // An RPC load that causes an exception
+extern Charge const feeLightRPC; // A normal RPC command
+extern Charge const feeLowBurdenRPC; // A slightly burdensome RPC load
+extern Charge const feeMediumBurdenRPC; // A somewhat burdensome RPC load
+extern Charge const feeHighBurdenRPC; // A very burdensome RPC load
+
+// Good things
+extern Charge const feeNewTrustedNote; // A new transaction/validation/proposal we trust
+extern Charge const feeNewValidTx; // A new, valid transaction
+extern Charge const feeSatisfiedRequest; // Data we requested
+
+// Requests
+extern Charge const feeRequestedData; // A request that is hard to satisfy, disk access
+extern Charge const feeCheapQuery; // A query that is trivial, cached data
+
+// Administrative
+extern Charge const feeWarning; // The cost of receiving a warning
+extern Charge const feeDrop; // The cost of being dropped for excess load
+/** @} */
+
+/** Returns an appropriate Charge based on the legacy LoadType. */
+extern Charge legacyFee (LoadType t);
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/api/Gossip.h b/src/ripple/resource/api/Gossip.h
new file mode 100644
index 000000000..a3ee1ea19
--- /dev/null
+++ b/src/ripple/resource/api/Gossip.h
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_GOSSIP_H_INCLUDED
+#define RIPPLE_RESOURCE_GOSSIP_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** Data format for exchanging consumption information across peers. */
+struct Gossip
+{
+ /** Describes a single consumer. */
+ struct Item
+ {
+ int balance;
+ IPEndpoint address;
+ };
+
+ std::vector - items;
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple_core/functional/LoadType.h b/src/ripple/resource/api/LegacyFees.h
similarity index 75%
rename from src/ripple_core/functional/LoadType.h
rename to src/ripple/resource/api/LegacyFees.h
index c69ff949a..bf017a07c 100644
--- a/src/ripple_core/functional/LoadType.h
+++ b/src/ripple/resource/api/LegacyFees.h
@@ -17,36 +17,11 @@
*/
//==============================================================================
+#ifndef RIPPLE_RESOURCE_LEGACYFEES_H_INCLUDED
+#define RIPPLE_RESOURCE_LEGACYFEES_H_INCLUDED
-#ifndef RIPPLE_CORE_FUNCTIONAL_LOADTYPE_H_INCLUDED
-#define RIPPLE_CORE_FUNCTIONAL_LOADTYPE_H_INCLUDED
+namespace ripple {
-// types of load that can be placed on the server
-/** The type of load placed on the server.
-*/
-/* VFALCO TODO
- - Remove LT_ from each enum
- - Put LoadType into a struct like this:
- (Note this is modeled after boost::system::error_code::err_c)
-
- struct LoadType
- {
- enum load_c
- {
- invalidRequest,
- //...
- }
- };
-
- // For parameters
- typedef LoadType::load_c LoadTypeParam;
-
- // Example of passing a LoadType:
- peer->applyLoadCharge (LoadType::newTransaction);
-
- // Example function prototype
- void applyLoadCharge (LoadTypeParam loadType);
-*/
enum LoadType
{
// Bad things
@@ -75,4 +50,6 @@ enum LoadType
LT_MAX // MUST BE LAST
};
+}
+
#endif
diff --git a/src/ripple/resource/api/Manager.h b/src/ripple/resource/api/Manager.h
new file mode 100644
index 000000000..cee8ce62b
--- /dev/null
+++ b/src/ripple/resource/api/Manager.h
@@ -0,0 +1,58 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_MANAGER_H_INCLUDED
+#define RIPPLE_RESOURCE_MANAGER_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** Tracks load and resource consumption. */
+class Manager : public PropertyStream::Source
+{
+protected:
+ Manager ();
+
+public:
+ static Manager* New (Journal journal);
+
+ virtual ~Manager() { }
+
+ /** Create a new endpoint keyed by inbound IP address. */
+ virtual Consumer newInboundEndpoint (IPEndpoint const& address) = 0;
+
+ /** Create a new endpoint keyed by outbound IP address and port. */
+ virtual Consumer newOutboundEndpoint (IPEndpoint const& address) = 0;
+
+ /** Create a new endpoint keyed by name. */
+ virtual Consumer newAdminEndpoint (std::string const& name) = 0;
+
+ /** Extract packaged consumer information for export. */
+ virtual Gossip exportConsumers () = 0;
+
+ /** Import packaged consumer information.
+ @param origin An identifier that unique labels the origin.
+ */
+ virtual void importConsumers (std::string const& origin, Gossip const& gossip) = 0;
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/api/Types.h b/src/ripple/resource/api/Types.h
new file mode 100644
index 000000000..c788d53e3
--- /dev/null
+++ b/src/ripple/resource/api/Types.h
@@ -0,0 +1,35 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_TYPES_H_INCLUDED
+#define RIPPLE_RESOURCE_TYPES_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+struct Key;
+struct Entry;
+
+/** Measures seconds from an unspecified fixed reference event in the past. */
+typedef int DiscreteTime;
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/Charge.cpp b/src/ripple/resource/impl/Charge.cpp
new file mode 100644
index 000000000..c792a71a8
--- /dev/null
+++ b/src/ripple/resource/impl/Charge.cpp
@@ -0,0 +1,60 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+#include
+
+namespace ripple {
+namespace Resource {
+
+Charge::Charge ()
+ : m_cost (0)
+{
+}
+
+Charge::Charge (value_type cost, std::string const& label)
+ : m_cost (cost)
+ , m_label (label)
+{
+}
+
+std::string const& Charge::label () const
+{
+ return m_label;
+}
+
+Charge::value_type Charge::cost() const
+{
+ return m_cost;
+}
+
+std::string Charge::to_string () const
+{
+ std::stringstream ss;
+ ss << m_label << " ($" << m_cost << ")";
+ return ss.str();
+}
+
+std::ostream& operator<< (std::ostream& os, Charge const& v)
+{
+ os << v.to_string();
+ return os;
+}
+
+}
+}
diff --git a/src/ripple/resource/impl/Consumer.cpp b/src/ripple/resource/impl/Consumer.cpp
new file mode 100644
index 000000000..15b9b4acf
--- /dev/null
+++ b/src/ripple/resource/impl/Consumer.cpp
@@ -0,0 +1,129 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+namespace ripple {
+namespace Resource {
+
+Consumer::Consumer (Logic& logic, Entry& entry)
+ : m_logic (&logic)
+ , m_entry (&entry)
+{
+}
+
+Consumer::Consumer ()
+ : m_logic (nullptr)
+ , m_entry (nullptr)
+{
+}
+
+Consumer::Consumer (Consumer const& other)
+ : m_logic (other.m_logic)
+ , m_entry (nullptr)
+{
+ if (m_logic != nullptr)
+ {
+ if (other.m_entry != nullptr)
+ {
+ m_entry = other.m_entry;
+ m_logic->acquire (*m_entry);
+ }
+ }
+}
+
+Consumer::~Consumer()
+{
+ if (m_logic != nullptr)
+ {
+ if (m_entry != nullptr)
+ m_logic->release (*m_entry);
+ }
+}
+
+Consumer& Consumer::operator= (Consumer const& other)
+{
+ // remove old ref
+ if (m_logic != nullptr)
+ {
+ if (m_entry != nullptr)
+ m_logic->release (*m_entry);
+ }
+
+ m_logic = other.m_logic;
+ m_entry = other.m_entry;
+
+ // add new ref
+ if (m_logic != nullptr)
+ {
+ if (m_entry != nullptr)
+ m_logic->acquire (*m_entry);
+ }
+
+ return *this;
+}
+
+std::string Consumer::label ()
+{
+ if (m_logic == nullptr)
+ return "(none)";
+
+ return m_entry->label();
+}
+
+bool Consumer::admin () const
+{
+ return m_entry->admin();
+}
+
+void Consumer::elevate (std::string const& name)
+{
+ m_entry = &m_logic->elevateToAdminEndpoint (*m_entry, name);
+}
+
+Disposition Consumer::disposition() const
+{
+ return ok;
+}
+
+Disposition Consumer::charge (Charge const& what)
+{
+ return m_logic->charge (*m_entry, what);
+}
+
+bool Consumer::warn ()
+{
+ return m_logic->warn (*m_entry);
+}
+
+bool Consumer::disconnect ()
+{
+ return m_logic->disconnect (*m_entry);
+}
+
+int Consumer::balance()
+{
+ return m_logic->balance (*m_entry);
+}
+
+Entry& Consumer::entry()
+{
+ return *m_entry;
+}
+
+}
+}
diff --git a/src/ripple/resource/impl/DecayingSample.h b/src/ripple/resource/impl/DecayingSample.h
new file mode 100644
index 000000000..4b603ca6c
--- /dev/null
+++ b/src/ripple/resource/impl/DecayingSample.h
@@ -0,0 +1,99 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_DECAYINGSAMPLE_H_INCLUDED
+#define RIPPLE_RESOURCE_DECAYINGSAMPLE_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** Sampling function using exponential decay to provide a continuous value. */
+template
+class DecayingSample
+{
+public:
+ typedef Value value_type;
+ typedef Elapsed elapsed_type;
+
+ /** Create a default constructed sample. */
+ DecayingSample ()
+ : m_value (value_type())
+ , m_when (elapsed_type())
+ {
+ }
+
+ /** Add a new sample.
+ The value is first aged according to the specified time.
+ */
+ Value add (value_type value, elapsed_type now)
+ {
+ decay (now);
+ m_value += value;
+ return m_value / Window;
+ }
+
+ /** Retrieve the current value in normalized units.
+ The samples are first aged according to the specified time.
+ */
+ Value value (elapsed_type now)
+ {
+ decay (now);
+ return m_value / Window;
+ }
+
+private:
+ // Apply exponential decay based on the specified time.
+ void decay (elapsed_type now)
+ {
+ if (m_value == value_type())
+ return;
+
+ elapsed_type n (now - m_when);
+
+ if (n == 0)
+ return;
+
+ // A span larger than four times the window decays the
+ // value to an insignificant amount so just reset it.
+ //
+ if (n > 4 * Window)
+ {
+ m_value = value_type();
+ return;
+ }
+
+ while (n--)
+ m_value -= (m_value + Window - 1) / Window;
+
+ m_when = now;
+ }
+
+ // Current value in exponential units
+ value_type m_value;
+
+ // Last time the aging function was applied
+ elapsed_type m_when;
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/Entry.h b/src/ripple/resource/impl/Entry.h
new file mode 100644
index 000000000..09147f526
--- /dev/null
+++ b/src/ripple/resource/impl/Entry.h
@@ -0,0 +1,97 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_ENTRY_H_INCLUDED
+#define RIPPLE_RESOURCE_ENTRY_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+// An entry in the table
+struct Entry : public List ::Node
+{
+ // Dummy argument is necessary for zero-copy construction of elements
+ Entry (int)
+ : refcount (0)
+ , remote_balance (0)
+ , disposition (ok)
+ , lastWarningTime (0)
+ , whenExpires (0)
+ {
+ }
+
+ std::string label() const
+ {
+ switch (key->kind)
+ {
+ case kindInbound: return key->address.to_string();
+ case kindOutbound: return key->address.to_string();
+ case kindAdmin: return key->name;
+ default:
+ bassertfalse;
+ }
+
+ return "(undefined)";
+ }
+
+ // Returns `true` if this connection is privileged
+ bool admin () const
+ {
+ return key->kind == kindAdmin;
+ }
+
+ // Balance including remote contributions
+ int balance (DiscreteTime const now)
+ {
+ return local_balance.value (now) + remote_balance;
+ }
+
+ // Add a charge and return normalized balance
+ // including contributions from imports.
+ int add (int charge, DiscreteTime const now)
+ {
+ return local_balance.add (charge, now) + remote_balance;
+ }
+
+ // Back pointer to the map key (bit of a hack here)
+ Key const* key;
+
+ // Number of Consumer references
+ int refcount;
+
+ // Exponentially decaying balance of resource consumption
+ DecayingSample local_balance;
+
+ // Normalized balance contribution from imports
+ int remote_balance;
+
+ // Disposition
+ Disposition disposition;
+
+ // Time of the last warning
+ DiscreteTime lastWarningTime;
+
+ // For inactive entries, time after which this entry will be erased
+ DiscreteTime whenExpires;
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/Fees.cpp b/src/ripple/resource/impl/Fees.cpp
new file mode 100644
index 000000000..166fd2fb8
--- /dev/null
+++ b/src/ripple/resource/impl/Fees.cpp
@@ -0,0 +1,49 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+namespace ripple {
+namespace Resource {
+
+Charge const feeInvalidRequest ( 10, "malformed request" );
+Charge const feeRequestNoReply ( 1, "unsatisfiable request" );
+Charge const feeInvalidSignature ( 100, "invalid signature" );
+Charge const feeUnwantedData ( 5, "useless data" );
+Charge const feeBadProofOfWork ( 250, "incorrect proof of work"); // DAVID: Check the cost
+Charge const feeBadData ( 20, "invalid data" );
+
+Charge const feeInvalidRPC ( 10, "malformed RPC" );
+Charge const feeReferenceRPC ( 2, "reference RPC" );
+Charge const feeExceptionRPC ( 10, "exceptioned RPC" );
+Charge const feeLightRPC ( 5, "light RPC" ); // DAVID: Check the cost
+Charge const feeLowBurdenRPC ( 10, "low RPC" );
+Charge const feeMediumBurdenRPC ( 20, "medium RPC" );
+Charge const feeHighBurdenRPC ( 50, "heavy RPC" );
+
+Charge const feeNewTrustedNote ( 10, "trusted note" );
+Charge const feeNewValidTx ( 2, "valid tx" );
+Charge const feeSatisfiedRequest ( 10, "needed data" );
+
+Charge const feeRequestedData ( 5, "costly request" );
+Charge const feeCheapQuery ( 1, "trivial query" );
+
+Charge const feeWarning ( 10, "received warning" ); // DAVID: Check the cost
+Charge const feeDrop ( 100, "dropped" ); // DAVID: Check the cost
+
+}
+}
diff --git a/src/ripple/resource/impl/Import.h b/src/ripple/resource/impl/Import.h
new file mode 100644
index 000000000..43c222633
--- /dev/null
+++ b/src/ripple/resource/impl/Import.h
@@ -0,0 +1,51 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_IMPORT_H_INCLUDED
+#define RIPPLE_RESOURCE_IMPORT_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** A set of imported consumer data from a gossip origin. */
+struct Import
+{
+ struct Item
+ {
+ int balance;
+ Consumer consumer;
+ };
+
+ // Dummy argument required for zero-copy construction
+ Import (int = 0)
+ : whenExpires (0)
+ {
+ }
+
+ // When the imported data expires
+ DiscreteTime whenExpires;
+
+ // List of remote entries
+ std::vector
- items;
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/Key.h b/src/ripple/resource/impl/Key.h
new file mode 100644
index 000000000..69cb60c83
--- /dev/null
+++ b/src/ripple/resource/impl/Key.h
@@ -0,0 +1,88 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_KEY_H_INCLUDED
+#define RIPPLE_RESOURCE_KEY_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+// The consumer key
+struct Key
+{
+ Kind kind;
+ IPEndpoint address;
+ std::string name;
+
+ struct hasher
+ {
+ std::size_t operator() (Key const& v) const
+ {
+ switch (v.kind)
+ {
+ case kindInbound:
+ case kindOutbound:
+ return m_addr_hash (v.address);
+
+ case kindAdmin:
+ return m_name_hash (v.name);
+
+ default:
+ bassertfalse;
+ };
+
+ return 0;
+ }
+
+ private:
+ IPEndpoint::hasher m_addr_hash;
+ boost::hash m_name_hash;
+ };
+
+ struct key_equal
+ {
+ bool operator() (Key const& lhs, Key const& rhs) const
+ {
+ if (lhs.kind != rhs.kind)
+ return false;
+
+ switch (lhs.kind)
+ {
+ case kindInbound:
+ case kindOutbound:
+ return lhs.address == rhs.address;
+
+ case kindAdmin:
+ return lhs.name == rhs.name;
+
+ default:
+ bassertfalse;
+ };
+
+ return false;
+ }
+
+ private:
+ };
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/Kind.h b/src/ripple/resource/impl/Kind.h
new file mode 100644
index 000000000..b7c2d71ba
--- /dev/null
+++ b/src/ripple/resource/impl/Kind.h
@@ -0,0 +1,37 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_KIND_H_INCLUDED
+#define RIPPLE_RESOURCE_KIND_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+// Kind of consumer
+enum Kind
+{
+ kindInbound
+ ,kindOutbound
+ ,kindAdmin
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/LegacyFees.cpp b/src/ripple/resource/impl/LegacyFees.cpp
new file mode 100644
index 000000000..a9a630e09
--- /dev/null
+++ b/src/ripple/resource/impl/LegacyFees.cpp
@@ -0,0 +1,60 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+namespace ripple {
+namespace Resource {
+
+Charge legacyFee (LoadType t)
+{
+ switch (t)
+ {
+ case LT_InvalidRequest: return feeInvalidRequest;
+ case LT_RequestNoReply: return feeRequestNoReply;
+ case LT_InvalidSignature: return feeInvalidSignature;
+ case LT_UnwantedData: return feeUnwantedData;
+ case LT_BadPoW: return feeBadProofOfWork;
+ case LT_BadData: return feeBadData;
+
+ case LT_RPCInvalid: return feeInvalidRPC;
+ case LT_RPCReference: return feeReferenceRPC;
+ case LT_RPCException: return feeExceptionRPC;
+
+#if 0
+ case LT_RPCLight: return feeLightRPC;
+ case LT_RPCBurdenLow: return feeLowBurdenRPC;
+ case LT_RPCBurdenMedium: return feeMediumBurdenRPC;
+ case LT_RPCBurdenHigh: return feeHighBurdenRPC;
+#endif
+
+ case LT_NewTrusted: return feeNewTrustedNote;
+ case LT_NewTransaction: return feeNewValidTx;
+ case LT_NeededData: return feeSatisfiedRequest;
+
+ case LT_RequestData: return feeRequestedData;
+
+ default:
+ bassertfalse;
+ case LT_CheapQuery: return feeCheapQuery;
+ };
+
+ return feeInvalidRequest;
+};
+
+}
+}
diff --git a/src/ripple/resource/impl/Logic.h b/src/ripple/resource/impl/Logic.h
new file mode 100644
index 000000000..70a03c0f5
--- /dev/null
+++ b/src/ripple/resource/impl/Logic.h
@@ -0,0 +1,543 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_LOGIC_H_INCLUDED
+#define RIPPLE_RESOURCE_LOGIC_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+class Logic
+{
+public:
+ typedef boost::unordered_map Imports;
+ typedef boost::unordered_map Table;
+
+ struct State
+ {
+ // Table of all entries
+ Table table;
+
+ // List of all active inbound entries
+ List inbound;
+
+ // List of all active outbound entries
+ List outbound;
+
+ // List of all active admin entries
+ List admin;
+
+ // List of all inactve entries
+ List inactive;
+
+ // All imported gossip data
+ Imports import_table;
+ };
+
+ typedef SharedData SharedState;
+
+ SharedState m_state;
+ Journal m_journal;
+
+ //--------------------------------------------------------------------------
+
+ Logic (Journal journal)
+ : m_journal (journal)
+ {
+#if 1
+#if BEAST_MSVC
+ if (beast_isRunningUnderDebugger())
+ {
+ m_journal.sink().set_console (true);
+ m_journal.sink().set_severity (Journal::kLowestSeverity);
+ }
+#endif
+#endif
+ }
+
+ virtual ~Logic ()
+ {
+ // These have to be cleared before the Logic is destroyed
+ // since their destructors call back into the class.
+ // Order matters here as well, the import table has to be
+ // destroyed before the consumer table.
+ //
+ SharedState::UnlockedAccess state (m_state);
+ state->import_table.clear();
+ state->table.clear();
+ }
+
+ virtual DiscreteTime get_now ()
+ {
+ return 0;
+ }
+
+ Consumer newInboundEndpoint (IPEndpoint const& address)
+ {
+ if (isWhitelisted (address))
+ return newAdminEndpoint (address.to_string());
+
+ Key key;
+ key.kind = kindInbound;
+ key.address = address;
+
+ Entry* entry (nullptr);
+
+ {
+ SharedState::Access state (m_state);
+ std::pair result (
+ state->table.emplace (key, 0));
+ entry = &result.first->second;
+ entry->key = &result.first->first;
+ ++entry->refcount;
+ if (entry->refcount == 1)
+ {
+ if (! result.second)
+ state->inactive.erase (
+ state->inactive.iterator_to (*entry));
+ state->inbound.push_back (*entry);
+ }
+ }
+
+ m_journal.debug << "New inbound endpoint " << entry->label();
+
+ return Consumer (*this, *entry);
+ }
+
+ Consumer newOutboundEndpoint (IPEndpoint const& address)
+ {
+ if (isWhitelisted (address))
+ return newAdminEndpoint (address.to_string());
+
+ Key key;
+ key.kind = kindOutbound;
+ key.address = address;
+
+ Entry* entry (nullptr);
+
+ {
+ SharedState::Access state (m_state);
+ std::pair result (
+ state->table.emplace (key, 0));
+ entry = &result.first->second;
+ entry->key = &result.first->first;
+ ++entry->refcount;
+ if (entry->refcount == 1)
+ {
+ if (! result.second)
+ state->inactive.erase (
+ state->inactive.iterator_to (*entry));
+ state->outbound.push_back (*entry);
+ }
+ }
+
+ m_journal.debug << "New outbound endpoint " << entry->label();
+
+ return Consumer (*this, *entry);
+ }
+
+ Consumer newAdminEndpoint (std::string const& name)
+ {
+ Key key;
+ key.kind = kindAdmin;
+ key.name = name;
+
+ Entry* entry (nullptr);
+
+ {
+ SharedState::Access state (m_state);
+ std::pair result (
+ state->table.emplace (key, 0));
+ entry = &result.first->second;
+ entry->key = &result.first->first;
+ ++entry->refcount;
+ if (entry->refcount == 1)
+ {
+ if (! result.second)
+ state->inactive.erase (
+ state->inactive.iterator_to (*entry));
+ state->admin.push_back (*entry);
+ }
+ }
+
+ m_journal.debug << "New admin endpoint " << entry->label();
+
+ return Consumer (*this, *entry);
+ }
+
+ Entry& elevateToAdminEndpoint (Entry& prior, std::string const& name)
+ {
+ Key key;
+ key.kind = kindAdmin;
+ key.name = name;
+
+ m_journal.info << "Elevate " << prior.label() << " to " << name;
+
+ Entry* entry (nullptr);
+
+ {
+ SharedState::Access state (m_state);
+ Table::iterator iter (
+ state->table.find (*prior.key));
+ std::pair result (
+ state->table.emplace (key, 0));
+ entry = &result.first->second;
+ entry->key = &result.first->first;
+ ++entry->refcount;
+ if (entry->refcount == 1)
+ {
+ if (! result.second)
+ state->inactive.erase (
+ state->inactive.iterator_to (*entry));
+ state->admin.push_back (*entry);
+ }
+
+ release (prior, state);
+ }
+
+ return *entry;
+ }
+
+ Gossip exportConsumers ()
+ {
+ DiscreteTime const now (get_now());
+
+ Gossip gossip;
+ SharedState::Access state (m_state);
+
+ gossip.items.reserve (state->inbound.size());
+
+ for (List ::iterator iter (state->inbound.begin());
+ iter != state->inbound.end(); ++iter)
+ {
+ Gossip::Item item;
+ item.balance = iter->local_balance.value (now);
+ if (item.balance >= minimumGossipBalance)
+ {
+ item.address = iter->key->address;
+ gossip.items.push_back (item);
+ }
+ }
+
+ return gossip;
+ }
+
+ //--------------------------------------------------------------------------
+
+ void importConsumers (std::string const& origin, Gossip const& gossip)
+ {
+ DiscreteTime const now (get_now());
+
+ {
+ SharedState::Access state (m_state);
+ std::pair result (
+ state->import_table.emplace (origin, 0));
+
+ if (result.second)
+ {
+ // This is a new import
+ Import& next (result.first->second);
+ next.whenExpires = now + gossipExpirationSeconds;
+ next.items.reserve (gossip.items.size());
+ for (std::vector ::const_iterator iter (gossip.items.begin());
+ iter != gossip.items.end(); ++iter)
+ {
+ Import::Item item;
+ item.balance = iter->balance;
+ item.consumer = newInboundEndpoint (iter->address);
+ item.consumer.entry().remote_balance += item.balance;
+ next.items.push_back (item);
+ }
+ }
+ else
+ {
+ // Previous import exists so add the new remote
+ // balances and then deduct the old remote balances.
+
+ Import next;
+ next.whenExpires = now + gossipExpirationSeconds;
+ next.items.reserve (gossip.items.size());
+ for (std::vector ::const_iterator iter (gossip.items.begin());
+ iter != gossip.items.end(); ++iter)
+ {
+ Import::Item item;
+ item.balance = iter->balance;
+ item.consumer = newInboundEndpoint (iter->address);
+ item.consumer.entry().remote_balance += item.balance;
+ next.items.push_back (item);
+ }
+
+ Import& prev (result.first->second);
+ for (std::vector ::iterator iter (prev.items.begin());
+ iter != prev.items.end(); ++iter)
+ {
+ iter->consumer.entry().remote_balance -= iter->balance;
+ }
+
+ std::swap (next, prev);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ bool isWhitelisted (IPEndpoint const& address)
+ {
+ if (! address.isPublic())
+ return true;
+
+ return false;
+ }
+
+ // Called periodically to expire entries and groom the table.
+ //
+ void periodicActivity ()
+ {
+ SharedState::Access state (m_state);
+
+ DiscreteTime const now (get_now());
+
+ for (List ::iterator iter (
+ state->inactive.begin()); iter != state->inactive.end();)
+ {
+ if (iter->whenExpires <= now)
+ {
+ m_journal.debug << "Expired " << iter->label();
+ Table::iterator table_iter (
+ state->table.find (*iter->key));
+ ++iter;
+ erase (table_iter, state);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ for (Imports::iterator iter (state->import_table.begin());
+ iter != state->import_table.end(); ++iter)
+ {
+ Import& import (iter->second);
+ if (iter->second.whenExpires <= now)
+ {
+ for (std::vector ::iterator item_iter (import.items.begin());
+ item_iter != import.items.end(); ++item_iter)
+ {
+ item_iter->consumer.entry().remote_balance -= item_iter->balance;
+ }
+
+ iter = state->import_table.erase (iter);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ // Returns the disposition based on the balance and thresholds
+ static Disposition disposition (int balance)
+ {
+ if (balance >= dropThreshold)
+ return Disposition::drop;
+
+ if (balance >= warningThreshold)
+ return Disposition::warn;
+
+ return Disposition::ok;
+ }
+
+ void acquire (Entry& entry, SharedState::Access& state)
+ {
+ ++entry.refcount;
+ }
+
+ void release (Entry& entry, SharedState::Access& state)
+ {
+ if (--entry.refcount == 0)
+ {
+ m_journal.debug << "Inactive " << entry.label();
+ switch (entry.key->kind)
+ {
+ case kindInbound:
+ state->inbound.erase (
+ state->inbound.iterator_to (entry));
+ break;
+ case kindOutbound:
+ state->outbound.erase (
+ state->outbound.iterator_to (entry));
+ break;
+ case kindAdmin:
+ state->admin.erase (
+ state->admin.iterator_to (entry));
+ break;
+ default:
+ bassertfalse;
+ break;
+ }
+ state->inactive.push_back (entry);
+ entry.whenExpires = get_now() + secondsUntilExpiration;
+ }
+ }
+
+ void erase (Table::iterator iter, SharedState::Access& state)
+ {
+ Entry& entry (iter->second);
+ bassert (entry.refcount == 0);
+ state->inactive.erase (
+ state->inactive.iterator_to (entry));
+ state->table.erase (iter);
+ }
+
+ Disposition charge (Entry& entry, Charge const& fee, SharedState::Access& state)
+ {
+ DiscreteTime const now (get_now());
+ int const balance (entry.add (fee.cost(), now));
+ m_journal.info << "Charging " << entry.label() << " for " << fee;
+ return disposition (balance);
+ }
+
+ bool warn (Entry& entry, SharedState::Access& state)
+ {
+ bool notify (false);
+ DiscreteTime const now (get_now());
+ if (entry.balance (now) >= warningThreshold && now != entry.lastWarningTime)
+ {
+ charge (entry, feeWarning, state);
+ notify = true;
+ entry.lastWarningTime = now;
+ }
+
+ if (notify)
+ m_journal.info << "Load warning: " << entry.label();
+
+ return notify;
+ }
+
+ bool disconnect (Entry& entry, SharedState::Access& state)
+ {
+ bool drop (false);
+ DiscreteTime const now (get_now());
+ if (entry.balance (now) >= dropThreshold)
+ {
+ charge (entry, feeDrop, state);
+ drop = true;
+ }
+ return drop;
+ }
+
+ int balance (Entry& entry, SharedState::Access& state)
+ {
+ return entry.balance (get_now());
+ }
+
+ //--------------------------------------------------------------------------
+
+ void acquire (Entry& entry)
+ {
+ SharedState::Access state (m_state);
+ acquire (entry, state);
+ }
+
+ void release (Entry& entry)
+ {
+ SharedState::Access state (m_state);
+ release (entry, state);
+ }
+
+ Disposition charge (Entry& entry, Charge const& fee)
+ {
+ SharedState::Access state (m_state);
+ return charge (entry, fee, state);
+ }
+
+ bool warn (Entry& entry)
+ {
+ if (entry.admin())
+ return false;
+
+ SharedState::Access state (m_state);
+ return warn (entry, state);
+ }
+
+ bool disconnect (Entry& entry)
+ {
+ if (entry.admin())
+ return false;
+
+ SharedState::Access state (m_state);
+ return disconnect (entry, state);
+ }
+
+ int balance (Entry& entry)
+ {
+ SharedState::Access state (m_state);
+ return balance (entry, state);
+ }
+
+ //--------------------------------------------------------------------------
+
+ void writeList (
+ DiscreteTime const now,
+ PropertyStream::Set& items,
+ List & list)
+ {
+ for (List ::iterator iter (list.begin());
+ iter != list.end(); ++iter)
+ {
+ PropertyStream::Map item (items);
+ if (iter->refcount != 0)
+ item ["count"] = iter->refcount;
+ item ["name"] = iter->label();
+ item ["balance"] = iter->balance(now);
+ if (iter->remote_balance != 0)
+ item ["remote_balance"] = iter->remote_balance;
+ }
+ }
+
+ void onWrite (PropertyStream::Map& map)
+ {
+ DiscreteTime const now (get_now());
+
+ SharedState::Access state (m_state);
+
+ {
+ PropertyStream::Set s ("inbound", map);
+ writeList (now, s, state->inbound);
+ }
+
+ {
+ PropertyStream::Set s ("outbound", map);
+ writeList (now, s, state->outbound);
+ }
+
+ {
+ PropertyStream::Set s ("admin", map);
+ writeList (now, s, state->admin);
+ }
+
+ {
+ PropertyStream::Set s ("inactive", map);
+ writeList (now, s, state->inactive);
+ }
+ }
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/LogicType.h b/src/ripple/resource/impl/LogicType.h
new file mode 100644
index 000000000..078c523a3
--- /dev/null
+++ b/src/ripple/resource/impl/LogicType.h
@@ -0,0 +1,50 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_LOGICTYPE_H_INCLUDED
+#define RIPPLE_RESOURCE_LOGICTYPE_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** Provides the Clock required by Logic's get_now().
+ This allows the unit tests to provide its own manual clock.
+*/
+template
+class LogicType : public Logic
+{
+public:
+ explicit LogicType (Journal journal)
+ : Logic (journal)
+ {
+ }
+
+ DiscreteTime get_now ()
+ {
+ return m_clock();
+ }
+
+private:
+ Clock m_clock;
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/Manager.cpp b/src/ripple/resource/impl/Manager.cpp
new file mode 100644
index 000000000..9b2b4770f
--- /dev/null
+++ b/src/ripple/resource/impl/Manager.cpp
@@ -0,0 +1,105 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+namespace ripple {
+namespace Resource {
+
+class ManagerImp
+ : public Manager
+ , public Thread
+{
+public:
+ Journal m_journal;
+ LogicType m_logic;
+
+ ManagerImp (Journal journal)
+ : Thread ("Resource::Manager")
+ ,
+ m_journal (journal)
+ , m_logic (journal)
+ {
+ startThread ();
+ }
+
+ ~ManagerImp ()
+ {
+ stopThread ();
+ }
+
+ Consumer newInboundEndpoint (IPEndpoint const& address)
+ {
+ return m_logic.newInboundEndpoint (address);
+ }
+
+ Consumer newOutboundEndpoint (IPEndpoint const& address)
+ {
+ return m_logic.newOutboundEndpoint (address);
+ }
+
+ Consumer newAdminEndpoint (std::string const& name)
+ {
+ return m_logic.newAdminEndpoint (name);
+ }
+
+ Gossip exportConsumers ()
+ {
+ return m_logic.exportConsumers();
+ }
+
+ void importConsumers (std::string const& origin, Gossip const& gossip)
+ {
+ m_logic.importConsumers (origin, gossip);
+ }
+
+ //--------------------------------------------------------------------------
+
+ void onWrite (PropertyStream::Map& map)
+ {
+ m_logic.onWrite (map);
+ }
+
+ //--------------------------------------------------------------------------
+
+ void run ()
+ {
+ do
+ {
+ m_logic.periodicActivity();
+ wait (1000);
+ }
+ while (! threadShouldExit ());
+ }
+};
+
+//------------------------------------------------------------------------------
+
+Manager::Manager ()
+ : PropertyStream::Source ("resource")
+{
+}
+
+//------------------------------------------------------------------------------
+
+Manager* Manager::New (Journal journal)
+{
+ return new ManagerImp (journal);
+}
+
+}
+}
diff --git a/src/ripple/resource/impl/SimpleMonotonicClock.h b/src/ripple/resource/impl/SimpleMonotonicClock.h
new file mode 100644
index 000000000..88a60824d
--- /dev/null
+++ b/src/ripple/resource/impl/SimpleMonotonicClock.h
@@ -0,0 +1,40 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_SIMPLEMONOTONICCLOCK_H_INCLUDED
+#define RIPPLE_RESOURCE_SIMPLEMONOTONICCLOCK_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** Monotonically increasing time value. */
+struct SimpleMonotonicClock
+{
+ typedef int value_type;
+
+ value_type operator() () const
+ {
+ return value_type (RelativeTime::fromStartup().inSeconds());
+ }
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/impl/Tests.cpp b/src/ripple/resource/impl/Tests.cpp
new file mode 100644
index 000000000..f963703bc
--- /dev/null
+++ b/src/ripple/resource/impl/Tests.cpp
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+namespace ripple {
+namespace Resource {
+
+class Tests : public UnitTest
+{
+public:
+ // A manually operated clock
+ class TestClock
+ {
+ public:
+ static int& now()
+ {
+ static int when (0);
+ return when;
+ }
+
+ int operator() () const
+ {
+ return now();
+ }
+ };
+
+ void createGossip (Gossip& gossip)
+ {
+ int const v (10 + random().nextInt (10));
+ int const n (10 + random().nextInt (10));
+ gossip.items.reserve (n);
+ for (int i = 0; i < n; ++i)
+ {
+ Gossip::Item item;
+ item.balance = 100 + random().nextInt (500);
+ item.address = IPEndpoint (IPEndpoint::V4 (
+ 207, 127, 82, v + i));
+ gossip.items.push_back (item);
+ }
+ }
+
+ void testImports ()
+ {
+ beginTestCase ("Imports");
+
+ ScopedPointer logic (
+ new LogicType (journal()));
+
+ Gossip g[5];
+
+ for (int i = 0; i < 5; ++i)
+ createGossip (g[i]);
+
+ for (int i = 0; i < 5; ++i)
+ logic->importConsumers (String::fromNumber (i).toStdString(), g[i]);
+
+ pass();
+ }
+
+ void testImport ()
+ {
+ beginTestCase ("Import");
+
+ ScopedPointer logic (
+ new LogicType (journal()));
+
+ Gossip g;
+ Gossip::Item item;
+ item.balance = 100;
+ item.address = IPEndpoint (IPEndpoint::V4 (207, 127, 82, 1));
+ g.items.push_back (item);
+
+ logic->importConsumers ("g", g);
+
+ pass();
+ }
+
+ void testCharges ()
+ {
+ beginTestCase ("Charge");
+ ScopedPointer logic (
+ new LogicType (journal()));
+
+ {
+ IPEndpoint address (IPEndpoint::from_string ("207.127.82.1"));
+ Consumer c (logic->newInboundEndpoint (address));
+ logMessage ("Charging " + c.label() + " 10,000 units");
+ c.charge (10000);
+ for (int i = 0; i < 128; ++i)
+ {
+ logMessage (
+ "Time = " + String::fromNumber (TestClock::now()) +
+ ", Balance = " + String::fromNumber (c.balance()));
+ ++TestClock::now();
+ }
+ }
+
+ {
+ IPEndpoint address (IPEndpoint::from_string ("207.127.82.2"));
+ Consumer c (logic->newInboundEndpoint (address));
+ logMessage ("Charging " + c.label() + " 1000 units per second");
+ for (int i = 0; i < 128; ++i)
+ {
+ c.charge (1000);
+ logMessage (
+ "Time = " + String::fromNumber (TestClock::now()) +
+ ", Balance = " + String::fromNumber (c.balance()));
+ ++TestClock::now();
+ }
+ }
+
+ pass();
+ }
+
+ void runTest ()
+ {
+ //testCharges();
+ testImports();
+ //testImport();
+ }
+
+ Tests () : UnitTest ("ResourceManager", "ripple", runManual)
+ {
+ }
+};
+
+static Tests tests;
+
+}
+}
diff --git a/src/ripple/resource/impl/Tuning.h b/src/ripple/resource/impl/Tuning.h
new file mode 100644
index 000000000..24a1b08e7
--- /dev/null
+++ b/src/ripple/resource/impl/Tuning.h
@@ -0,0 +1,52 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_TUNING_H_INCLUDED
+#define RIPPLE_RESOURCE_TUNING_H_INCLUDED
+
+namespace ripple {
+namespace Resource {
+
+/** Tunable constants. */
+enum
+{
+ // Balance at which a warning is issued
+ warningThreshold = 1000
+
+ // Balance at which the consumer is disconnected
+ ,dropThreshold = 5000
+
+ // The number of seconds until an inactive table item is removed
+ ,secondsUntilExpiration = 300
+
+ // The number of seconds in the exponential decay window
+ // (This should be a power of two)
+ ,decayWindowSeconds = 32
+
+ // The minimum balance required in order to include a load source in gossip
+ ,minimumGossipBalance = 100
+
+ // Number of seconds until imported gossip expires
+ ,gossipExpirationSeconds = 30
+};
+
+}
+}
+
+#endif
diff --git a/src/ripple/resource/ripple_resource.cpp b/src/ripple/resource/ripple_resource.cpp
new file mode 100644
index 000000000..25d8c0d88
--- /dev/null
+++ b/src/ripple/resource/ripple_resource.cpp
@@ -0,0 +1,41 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+#include "BeastConfig.h"
+
+#include "ripple_resource.h"
+
+#include "beast/modules/beast_core/system/BeforeBoost.h"
+#include
+
+#include "impl/Fees.cpp"
+# include "impl/Kind.h"
+# include "impl/Key.h"
+# include "impl/DecayingSample.h"
+# include "impl/Tuning.h"
+# include "impl/Entry.h"
+# include "impl/Import.h"
+#include "impl/SimpleMonotonicClock.h"
+#include "impl/Charge.cpp"
+# include "impl/Logic.h"
+# include "impl/LogicType.h"
+#include "impl/Consumer.cpp"
+#include "impl/LegacyFees.cpp"
+#include "impl/Manager.cpp"
+#include "impl/Tests.cpp"
diff --git a/src/ripple/resource/ripple_resource.h b/src/ripple/resource/ripple_resource.h
new file mode 100644
index 000000000..fd36c58c9
--- /dev/null
+++ b/src/ripple/resource/ripple_resource.h
@@ -0,0 +1,38 @@
+//------------------------------------------------------------------------------
+/*
+ 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 RIPPLE_RESOURCE_H_INCLUDED
+#define RIPPLE_RESOURCE_H_INCLUDED
+
+#include "beast/modules/beast_core/beast_core.h"
+
+namespace ripple {
+using namespace beast;
+}
+
+# include "api/Types.h"
+# include "api/Disposition.h"
+# include "api/Charge.h"
+# include "api/LegacyFees.h"
+# include "api/Fees.h"
+# include "api/Consumer.h"
+# include "api/Gossip.h"
+#include "api/Manager.h"
+
+#endif
diff --git a/src/ripple/testoverlay/ripple_testoverlay.cpp b/src/ripple/testoverlay/ripple_testoverlay.cpp
index 5aac668dc..d69aa1c79 100644
--- a/src/ripple/testoverlay/ripple_testoverlay.cpp
+++ b/src/ripple/testoverlay/ripple_testoverlay.cpp
@@ -17,13 +17,11 @@
*/
//==============================================================================
-
#include "BeastConfig.h"
#include "ripple_testoverlay.h"
-namespace ripple
-{
+namespace ripple {
#include "impl/TestOverlay.cpp"
diff --git a/src/ripple_app/ledger/InboundLedgers.cpp b/src/ripple_app/ledger/InboundLedgers.cpp
index 452815d57..e0caa175d 100644
--- a/src/ripple_app/ledger/InboundLedgers.cpp
+++ b/src/ripple_app/ledger/InboundLedgers.cpp
@@ -128,7 +128,10 @@ void InboundLedgers::gotLedgerData (Job&, LedgerHash hash,
WriteLog (lsTRACE, InboundLedger) << "Got data for ledger we're not acquiring";
if (peer)
+ {
+ peer->charge (Resource::feeInvalidRequest);
peer->applyLoadCharge (LT_InvalidRequest);
+ }
return;
}
@@ -143,6 +146,7 @@ void InboundLedgers::gotLedgerData (Job&, LedgerHash hash,
if (packet.nodes_size () < 1)
{
WriteLog (lsWARNING, InboundLedger) << "Got empty base data";
+ peer->charge (Resource::feeInvalidRequest);
peer->applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -150,6 +154,7 @@ void InboundLedgers::gotLedgerData (Job&, LedgerHash hash,
if (!ledger->takeBase (packet.nodes (0).nodedata ()))
{
WriteLog (lsWARNING, InboundLedger) << "Got invalid base data";
+ peer->charge (Resource::feeInvalidRequest);
peer->applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -185,6 +190,7 @@ void InboundLedgers::gotLedgerData (Job&, LedgerHash hash,
if (packet.nodes ().size () <= 0)
{
WriteLog (lsINFO, InboundLedger) << "Got response with no nodes";
+ peer->charge (Resource::feeInvalidRequest);
peer->applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -196,6 +202,7 @@ void InboundLedgers::gotLedgerData (Job&, LedgerHash hash,
if (!node.has_nodeid () || !node.has_nodedata ())
{
WriteLog (lsWARNING, InboundLedger) << "Got bad node";
+ peer->charge (Resource::feeInvalidRequest);
peer->applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -223,6 +230,7 @@ void InboundLedgers::gotLedgerData (Job&, LedgerHash hash,
}
WriteLog (lsWARNING, InboundLedger) << "Not sure what ledger data we got";
+ peer->charge (Resource::feeInvalidRequest);
peer->applyLoadCharge (LT_InvalidRequest);
}
diff --git a/src/ripple_app/main/Application.cpp b/src/ripple_app/main/Application.cpp
index 8ef799823..ed6a2442d 100644
--- a/src/ripple_app/main/Application.cpp
+++ b/src/ripple_app/main/Application.cpp
@@ -42,6 +42,8 @@ class HTTPServerLog;
template <> char const* LogPartition::getPartitionName () { return "RPCServer"; }
class LoadManagerLog;
template <> char const* LogPartition::getPartitionName () { return "LoadManager"; }
+class ResourceManagerLog;
+template <> char const* LogPartition::getPartitionName () { return "ResourceManager"; }
//
//------------------------------------------------------------------------------
@@ -71,6 +73,9 @@ public:
, m_tempNodeCache ("NodeCache", 16384, 90)
, m_sleCache ("LedgerEntryCache", 4096, 120)
+ , m_resourceManager (add (Resource::Manager::New (
+ LogJournal::get ())))
+
, m_rpcServiceManager (RPC::Manager::New (
LogJournal::get ()))
@@ -472,7 +477,8 @@ public:
// the creation of the peer SSL context and Peers object into
// the conditional.
//
- m_peers = add (Peers::New (m_mainIoPool, m_mainIoPool, m_peerSSLContext->get ()));
+ m_peers = add (Peers::New (m_mainIoPool, *m_resourceManager,
+ m_mainIoPool, m_peerSSLContext->get ()));
// If we're not in standalone mode,
// prepare ourselves for networking
@@ -483,6 +489,7 @@ public:
//
m_peerDoors.add (PeerDoor::New (
m_mainIoPool,
+ *m_resourceManager,
PeerDoor::sslRequired,
getConfig ().PEER_IP,
getConfig ().peerListeningPort,
@@ -494,6 +501,7 @@ public:
// Also listen on a PROXY-only port.
m_peerDoors.add (PeerDoor::New (
m_mainIoPool,
+ *m_resourceManager,
PeerDoor::sslAndPROXYRequired,
getConfig ().PEER_IP,
getConfig ().peerPROXYListeningPort,
@@ -523,8 +531,10 @@ public:
//
if (!getConfig ().WEBSOCKET_IP.empty () && getConfig ().WEBSOCKET_PORT)
{
- m_wsPrivateDoor = WSDoor::New (getOPs(), getConfig ().WEBSOCKET_IP,
- getConfig ().WEBSOCKET_PORT, false, m_wsSSLContext->get ());
+ m_wsPrivateDoor = WSDoor::New (*m_resourceManager,
+ getOPs(), getConfig ().WEBSOCKET_IP,
+ getConfig ().WEBSOCKET_PORT, false,
+ m_wsSSLContext->get ());
if (m_wsPrivateDoor == nullptr)
{
@@ -541,8 +551,10 @@ public:
//
if (!getConfig ().WEBSOCKET_PUBLIC_IP.empty () && getConfig ().WEBSOCKET_PUBLIC_PORT)
{
- m_wsPublicDoor = WSDoor::New (getOPs(), getConfig ().WEBSOCKET_PUBLIC_IP,
- getConfig ().WEBSOCKET_PUBLIC_PORT, true, m_wsSSLContext->get ());
+ m_wsPublicDoor = WSDoor::New (*m_resourceManager,
+ getOPs(), getConfig ().WEBSOCKET_PUBLIC_IP,
+ getConfig ().WEBSOCKET_PUBLIC_PORT, true,
+ m_wsSSLContext->get ());
if (m_wsPublicDoor == nullptr)
{
@@ -839,6 +851,7 @@ private:
LocalCredentials m_localCredentials;
TransactionMaster m_txMaster;
+ ScopedPointer m_resourceManager;
ScopedPointer m_rpcServiceManager;
// These are Stoppable-related
diff --git a/src/ripple_app/main/LoadManager.cpp b/src/ripple_app/main/LoadManager.cpp
index a3f4202f5..a61fd519a 100644
--- a/src/ripple_app/main/LoadManager.cpp
+++ b/src/ripple_app/main/LoadManager.cpp
@@ -102,6 +102,16 @@ public:
, mDeadLock (0)
, mCosts (LT_MAX)
{
+#if 0
+#if BEAST_MSVC
+ if (beast_isRunningUnderDebugger())
+ {
+ m_journal.sink().set_console (true);
+ m_journal.sink().set_severity (Journal::kLowestSeverity);
+ }
+#endif
+#endif
+
/** Flags indicating the type of load.
Utilization may include any combination of:
diff --git a/src/ripple_app/main/LoadManager.h b/src/ripple_app/main/LoadManager.h
index 067d07eca..43d5347ed 100644
--- a/src/ripple_app/main/LoadManager.h
+++ b/src/ripple_app/main/LoadManager.h
@@ -17,9 +17,8 @@
*/
//==============================================================================
-
-#ifndef RIPPLE_LOADMANAGER_H_INCLUDEd
-#define RIPPLE_LOADMANAGER_H_INCLUDEd
+#ifndef RIPPLE_LOADMANAGER_H_INCLUDED
+#define RIPPLE_LOADMANAGER_H_INCLUDED
/** Manages load sources.
diff --git a/src/ripple_app/peers/Peer.cpp b/src/ripple_app/peers/Peer.cpp
index 37b586b91..570d35cc0 100644
--- a/src/ripple_app/peers/Peer.cpp
+++ b/src/ripple_app/peers/Peer.cpp
@@ -35,8 +35,9 @@ class PeerImp : public Peer
, public CountedObject
{
private:
- // This is up here to prevent warnings about order of initializations
+ // These is up here to prevent warnings about order of initializations
//
+ Resource::Manager& m_resourceManager;
bool m_isInbound;
public:
@@ -59,12 +60,13 @@ public:
return *m_socket;
}
- PeerImp (boost::asio::io_service& io_service,
- boost::asio::ssl::context& ssl_context,
- uint64 peerID,
- bool inbound,
- MultiSocket::Flag flags)
- : m_isInbound (inbound)
+ PeerImp (Resource::Manager& resourceManager,
+ boost::asio::io_service& io_service,
+ boost::asio::ssl::context& ssl_context,
+ uint64 peerID, bool inbound,
+ MultiSocket::Flag flags)
+ : m_resourceManager (resourceManager)
+ , m_isInbound (inbound)
, m_socket (MultiSocket::New (
io_service, ssl_context, flags.asBits ()))
, m_strand (io_service)
@@ -118,7 +120,8 @@ private:
bool m_remoteAddressSet;
IPEndpoint m_remoteAddress;
-
+ Resource::Consumer m_usage;
+
public:
static char const* getCountedObjectName () { return "Peer"; }
@@ -160,6 +163,11 @@ public:
void sendGetPeers ();
+ void charge (Resource::Charge const& fee)
+ {
+ m_usage.charge (fee);
+ }
+
void applyLoadCharge (LoadType);
Json::Value getJson ();
@@ -300,24 +308,6 @@ private:
}
else
{
- boost::asio::ip::address addr (getNativeSocket().remote_endpoint().address());
-
- if (addr.is_v4())
- {
- boost::asio::ip::address_v4::bytes_type bytes (addr.to_v4().to_bytes());
- m_remoteAddress = IPEndpoint (IPEndpoint::V4 (
- bytes[0], bytes[1], bytes[2], bytes[3]), 0);
- if (! m_isInbound)
- m_remoteAddress = m_remoteAddress.withPort (
- getNativeSocket().remote_endpoint().port());
- }
- else
- {
- // TODO: Support ipv6
- bassertfalse;
- }
- m_remoteAddressSet = true;
-
if (m_socket->getFlags ().set (MultiSocket::Flag::proxy) && m_isInbound)
{
MultiSocket::ProxyInfo const proxyInfo (m_socket->getProxyInfo ());
@@ -336,6 +326,11 @@ private:
mIpPort.first = proxyInfo.sourceAddress.toString ().toStdString ();
mIpPort.second = proxyInfo.sourcePort;
+ if (m_isInbound)
+ m_usage = m_resourceManager.newInboundEndpoint (m_remoteAddress);
+ else
+ m_usage = m_resourceManager.newOutboundEndpoint (m_remoteAddress);
+
// Must compute mCookieHash before receiving a hello.
sendHello ();
startReadHeader ();
@@ -359,6 +354,29 @@ private:
}
else
{
+ boost::asio::ip::address addr (getNativeSocket().remote_endpoint().address());
+
+ if (addr.is_v4())
+ {
+ boost::asio::ip::address_v4::bytes_type bytes (addr.to_v4().to_bytes());
+ m_remoteAddress = IPEndpoint (IPEndpoint::V4 (
+ bytes[0], bytes[1], bytes[2], bytes[3]), 0);
+ if (! m_isInbound)
+ m_remoteAddress = m_remoteAddress.withPort (
+ getNativeSocket().remote_endpoint().port());
+ }
+ else
+ {
+ // TODO: Support ipv6
+ bassertfalse;
+ }
+ m_remoteAddressSet = true;
+
+ if (m_isInbound)
+ m_usage = m_resourceManager.newInboundEndpoint (m_remoteAddress);
+ else
+ m_usage = m_resourceManager.newOutboundEndpoint (m_remoteAddress);
+
// Must compute mCookieHash before receiving a hello.
sendHello ();
startReadHeader ();
@@ -1221,6 +1239,7 @@ static void checkTransaction (Job&, int flags, SerializedTransaction::pointer st
if (tx->getStatus () == INVALID)
{
getApp().getHashRouter ().setFlag (stx->getTransactionID (), SF_BAD);
+ Peer::charge (peer, Resource::feeInvalidSignature);
Peer::applyLoadCharge (peer, LT_InvalidSignature);
return;
}
@@ -1234,6 +1253,7 @@ static void checkTransaction (Job&, int flags, SerializedTransaction::pointer st
catch (...)
{
getApp().getHashRouter ().setFlag (stx->getTransactionID (), SF_BAD);
+ Peer::charge (peer, Resource::feeInvalidRequest);
Peer::applyLoadCharge (peer, LT_InvalidRequest);
}
@@ -1261,6 +1281,7 @@ void PeerImp::recvTransaction (protocol::TMTransaction& packet, Application::Sco
// we have seen this transaction recently
if (isSetBit (flags, SF_BAD))
{
+ charge (Resource::feeInvalidSignature);
applyLoadCharge (LT_InvalidSignature);
return;
}
@@ -1325,6 +1346,7 @@ static void checkPropose (Job& job, boost::shared_ptr pa
Peer::pointer p = peer.lock ();
WriteLog (lsWARNING, Peer) << "proposal with previous ledger fails signature check: " <<
(p ? p->getIP () : std::string ("???"));
+ Peer::charge (peer, Resource::feeInvalidSignature);
Peer::applyLoadCharge (peer, LT_InvalidSignature);
return;
}
@@ -1369,6 +1391,7 @@ void PeerImp::recvPropose (const boost::shared_ptr& pack
(set.signature ().size () < 56) || (set.nodepubkey ().size () > 128) || (set.signature ().size () > 128))
{
WriteLog (lsWARNING, Peer) << "Received proposal is malformed";
+ charge (Resource::feeInvalidSignature);
applyLoadCharge (LT_InvalidSignature);
return;
}
@@ -1376,6 +1399,7 @@ void PeerImp::recvPropose (const boost::shared_ptr& pack
if (set.has_previousledger () && (set.previousledger ().size () != 32))
{
WriteLog (lsWARNING, Peer) << "Received proposal is malformed";
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -1437,6 +1461,7 @@ void PeerImp::recvHaveTxSet (protocol::TMHaveTransactionSet& packet)
if (packet.hash ().size () != (256 / 8))
{
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -1452,7 +1477,10 @@ void PeerImp::recvHaveTxSet (protocol::TMHaveTransactionSet& packet)
addTxSet (hash);
if (!getApp().getOPs ().hasTXSet (shared_from_this (), hash, packet.status ()))
+ {
+ charge (Resource::feeUnwantedData);
applyLoadCharge (LT_UnwantedData);
+ }
}
static void checkValidation (Job&, SerializedValidation::pointer val, bool isTrusted, bool isCluster,
@@ -1467,6 +1495,7 @@ static void checkValidation (Job&, SerializedValidation::pointer val, bool isTru
if (!isCluster && !val->isValid (signingHash))
{
WriteLog (lsWARNING, Peer) << "Validation is invalid";
+ Peer::charge (peer, Resource::feeInvalidRequest);
Peer::applyLoadCharge (peer, LT_InvalidRequest);
return;
}
@@ -1505,6 +1534,7 @@ static void checkValidation (Job&, SerializedValidation::pointer val, bool isTru
catch (...)
{
WriteLog (lsWARNING, Peer) << "Exception processing validation";
+ Peer::charge (peer, Resource::feeInvalidRequest);
Peer::applyLoadCharge (peer, LT_InvalidRequest);
}
@@ -1519,6 +1549,7 @@ void PeerImp::recvValidation (const boost::shared_ptr& p
if (packet->validation ().size () < 50)
{
WriteLog (lsWARNING, Peer) << "Too small validation from peer";
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -1535,6 +1566,7 @@ void PeerImp::recvValidation (const boost::shared_ptr& p
if (closeTime > (120 + val->getFieldU32(sfSigningTime)))
{
WriteLog (lsTRACE, Peer) << "Validation is more than two minutes old";
+ charge (Resource::feeUnwantedData);
applyLoadCharge (LT_UnwantedData);
return;
}
@@ -1558,6 +1590,7 @@ void PeerImp::recvValidation (const boost::shared_ptr& p
catch (...)
{
WriteLog (lsWARNING, Peer) << "Exception processing validation";
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
}
@@ -1568,6 +1601,7 @@ void PeerImp::recvCluster (protocol::TMCluster& packet)
{
if (!mCluster)
{
+ charge (Resource::feeUnwantedData);
applyLoadCharge(LT_UnwantedData);
return;
}
@@ -1863,6 +1897,7 @@ void PeerImp::recvProofWork (protocol::TMProofWork& packet)
// this is an answer to a proof of work we requested
if (packet.response ().size () != (256 / 8))
{
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -1881,7 +1916,10 @@ void PeerImp::recvProofWork (protocol::TMProofWork& packet)
// return error message
// WRITEME
if (r != powTOOEASY)
+ {
+ charge (Resource::feeBadProofOfWork);
applyLoadCharge (LT_BadPoW);
+ }
return;
}
@@ -1901,6 +1939,7 @@ void PeerImp::recvProofWork (protocol::TMProofWork& packet)
if ((packet.challenge ().size () != (256 / 8)) || (packet.target ().size () != (256 / 8)))
{
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -1912,6 +1951,7 @@ void PeerImp::recvProofWork (protocol::TMProofWork& packet)
if (!pow->isValid ())
{
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2009,6 +2049,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, Application::ScopedL
if ((!packet.has_ledgerhash () || packet.ledgerhash ().size () != 32))
{
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
WriteLog (lsWARNING, Peer) << "invalid request for TX candidate set data";
return;
@@ -2045,6 +2086,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, Application::ScopedL
}
WriteLog (lsERROR, Peer) << "We do not have the map our peer wants " << getIP ();
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2073,6 +2115,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, Application::ScopedL
if (packet.ledgerhash ().size () != 32)
{
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
WriteLog (lsWARNING, Peer) << "Invalid request";
return;
@@ -2129,6 +2172,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, Application::ScopedL
}
else
{
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
WriteLog (lsWARNING, Peer) << "Can't figure out what ledger they want";
return;
@@ -2136,6 +2180,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, Application::ScopedL
if ((!ledger) || (packet.has_ledgerseq () && (packet.ledgerseq () != ledger->getLedgerSeq ())))
{
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
if (ShouldLog (lsWARNING, Peer))
@@ -2216,6 +2261,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, Application::ScopedL
if ((!map) || (packet.nodeids_size () == 0))
{
WriteLog (lsWARNING, Peer) << "Can't find map or empty request";
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2229,6 +2275,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, Application::ScopedL
if (!mn.isValid ())
{
WriteLog (lsWARNING, Peer) << "Request for invalid node: " << logMe;
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2290,6 +2337,7 @@ void PeerImp::recvLedger (const boost::shared_ptr& packe
if (packet.nodes ().size () <= 0)
{
WriteLog (lsWARNING, Peer) << "Ledger/TXset data with no nodes";
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2306,6 +2354,7 @@ void PeerImp::recvLedger (const boost::shared_ptr& packe
else
{
WriteLog (lsINFO, Peer) << "Unable to route TX/ledger data reply";
+ charge (Resource::feeUnwantedData);
applyLoadCharge (LT_UnwantedData);
}
@@ -2317,6 +2366,7 @@ void PeerImp::recvLedger (const boost::shared_ptr& packe
if (packet.ledgerhash ().size () != 32)
{
WriteLog (lsWARNING, Peer) << "TX candidate reply with invalid hash size";
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2336,6 +2386,7 @@ void PeerImp::recvLedger (const boost::shared_ptr& packe
if (!node.has_nodeid () || !node.has_nodedata () || (node.nodeid ().size () != 33))
{
WriteLog (lsWARNING, Peer) << "LedgerData request with invalid node ID";
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2347,17 +2398,25 @@ void PeerImp::recvLedger (const boost::shared_ptr& packe
SHAMapAddNode san = getApp().getOPs ().gotTXData (shared_from_this (), hash, nodeIDs, nodeData);
if (san.isInvalid ())
+ {
+ charge (Resource::feeUnwantedData);
applyLoadCharge (LT_UnwantedData);
+ }
return;
}
if (getApp().getInboundLedgers ().awaitLedgerData (hash))
+ {
getApp().getJobQueue ().addJob (jtLEDGER_DATA, "gotLedgerData",
BIND_TYPE (&InboundLedgers::gotLedgerData, &getApp().getInboundLedgers (),
P_1, hash, packet_ptr, boost::weak_ptr (shared_from_this ())));
+ }
else
+ {
+ charge (Resource::feeUnwantedData);
applyLoadCharge (LT_UnwantedData);
+ }
}
void PeerImp::ledgerRange (uint32& minSeq, uint32& maxSeq) const
@@ -2570,6 +2629,7 @@ void PeerImp::doFetchPack (const boost::shared_ptr&
if (packet->ledgerhash ().size () != 32)
{
WriteLog (lsWARNING, Peer) << "FetchPack hash size malformed";
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2582,6 +2642,7 @@ void PeerImp::doFetchPack (const boost::shared_ptr&
if (!haveLedger)
{
WriteLog (lsINFO, Peer) << "Peer requests fetch pack for ledger we don't have: " << hash;
+ charge (Resource::feeRequestNoReply);
applyLoadCharge (LT_RequestNoReply);
return;
}
@@ -2589,6 +2650,7 @@ void PeerImp::doFetchPack (const boost::shared_ptr&
if (!haveLedger->isClosed ())
{
WriteLog (lsWARNING, Peer) << "Peer requests fetch pack from open ledger: " << hash;
+ charge (Resource::feeInvalidRequest);
applyLoadCharge (LT_InvalidRequest);
return;
}
@@ -2598,6 +2660,7 @@ void PeerImp::doFetchPack (const boost::shared_ptr&
if (!wantLedger)
{
WriteLog (lsINFO, Peer) << "Peer requests fetch pack for ledger whose predecessor we don't have: " << hash;
+ charge (Resource::feeRequestNoReply);
applyLoadCharge (LT_RequestNoReply);
return;
}
@@ -2692,9 +2755,10 @@ Json::Value PeerImp::getJson ()
//------------------------------------------------------------------------------
-Peer::pointer Peer::New (boost::asio::io_service& io_service,
- boost::asio::ssl::context& ssl_context, uint64 id,
- bool inbound, bool requirePROXYHandshake)
+Peer::pointer Peer::New (Resource::Manager& resourceManager,
+ boost::asio::io_service& io_service,
+ boost::asio::ssl::context& ssl_context, uint64 id,
+ bool inbound, bool requirePROXYHandshake)
{
MultiSocket::Flag flags;
@@ -2714,12 +2778,19 @@ Peer::pointer Peer::New (boost::asio::io_service& io_service,
bassert (! requirePROXYHandshake);
}
- return Peer::pointer (new PeerImp (
+ return Peer::pointer (new PeerImp (resourceManager,
io_service, ssl_context, id, inbound, flags));
}
//------------------------------------------------------------------------------
+void Peer::charge (boost::weak_ptr & peer, Resource::Charge const& fee)
+{
+ Peer::pointer p (peer.lock());
+ if (p != nullptr)
+ p->charge (fee);
+}
+
void Peer::applyLoadCharge (boost::weak_ptr & peerToPunish,
LoadType loadThatWasImposed)
{
@@ -2730,3 +2801,4 @@ void Peer::applyLoadCharge (boost::weak_ptr & peerToPunish,
p->applyLoadCharge (loadThatWasImposed);
}
}
+
diff --git a/src/ripple_app/peers/Peer.h b/src/ripple_app/peers/Peer.h
index acedb07d6..386ec801b 100644
--- a/src/ripple_app/peers/Peer.h
+++ b/src/ripple_app/peers/Peer.h
@@ -17,10 +17,14 @@
*/
//==============================================================================
-
#ifndef RIPPLE_PEER_H_INCLUDED
#define RIPPLE_PEER_H_INCLUDED
+namespace Resource {
+class Charge;
+class Manager;
+}
+
// VFALCO TODO Couldn't this be a struct?
typedef std::pair IPAndPortNumber;
@@ -35,7 +39,8 @@ public:
typedef pointer const& ref;
public:
- static pointer New (boost::asio::io_service& io_service,
+ static pointer New (Resource::Manager& resourceManager,
+ boost::asio::io_service& io_service,
boost::asio::ssl::context& ctx,
uint64 id,
bool inbound,
@@ -63,14 +68,15 @@ public:
virtual void sendGetPeers () = 0;
- virtual void applyLoadCharge (LoadType) = 0;
-
// VFALCO NOTE what's with this odd parameter passing? Why the static member?
//
/** Adjust this peer's load balance based on the type of load imposed.
@note Formerly named punishPeer
*/
+ virtual void charge (Resource::Charge const& fee) = 0;
+ static void charge (boost::weak_ptr & peer, Resource::Charge const& fee);
+ virtual void applyLoadCharge (LoadType) = 0;
static void applyLoadCharge (boost::weak_ptr & peerTOCharge, LoadType loadThatWasImposed);
virtual Json::Value getJson () = 0;
diff --git a/src/ripple_app/peers/PeerDoor.cpp b/src/ripple_app/peers/PeerDoor.cpp
index 76886c0a1..55bf5580c 100644
--- a/src/ripple_app/peers/PeerDoor.cpp
+++ b/src/ripple_app/peers/PeerDoor.cpp
@@ -25,9 +25,11 @@ class PeerDoorImp
, public LeakChecked
{
public:
- PeerDoorImp (Stoppable& parent, Kind kind, std::string const& ip, int port,
- boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context)
+ PeerDoorImp (Stoppable& parent, Resource::Manager& resourceManager,
+ Kind kind, std::string const& ip, int port,
+ boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context)
: PeerDoor (parent)
+ , m_resourceManager (resourceManager)
, m_kind (kind)
, m_ssl_context (ssl_context)
, mAcceptor (io_service, boost::asio::ip::tcp::endpoint (
@@ -56,8 +58,8 @@ public:
bool const requirePROXYHandshake (m_kind == sslAndPROXYRequired);
Peer::pointer new_connection (Peer::New (
- mAcceptor.get_io_service (), m_ssl_context,
- getApp().getPeers ().assignPeerId (),
+ m_resourceManager, mAcceptor.get_io_service (),
+ m_ssl_context, getApp().getPeers ().assignPeerId (),
isInbound, requirePROXYHandshake));
mAcceptor.async_accept (new_connection->getNativeSocket (),
@@ -123,6 +125,7 @@ public:
}
private:
+ Resource::Manager& m_resourceManager;
Kind m_kind;
boost::asio::ssl::context& m_ssl_context;
boost::asio::ip::tcp::acceptor mAcceptor;
@@ -138,8 +141,12 @@ PeerDoor::PeerDoor (Stoppable& parent)
//------------------------------------------------------------------------------
-PeerDoor* PeerDoor::New (Stoppable& parent, Kind kind, std::string const& ip, int port,
- boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context)
+PeerDoor* PeerDoor::New (Stoppable& parent,
+ Resource::Manager& resourceManager,
+ Kind kind, std::string const& ip, int port,
+ boost::asio::io_service& io_service,
+ boost::asio::ssl::context& ssl_context)
{
- return new PeerDoorImp (parent, kind, ip, port, io_service, ssl_context);
+ return new PeerDoorImp (parent, resourceManager,
+ kind, ip, port, io_service, ssl_context);
}
diff --git a/src/ripple_app/peers/PeerDoor.h b/src/ripple_app/peers/PeerDoor.h
index 2629edad2..77cfe200b 100644
--- a/src/ripple_app/peers/PeerDoor.h
+++ b/src/ripple_app/peers/PeerDoor.h
@@ -17,10 +17,13 @@
*/
//==============================================================================
-
#ifndef RIPPLE_PEERDOOR_H_INCLUDED
#define RIPPLE_PEERDOOR_H_INCLUDED
+namespace Resource {
+class Manager;
+}
+
/** Handles incoming connections from peers. */
class PeerDoor : public Stoppable
{
@@ -36,8 +39,11 @@ public:
sslAndPROXYRequired
};
- static PeerDoor* New (Stoppable& parent, Kind kind, std::string const& ip, int port,
- boost::asio::io_service& io_service, boost::asio::ssl::context& ssl_context);
+ static PeerDoor* New (Stoppable& parent,
+ Resource::Manager& resourceManager,
+ Kind kind, std::string const& ip, int port,
+ boost::asio::io_service& io_service,
+ boost::asio::ssl::context& ssl_context);
//virtual boost::asio::ssl::context& getSSLContext () = 0;
};
diff --git a/src/ripple_app/peers/Peers.cpp b/src/ripple_app/peers/Peers.cpp
index 509fadaf3..9fefb0993 100644
--- a/src/ripple_app/peers/Peers.cpp
+++ b/src/ripple_app/peers/Peers.cpp
@@ -42,6 +42,7 @@ public:
typedef std::map::value_type vtPeer;
typedef boost::unordered_map::value_type vtConMap;
+ Resource::Manager& m_resourceManager;
ScopedPointer m_peerFinder;
boost::asio::io_service& m_io_service;
@@ -88,9 +89,11 @@ public:
//--------------------------------------------------------------------------
PeersImp (Stoppable& parent,
- boost::asio::io_service& io_service,
- boost::asio::ssl::context& ssl_context)
+ Resource::Manager& resourceManager,
+ boost::asio::io_service& io_service,
+ boost::asio::ssl::context& ssl_context)
: Stoppable ("Peers", parent)
+ , m_resourceManager (resourceManager)
, m_peerFinder (add (PeerFinder::Manager::New (
*this, *this, LogJournal::get ())))
, m_io_service (io_service)
@@ -193,6 +196,7 @@ public:
if (peer->isConnected() &&
PeerFinder::PeerID (peer->getNodePublic()) == id)
{
+ peer->charge (Resource::feeUnwantedData);
peer->applyLoadCharge (LT_UnwantedData);
break;
}
@@ -639,7 +643,7 @@ Peer::pointer PeersImp::peerConnect (const std::string& strIp, int iPort)
bool const isInbound (false);
bool const requirePROXYHandshake (false);
- ppResult = Peer::New (m_io_service, m_ssl_context,
+ ppResult = Peer::New (m_resourceManager, m_io_service, m_ssl_context,
++mLastPeer, isInbound, requirePROXYHandshake);
mIpMap [pipPeer] = ppResult;
@@ -1093,9 +1097,10 @@ Peers::Peers ()
}
Peers* Peers::New (Stoppable& parent,
+ Resource::Manager& resourceManager,
boost::asio::io_service& io_service,
boost::asio::ssl::context& ssl_context)
{
- return new PeersImp (parent, io_service, ssl_context);
+ return new PeersImp (parent, resourceManager, io_service, ssl_context);
}
diff --git a/src/ripple_app/peers/Peers.h b/src/ripple_app/peers/Peers.h
index 7d3849216..b4db7187b 100644
--- a/src/ripple_app/peers/Peers.h
+++ b/src/ripple_app/peers/Peers.h
@@ -20,6 +20,10 @@
#ifndef RIPPLE_PEERS_H_INCLUDED
#define RIPPLE_PEERS_H_INCLUDED
+namespace Resource {
+class Manager;
+}
+
namespace PeerFinder {
class Manager;
}
@@ -29,8 +33,9 @@ class Peers : public PropertyStream::Source
{
public:
static Peers* New (Stoppable& parent,
- boost::asio::io_service& io_service,
- boost::asio::ssl::context& context);
+ Resource::Manager& resourceManager,
+ boost::asio::io_service& io_service,
+ boost::asio::ssl::context& context);
Peers ();
diff --git a/src/ripple_app/ripple_app.cpp b/src/ripple_app/ripple_app.cpp
index 960316a83..8a06dd1b9 100644
--- a/src/ripple_app/ripple_app.cpp
+++ b/src/ripple_app/ripple_app.cpp
@@ -36,6 +36,7 @@
// material in Ripple since it holds the Application object.
#include "../ripple/http/ripple_http.h"
+#include "../ripple/resource/ripple_resource.h"
#include "../ripple/rpc/ripple_rpc.h"
#include "../ripple/validators/ripple_validators.h"
diff --git a/src/ripple_app/ripple_app.h b/src/ripple_app/ripple_app.h
index 7c2441a34..bce23e9b1 100644
--- a/src/ripple_app/ripple_app.h
+++ b/src/ripple_app/ripple_app.h
@@ -62,8 +62,7 @@
//
#include "peers/PackedMessage.h"
-namespace ripple
-{
+namespace ripple {
// Order matters here. If you get compile errors,
// reorder the include lines until the order is correct.
diff --git a/src/ripple_app/ripple_app_pt2.cpp b/src/ripple_app/ripple_app_pt2.cpp
index f9191e588..6fe9b7ff2 100644
--- a/src/ripple_app/ripple_app_pt2.cpp
+++ b/src/ripple_app/ripple_app_pt2.cpp
@@ -22,8 +22,7 @@
#include "ripple_app.h"
-namespace ripple
-{
+namespace ripple {
#include "shamap/SHAMap.cpp" // Uses theApp
#include "shamap/SHAMapItem.cpp"
diff --git a/src/ripple_app/ripple_app_pt5.cpp b/src/ripple_app/ripple_app_pt5.cpp
index 7ae574f83..9ed318b46 100644
--- a/src/ripple_app/ripple_app_pt5.cpp
+++ b/src/ripple_app/ripple_app_pt5.cpp
@@ -24,10 +24,10 @@
#include "../ripple_net/ripple_net.h"
#include "../ripple/peerfinder/ripple_peerfinder.h"
+#include "../ripple/resource/ripple_resource.h"
#include "../ripple/validators/ripple_validators.h"
-namespace ripple
-{
+namespace ripple {
#include "ledger/LedgerTiming.cpp"
#include "ledger/AcceptedLedgerTx.cpp"
diff --git a/src/ripple_app/ripple_app_pt7.cpp b/src/ripple_app/ripple_app_pt7.cpp
index e53910ed6..a266ab4fd 100644
--- a/src/ripple_app/ripple_app_pt7.cpp
+++ b/src/ripple_app/ripple_app_pt7.cpp
@@ -22,6 +22,8 @@
#include "ripple_app.h"
+#include "../ripple/resource/ripple_resource.h"
+
namespace ripple
{
diff --git a/src/ripple_app/websocket/WSConnection.cpp b/src/ripple_app/websocket/WSConnection.cpp
index 195067456..1c85eb5d4 100644
--- a/src/ripple_app/websocket/WSConnection.cpp
+++ b/src/ripple_app/websocket/WSConnection.cpp
@@ -28,9 +28,12 @@ static std::string trimIP(const std::string& ip)
//------------------------------------------------------------------------------
-WSConnection::WSConnection (InfoSub::Source& source, bool isPublic,
- std::string const& remoteIP, boost::asio::io_service& io_service)
+WSConnection::WSConnection (Resource::Manager& resourceManager,
+ Resource::Consumer usage, InfoSub::Source& source, bool isPublic,
+ std::string const& remoteIP, boost::asio::io_service& io_service)
: InfoSub (source)
+ , m_resourceManager (resourceManager)
+ , m_usage (usage)
, m_isPublic (isPublic)
, m_remoteIP (remoteIP)
, m_receiveQueueMutex (this, "WSConnection", __FILE__, __LINE__)
@@ -110,12 +113,19 @@ void WSConnection::returnMessage (message_ptr ptr)
Json::Value WSConnection::invokeCommand (Json::Value& jvRequest)
{
- // VFALCO TODO Make LoadManager a ctor argument
+#if RIPPLE_USE_RESOURCE_MANAGER
+ if (m_usage.disconnect ())
+ {
+ disconnect ();
+ return rpcError (rpcSLOW_DOWN);
+ }
+#else
if (getApp().getLoadManager ().shouldCutoff (m_loadSource))
{
disconnect ();
return rpcError (rpcSLOW_DOWN);
}
+#endif
// Requests without "command" are invalid.
//
@@ -133,7 +143,11 @@ Json::Value WSConnection::invokeCommand (Json::Value& jvRequest)
jvResult["id"] = jvRequest["id"];
}
+#if RIPPLE_USE_RESOURCE_MANAGER
+ m_usage.charge (Resource::feeInvalidRPC);
+#else
getApp().getLoadManager ().applyLoadCharge (m_loadSource, LT_RPCInvalid);
+#endif
return jvResult;
}
@@ -155,6 +169,13 @@ Json::Value WSConnection::invokeCommand (Json::Value& jvRequest)
jvResult["result"] = mRPCHandler.doCommand (jvRequest, role, &loadType);
}
+#if RIPPLE_USE_RESOURCE_MANAGER
+ m_usage.charge (Resource::legacyFee (loadType));
+ if (m_usage.warn ())
+ {
+ jvResult["warning"] = "load";
+ }
+#else
// Debit/credit the load and see if we should include a warning.
//
if (getApp().getLoadManager ().applyLoadCharge (m_loadSource, loadType) &&
@@ -162,6 +183,7 @@ Json::Value WSConnection::invokeCommand (Json::Value& jvRequest)
{
jvResult["warning"] = "load";
}
+#endif
// Currently we will simply unwrap errors returned by the RPC
// API, in the future maybe we can make the responses
diff --git a/src/ripple_app/websocket/WSConnection.h b/src/ripple_app/websocket/WSConnection.h
index 44a5b8df6..c8d58edba 100644
--- a/src/ripple_app/websocket/WSConnection.h
+++ b/src/ripple_app/websocket/WSConnection.h
@@ -38,8 +38,9 @@ public:
protected:
typedef websocketpp::message::data::ptr message_ptr;
- WSConnection (InfoSub::Source& source, bool isPublic,
- std::string const& remoteIP, boost::asio::io_service& io_service);
+ WSConnection (Resource::Manager& resourceManager,
+ Resource::Consumer usage, InfoSub::Source& source, bool isPublic,
+ std::string const& remoteIP, boost::asio::io_service& io_service);
virtual ~WSConnection ();
@@ -54,6 +55,8 @@ public:
Json::Value invokeCommand (Json::Value& jvRequest);
protected:
+ Resource::Manager& m_resourceManager;
+ Resource::Consumer m_usage;
bool const m_isPublic;
std::string const m_remoteIP;
LockType m_receiveQueueMutex;
@@ -89,9 +92,21 @@ public:
typedef WSServerHandler server_type;
public:
- WSConnectionType (InfoSub::Source& source, server_type& serverHandler,
- connection_ptr const& cpConnection)
- : WSConnection (source,
+ static IPEndpoint from_address (boost::asio::ip::address const& addr)
+ {
+ boost::asio::ip::address_v4::bytes_type bytes (addr.to_v4().to_bytes());
+ IPEndpoint ep (IPEndpoint::V4 (bytes[0], bytes[1], bytes[2], bytes[3]), 0);
+ return ep;
+ }
+
+ WSConnectionType (Resource::Manager& resourceManager,
+ InfoSub::Source& source, server_type& serverHandler,
+ connection_ptr const& cpConnection)
+ : WSConnection (
+ resourceManager,
+ resourceManager.newInboundEndpoint (from_address (
+ cpConnection->get_socket ().lowest_layer ().remote_endpoint ().address ())),
+ source,
serverHandler.getPublic (),
cpConnection->get_socket ().lowest_layer ().remote_endpoint ().address ().to_string (),
cpConnection->get_io_service ())
diff --git a/src/ripple_app/websocket/WSDoor.cpp b/src/ripple_app/websocket/WSDoor.cpp
index 6f355f645..ba9a2bd15 100644
--- a/src/ripple_app/websocket/WSDoor.cpp
+++ b/src/ripple_app/websocket/WSDoor.cpp
@@ -39,11 +39,12 @@ SETUP_LOG (WSDoor)
class WSDoorImp : public WSDoor, protected Thread, LeakChecked
{
public:
- WSDoorImp (InfoSub::Source& source,
- std::string const& strIp, int iPort, bool bPublic,
- boost::asio::ssl::context& ssl_context)
+ WSDoorImp (Resource::Manager& resourceManager,
+ InfoSub::Source& source, std::string const& strIp,
+ int iPort, bool bPublic, boost::asio::ssl::context& ssl_context)
: WSDoor (source)
, Thread ("websocket")
+ , m_resourceManager (resourceManager)
, m_source (source)
, m_ssl_context (ssl_context)
, m_endpointLock (this, "WSDoor", __FILE__, __LINE__)
@@ -67,8 +68,8 @@ private:
(mPublic ? "Public" : "Private") % mIp % mPort);
websocketpp::server_autotls::handler::ptr handler (
- new WSServerHandler (m_source,
- m_ssl_context, mPublic));
+ new WSServerHandler (
+ m_resourceManager, m_source, m_ssl_context, mPublic));
{
ScopedLockType lock (m_endpointLock, __FILE__, __LINE__);
@@ -130,7 +131,8 @@ private:
private:
typedef RippleRecursiveMutex LockType;
typedef LockType::ScopedLockType ScopedLockType;
-
+
+ Resource::Manager& m_resourceManager;
InfoSub::Source& m_source;
boost::asio::ssl::context& m_ssl_context;
LockType m_endpointLock;
@@ -150,14 +152,16 @@ WSDoor::WSDoor (Stoppable& parent)
//------------------------------------------------------------------------------
-WSDoor* WSDoor::New (InfoSub::Source& source, std::string const& strIp,
- int iPort, bool bPublic, boost::asio::ssl::context& ssl_context)
+WSDoor* WSDoor::New (Resource::Manager& resourceManager,
+ InfoSub::Source& source, std::string const& strIp,
+ int iPort, bool bPublic, boost::asio::ssl::context& ssl_context)
{
ScopedPointer door;
try
{
- door = new WSDoorImp (source, strIp, iPort, bPublic, ssl_context);
+ door = new WSDoorImp (resourceManager,
+ source, strIp, iPort, bPublic, ssl_context);
}
catch (...)
{
diff --git a/src/ripple_app/websocket/WSDoor.h b/src/ripple_app/websocket/WSDoor.h
index 78bec2a56..90afb0876 100644
--- a/src/ripple_app/websocket/WSDoor.h
+++ b/src/ripple_app/websocket/WSDoor.h
@@ -30,8 +30,9 @@ protected:
public:
virtual ~WSDoor () { }
- static WSDoor* New (InfoSub::Source& source, std::string const& strIp,
- int iPort, bool bPublic, boost::asio::ssl::context& ssl_context);
+ static WSDoor* New (Resource::Manager& resourceManager,
+ InfoSub::Source& source, std::string const& strIp,
+ int iPort, bool bPublic, boost::asio::ssl::context& ssl_context);
};
#endif
diff --git a/src/ripple_app/websocket/WSServerHandler.h b/src/ripple_app/websocket/WSServerHandler.h
index ad91ffde3..1cb1f990d 100644
--- a/src/ripple_app/websocket/WSServerHandler.h
+++ b/src/ripple_app/websocket/WSServerHandler.h
@@ -56,6 +56,7 @@ public:
};
private:
+ Resource::Manager& m_resourceManager;
InfoSub::Source& m_source;
protected:
@@ -74,8 +75,10 @@ protected:
bool const mPublic;
public:
- WSServerHandler (InfoSub::Source& source, boost::asio::ssl::context& ssl_context, bool bPublic)
- : m_source (source)
+ WSServerHandler (Resource::Manager& resourceManager,
+ InfoSub::Source& source, boost::asio::ssl::context& ssl_context, bool bPublic)
+ : m_resourceManager (resourceManager)
+ , m_source (source)
, mLock (static_cast (this), "WSServerHandler", __FILE__, __LINE__)
, m_ssl_context (ssl_context)
, mPublic (bPublic)
@@ -181,7 +184,9 @@ public:
{
mMap [cpClient] = boost::make_shared <
WSConnectionType
- > (boost::ref (m_source), boost::ref(*this), boost::cref(cpClient));
+ > (boost::ref(m_resourceManager),
+ boost::ref (m_source),
+ boost::ref(*this), boost::cref(cpClient));
}
catch (...)
{
diff --git a/src/ripple_core/functional/LoadSource.h b/src/ripple_core/functional/LoadSource.h
index af7540543..f74e3e8b0 100644
--- a/src/ripple_core/functional/LoadSource.h
+++ b/src/ripple_core/functional/LoadSource.h
@@ -47,16 +47,6 @@
class LoadSource
{
public:
- // VFALCO TODO Use these dispositions
- /*
- enum Disposition
- {
- none,
- shouldWarn,
- shouldDrop,
- };
- */
-
/** Construct a load source.
Sources with admin privileges have relaxed or no restrictions
diff --git a/src/ripple_core/ripple_core.h b/src/ripple_core/ripple_core.h
index 05dcc2cf5..6985dc5f6 100644
--- a/src/ripple_core/ripple_core.h
+++ b/src/ripple_core/ripple_core.h
@@ -26,6 +26,7 @@
#include "beast/beast/http/URL.h" // for Config
+#include "../ripple/resource/api/LegacyFees.h"
#include "nodestore/NodeStore.h"
@@ -41,7 +42,6 @@ namespace ripple
# include "functional/LoadMonitor.h"
# include "functional/Job.h"
#include "functional/JobQueue.h"
-# include "functional/LoadType.h"
#include "functional/LoadSource.h"
}