diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index bc892ce01c..c5163f5a2a 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -1898,18 +1898,18 @@
True
-
+
-
-
-
-
-
-
-
+
+
+ True
+
+
+ True
+
@@ -3448,8 +3448,6 @@
-
-
..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)
..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index f31331d692..0282167f64 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -334,9 +334,6 @@
{8601C61D-413C-725E-C9E6-BD4F97E40032}
-
- {F98B3E94-4FB9-98FF-C625-533A969D1210}
-
{43D68742-4714-D103-EE00-EB10BD045FB6}
@@ -2856,24 +2853,21 @@
ripple\common\tests
-
- ripple\http\api
+
+ ripple\http
-
- ripple\http\api
-
-
- ripple\http\api
-
-
- ripple\http\api
-
-
- ripple\http\api
+
+ ripple\http
+
+ ripple\http\impl
+
ripple\http\impl
+
+ ripple\http\impl
+
ripple\http\impl
@@ -4740,9 +4734,6 @@
ripple\unity
-
- ripple\unity
-
ripple\unity
diff --git a/src/BeastConfig.h b/src/BeastConfig.h
index 2ffdf48e5f..1b0a014a6b 100644
--- a/src/BeastConfig.h
+++ b/src/BeastConfig.h
@@ -227,4 +227,10 @@
#define RIPPLE_STRUCTURED_OVERLAY 0
#endif
+/** Config: RIPPLE_ASYNC_RPC_HANDLER
+*/
+#ifndef RIPPLE_ASYNC_RPC_HANDLER
+#define RIPPLE_ASYNC_RPC_HANDLER 1
+#endif
+
#endif
diff --git a/src/ripple/common/MultiSocket.h b/src/ripple/common/MultiSocket.h
index d73c39a5e4..e116164d5c 100644
--- a/src/ripple/common/MultiSocket.h
+++ b/src/ripple/common/MultiSocket.h
@@ -96,15 +96,6 @@ public:
private:
int m_flags;
};
-
- enum Flags
- {
- none = 0,
- client_ssl = 1,
- server_ssl = 2,
- server_ssl_required = 4,
- server_proxy = 8
- };
typedef beast::asio::HandshakeDetectLogicPROXY::ProxyInfo ProxyInfo;
diff --git a/src/ripple/http/api/Server.h b/src/ripple/http/Server.h
similarity index 53%
rename from src/ripple/http/api/Server.h
rename to src/ripple/http/Server.h
index a657d414e9..10de42c116 100644
--- a/src/ripple/http/api/Server.h
+++ b/src/ripple/http/Server.h
@@ -20,13 +20,80 @@
#ifndef RIPPLE_HTTP_SERVER_H_INCLUDED
#define RIPPLE_HTTP_SERVER_H_INCLUDED
+#include
+#include
+#include
+#include
#include
#include
namespace ripple {
-
namespace HTTP {
+//------------------------------------------------------------------------------
+
+/** Configuration information for a server listening port. */
+struct Port
+{
+ enum Security
+ {
+ no_ssl,
+ allow_ssl,
+ require_ssl
+ };
+
+ Security security;
+ std::uint16_t port;
+ beast::IP::Endpoint addr;
+ beast::asio::SSLContext* context;
+
+ Port ();
+ Port (Port const& other);
+ Port& operator= (Port const& other);
+ Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
+ Security security_, beast::asio::SSLContext* context_);
+};
+
+bool operator== (Port const& lhs, Port const& rhs);
+bool operator< (Port const& lhs, Port const& rhs);
+
+/** A set of listening ports settings. */
+typedef std::vector Ports;
+
+//------------------------------------------------------------------------------
+
+class Server;
+class Session;
+
+/** Processes all sessions.
+ Thread safety:
+ Must be safe to call concurrently from any number of foreign threads.
+*/
+struct Handler
+{
+ /** Called when the connection is accepted and we know remoteAddress. */
+ virtual void onAccept (Session& session) = 0;
+
+ /** Called repeatedly as new HTTP headers are received.
+ Guaranteed to be called at least once.
+ */
+ virtual void onHeaders (Session& session) = 0;
+
+ /** Called when we have the full Content-Body. */
+ virtual void onRequest (Session& session) = 0;
+
+ /** Called when the session ends.
+ Guaranteed to be called once.
+ @param errorCode Non zero for a failed connection.
+ */
+ virtual void onClose (Session& session, int errorCode) = 0;
+
+ /** Called when the server has finished its stop. */
+ virtual void onStopped (Server& server) = 0;
+};
+
+//------------------------------------------------------------------------------
+
class ServerImpl;
/** Multi-threaded, asynchronous HTTP server. */
@@ -39,17 +106,19 @@ public:
/** Destroy the server.
This blocks until the server stops.
*/
- virtual ~Server ();
-
+ virtual
+ ~Server ();
/** Returns the Journal associated with the server. */
- beast::Journal const& journal () const;
+ beast::Journal
+ journal () const;
/** Returns the listening ports settings.
Thread safety:
Safe to call from any thread.
Cannot be called concurrently with setPorts.
*/
- Ports const& getPorts () const;
+ Ports const&
+ getPorts () const;
/** Set the listening ports settings.
These take effect immediately. Any current ports that are not in the
@@ -57,13 +126,15 @@ public:
Thread safety:
Cannot be called concurrently.
*/
- void setPorts (Ports const& ports);
+ void
+ setPorts (Ports const& ports);
/** Notify the server to stop, without blocking.
Thread safety:
Safe to call concurrently from any thread.
*/
- void stopAsync ();
+ void
+ stopAsync ();
/** Notify the server to stop, and block until the stop is complete.
The handler's onStopped method will be called when the stop completes.
@@ -71,13 +142,14 @@ public:
Cannot be called concurrently.
Cannot be called from the thread of execution of any Handler functions.
*/
- void stop ();
+ void
+ stop ();
private:
std::unique_ptr m_impl;
};
-} // namespace HTTP
-} // namespace ripple
+} // HTTP
+} // ripple
#endif
diff --git a/src/ripple/http/api/Session.h b/src/ripple/http/Session.h
similarity index 81%
rename from src/ripple/http/api/Session.h
rename to src/ripple/http/Session.h
index 92e3a97bb2..54542c5e61 100644
--- a/src/ripple/http/api/Session.h
+++ b/src/ripple/http/Session.h
@@ -24,13 +24,52 @@
#include
#include
#include
-
#include
namespace ripple {
namespace HTTP {
+class Session;
+
+/** Scoped ostream-based RAII container for building the HTTP response. */
+// VFALCO TODO Use abstract_ostream
+class ScopedStream
+{
+public:
+ explicit ScopedStream (Session& session);
+ ScopedStream (ScopedStream const& other);
+
+ template
+ ScopedStream (Session& session, T const& t)
+ : m_session (session)
+ {
+ m_ostream << t;
+ }
+
+ ScopedStream (Session& session, std::ostream& manip (std::ostream&));
+
+ ~ScopedStream ();
+
+ std::ostringstream& ostream () const;
+
+ std::ostream& operator<< (std::ostream& manip (std::ostream&)) const;
+
+ template
+ std::ostream& operator<< (T const& t) const
+ {
+ return m_ostream << t;
+ }
+
+private:
+ ScopedStream& operator= (ScopedStream const&); // disallowed
+
+ Session& m_session;
+ std::ostringstream mutable m_ostream;
+};
+
+//------------------------------------------------------------------------------
+
/** Persistent state information for a connection session.
These values are preserved between calls for efficiency.
Some fields are input parameters, some are output parameters,
diff --git a/src/ripple/http/api/Handler.h b/src/ripple/http/api/Handler.h
deleted file mode 100644
index d4155292f4..0000000000
--- a/src/ripple/http/api/Handler.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- 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_HTTP_HANDLER_H_INCLUDED
-#define RIPPLE_HTTP_HANDLER_H_INCLUDED
-
-namespace ripple {
-
-namespace HTTP {
-
-class Server;
-class Session;
-
-/** Processes all sessions.
- Thread safety:
- Must be safe to call concurrently from any number of foreign threads.
-*/
-struct Handler
-{
- /** Called when the connection is accepted and we know remoteAddress. */
- virtual void onAccept (Session& session) = 0;
-
- /** Called repeatedly as new HTTP headers are received.
- Guaranteed to be called at least once.
- */
- virtual void onHeaders (Session& session) = 0;
-
- /** Called when we have the full Content-Body. */
- virtual void onRequest (Session& session) = 0;
-
- /** Called when the session ends.
- Guaranteed to be called once.
- @param errorCode Non zero for a failed connection.
- */
- virtual void onClose (Session& session, int errorCode) = 0;
-
- /** Called when the server has finished its stop. */
- virtual void onStopped (Server& server) = 0;
-};
-
-} // namespace HTTP
-} // namespace ripple
-
-#endif
diff --git a/src/ripple/http/api/Port.h b/src/ripple/http/api/Port.h
deleted file mode 100644
index 74b9b9fe4c..0000000000
--- a/src/ripple/http/api/Port.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- 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_HTTP_PORT_H_INCLUDED
-#define RIPPLE_HTTP_PORT_H_INCLUDED
-
-#include
-#include
-
-#include
-
-namespace ripple {
-
-namespace HTTP {
-
-/** Configuration information for a server listening port. */
-struct Port
-{
- enum Security
- {
- no_ssl,
- allow_ssl,
- require_ssl
- };
-
- Port ();
- Port (Port const& other);
- Port& operator= (Port const& other);
- Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
- Security security_, beast::asio::SSLContext* context_);
-
- std::uint16_t port;
- beast::IP::Endpoint addr;
- Security security;
- beast::asio::SSLContext* context;
-};
-
-bool operator== (Port const& lhs, Port const& rhs);
-bool operator!= (Port const& lhs, Port const& rhs);
-bool operator< (Port const& lhs, Port const& rhs);
-bool operator<= (Port const& lhs, Port const& rhs);
-bool operator> (Port const& lhs, Port const& rhs);
-bool operator>= (Port const& lhs, Port const& rhs);
-
-/** A set of listening ports settings. */
-typedef std::vector Ports;
-
-} // namespace HTTP
-} // namespace ripple
-
-#endif
diff --git a/src/ripple/http/api/ScopedStream.h b/src/ripple/http/api/ScopedStream.h
deleted file mode 100644
index fdeb088f40..0000000000
--- a/src/ripple/http/api/ScopedStream.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- 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_HTTP_SCOPEDSTREAM_H_INCLUDED
-#define RIPPLE_HTTP_SCOPEDSTREAM_H_INCLUDED
-
-#include
-
-namespace ripple {
-
-namespace HTTP {
-
-class Session;
-
-/** Scoped ostream-based RAII container for building the HTTP response. */
-class ScopedStream
-{
-public:
- explicit ScopedStream (Session& session);
- ScopedStream (ScopedStream const& other);
-
- template
- ScopedStream (Session& session, T const& t)
- : m_session (session)
- {
- m_ostream << t;
- }
-
- ScopedStream (Session& session, std::ostream& manip (std::ostream&));
-
- ~ScopedStream ();
-
- std::ostringstream& ostream () const;
-
- std::ostream& operator<< (std::ostream& manip (std::ostream&)) const;
-
- template
- std::ostream& operator<< (T const& t) const
- {
- return m_ostream << t;
- }
-
-private:
- ScopedStream& operator= (ScopedStream const&); // disallowed
-
- Session& m_session;
- std::ostringstream mutable m_ostream;
-};
-
-} // namespace HTTP
-} // namespace ripple
-
-#endif
diff --git a/src/ripple/http/impl/Door.cpp b/src/ripple/http/impl/Door.cpp
new file mode 100644
index 0000000000..aa00157e0f
--- /dev/null
+++ b/src/ripple/http/impl/Door.cpp
@@ -0,0 +1,108 @@
+//------------------------------------------------------------------------------
+/*
+ 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
+#include
+#include
+
+namespace ripple {
+namespace HTTP {
+
+Door::Door (ServerImpl& impl, Port const& port)
+ : impl_ (impl)
+ , acceptor_ (impl_.get_io_service(), to_asio (port))
+ , port_ (port)
+{
+ impl_.add (*this);
+
+ error_code ec;
+
+ acceptor_.set_option (acceptor::reuse_address (true), ec);
+ if (ec)
+ {
+ impl_.journal().error <<
+ "Error setting acceptor socket option: " << ec.message();
+ }
+
+ if (! ec)
+ {
+ impl_.journal().info << "Bound to endpoint " <<
+ to_string (acceptor_.local_endpoint());
+
+ async_accept();
+ }
+ else
+ {
+ impl_.journal().error << "Error binding to endpoint " <<
+ to_string (acceptor_.local_endpoint()) <<
+ ", '" << ec.message() << "'";
+ }
+}
+
+Door::~Door ()
+{
+ impl_.remove (*this);
+}
+
+Port const&
+Door::port () const
+{
+ return port_;
+}
+
+void
+Door::cancel ()
+{
+ acceptor_.cancel();
+}
+
+void
+Door::failed (error_code ec)
+{
+}
+
+void
+Door::async_accept ()
+{
+ auto const peer (std::make_shared (impl_, port_));
+ acceptor_.async_accept (peer->get_socket(), std::bind (
+ &Door::handle_accept, Ptr(this),
+ beast::asio::placeholders::error, peer));
+}
+
+void
+Door::handle_accept (error_code ec,
+ std::shared_ptr const& peer)
+{
+ if (ec == boost::asio::error::operation_aborted)
+ return;
+
+ if (ec)
+ {
+ impl_.journal().error << "Accept failed: " << ec.message();
+ return;
+ }
+
+ async_accept();
+
+ peer->accept();
+}
+
+}
+}
diff --git a/src/ripple/http/impl/Door.h b/src/ripple/http/impl/Door.h
index d5267b1262..35a8f645eb 100644
--- a/src/ripple/http/impl/Door.h
+++ b/src/ripple/http/impl/Door.h
@@ -20,6 +20,8 @@
#ifndef RIPPLE_HTTP_DOOR_H_INCLUDED
#define RIPPLE_HTTP_DOOR_H_INCLUDED
+#include
+#include
#include
namespace ripple {
@@ -28,95 +30,37 @@ namespace HTTP {
/** A listening socket. */
class Door
: public beast::SharedObject
- , public beast::asio::AsyncObject
, public beast::List ::Node
, public beast::LeakChecked
{
-public:
+private:
+ // VFALCO TODO Use shared_ptr
typedef beast::SharedPtr Ptr;
- ServerImpl& m_impl;
- acceptor m_acceptor;
- Port m_port;
+ ServerImpl& impl_;
+ acceptor acceptor_;
+ Port port_;
- Door (ServerImpl& impl, Port const& port)
- : m_impl (impl)
- , m_acceptor (m_impl.get_io_service(), to_asio (port))
- , m_port (port)
- {
- m_impl.add (*this);
+public:
+ Door (ServerImpl& impl, Port const& port);
- error_code ec;
+ ~Door ();
- m_acceptor.set_option (acceptor::reuse_address (true), ec);
- if (ec)
- {
- m_impl.journal().error <<
- "Error setting acceptor socket option: " << ec.message();
- }
+ Port const&
+ port () const;
- if (! ec)
- {
- m_impl.journal().info << "Bound to endpoint " <<
- to_string (m_acceptor.local_endpoint());
+ void
+ cancel ();
- async_accept();
- }
- else
- {
- m_impl.journal().error << "Error binding to endpoint " <<
- to_string (m_acceptor.local_endpoint()) <<
- ", '" << ec.message() << "'";
- }
- }
+ void
+ failed (error_code ec);
- ~Door ()
- {
- m_impl.remove (*this);
- }
+ void
+ async_accept ();
- Port const& port () const
- {
- return m_port;
- }
-
- void cancel ()
- {
- m_acceptor.cancel();
- }
-
- void failed (error_code ec)
- {
- }
-
- void asyncHandlersComplete ()
- {
- }
-
- void async_accept ()
- {
- Peer* peer (new Peer (m_impl, m_port));
- m_acceptor.async_accept (peer->get_socket(), std::bind (
- &Door::handle_accept, Ptr(this),
- beast::asio::placeholders::error,
- Peer::Ptr (peer), CompletionCounter (this)));
- }
-
- void handle_accept (error_code ec, Peer::Ptr peer, CompletionCounter)
- {
- if (ec == boost::asio::error::operation_aborted)
- return;
-
- if (ec)
- {
- m_impl.journal().error << "Accept failed: " << ec.message();
- return;
- }
-
- async_accept();
-
- peer->handle_accept();
- }
+ void
+ handle_accept (error_code ec,
+ std::shared_ptr const& peer);
};
}
diff --git a/src/ripple/http/impl/Peer.cpp b/src/ripple/http/impl/Peer.cpp
new file mode 100644
index 0000000000..9af4e62811
--- /dev/null
+++ b/src/ripple/http/impl/Peer.cpp
@@ -0,0 +1,409 @@
+//------------------------------------------------------------------------------
+/*
+ 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 HTTP {
+
+Peer::Peer (ServerImpl& impl, Port const& port)
+ : impl_ (impl)
+ , strand_ (impl_.get_io_service())
+ , data_timer_ (impl_.get_io_service())
+ , request_timer_ (impl_.get_io_service())
+ , buffer_ (bufferSize)
+ , writesPending_ (0)
+ , closed_ (false)
+ , callClose_ (false)
+ , errorCode_ (0)
+ , detached_ (0)
+{
+ tag = nullptr;
+
+ int flags = MultiSocket::Flag::server_role;
+ switch (port.security)
+ {
+ default:
+ bassertfalse;
+
+ case Port::no_ssl:
+ break;
+
+ case Port::allow_ssl:
+ flags |= MultiSocket::Flag::ssl;
+ break;
+
+ case Port::require_ssl:
+ flags |= MultiSocket::Flag::ssl_required;
+ break;
+ }
+
+ socket_.reset (MultiSocket::New (
+ impl_.get_io_service(), port.context->get(), flags));
+
+ impl_.add (*this);
+}
+
+Peer::~Peer ()
+{
+ if (callClose_)
+ impl_.handler().onClose (session(), errorCode_);
+
+ impl_.remove (*this);
+}
+
+//--------------------------------------------------------------------------
+
+// Returns the Content-Body as a single buffer.
+// VFALCO NOTE This is inefficient...
+std::string
+Peer::content()
+{
+ std::string s;
+ beast::DynamicBuffer const& body (
+ parser_.request()->body ());
+ s.resize (body.size ());
+ boost::asio::buffer_copy (
+ boost::asio::buffer (&s[0],
+ s.size()), body.data ());
+ return s;
+}
+
+// Send a copy of the data.
+void
+Peer::write (void const* buffer, std::size_t bytes)
+{
+ // Make sure this happens on an io_service thread.
+ impl_.get_io_service().dispatch (strand_.wrap (
+ std::bind (&Peer::async_write, shared_from_this(),
+ SharedBuffer (static_cast (buffer), bytes))));
+}
+
+// Make the Session asynchronous
+void
+Peer::detach ()
+{
+ if (detached_.exchange (1) == 0)
+ {
+ bassert (! work_);
+ bassert (detach_ref_ == nullptr);
+
+ // Maintain an additional reference while detached
+ detach_ref_ = shared_from_this();
+
+ // Prevent the io_service from running out of work.
+ // The work object will be destroyed with the Peer
+ // after the Session is closed and handlers complete.
+ //
+ work_ = boost::in_place (std::ref (
+ impl_.get_io_service()));
+ }
+}
+
+// Called by the Handler to close the session.
+void
+Peer::close ()
+{
+ // Make sure this happens on an io_service thread.
+ impl_.get_io_service().dispatch (strand_.wrap (
+ std::bind (&Peer::handle_close, shared_from_this())));
+}
+
+//--------------------------------------------------------------------------
+
+// Called when the handshake completes
+//
+void
+Peer::handle_handshake (error_code ec)
+{
+ if (ec == boost::asio::error::operation_aborted)
+ return;
+
+ if (ec != 0)
+ {
+ failed (ec);
+ return;
+ }
+
+ async_read_some();
+}
+
+// Called when the data timer expires
+//
+void
+Peer::handle_data_timer (error_code ec)
+{
+ if (ec == boost::asio::error::operation_aborted)
+ return;
+
+ if (closed_)
+ return;
+
+ if (ec != 0)
+ {
+ failed (ec);
+ return;
+ }
+
+ failed (boost::system::errc::make_error_code (
+ boost::system::errc::timed_out));
+}
+
+// Called when the request timer expires
+//
+void
+Peer::handle_request_timer (error_code ec)
+{
+ if (ec == boost::asio::error::operation_aborted)
+ return;
+
+ if (closed_)
+ return;
+
+ if (ec != 0)
+ {
+ failed (ec);
+ return;
+ }
+
+ failed (boost::system::errc::make_error_code (
+ boost::system::errc::timed_out));
+}
+
+// Called when async_write completes.
+void
+Peer::handle_write (error_code ec, std::size_t bytes_transferred,
+ SharedBuffer const& buf)
+{
+ if (ec == boost::asio::error::operation_aborted)
+ return;
+
+ if (ec != 0)
+ {
+ failed (ec);
+ return;
+ }
+
+ bassert (writesPending_ > 0);
+ if (--writesPending_ == 0 && closed_)
+ socket_->shutdown (socket::shutdown_send);
+}
+
+// Called when async_read_some completes.
+void
+Peer::handle_read (error_code ec, std::size_t bytes_transferred)
+{
+ if (ec == boost::asio::error::operation_aborted)
+ return;
+
+ if (ec != 0 && ec != boost::asio::error::eof)
+ {
+ failed (ec);
+ return;
+ }
+
+ std::size_t const bytes_parsed (parser_.process (
+ buffer_.getData(), bytes_transferred));
+
+ if (parser_.error() ||
+ bytes_parsed != bytes_transferred)
+ {
+ failed (boost::system::errc::make_error_code (
+ boost::system::errc::bad_message));
+ return;
+ }
+
+ if (ec == boost::asio::error::eof)
+ {
+ parser_.process_eof();
+ ec = error_code();
+ }
+
+ if (parser_.error())
+ {
+ failed (boost::system::errc::make_error_code (
+ boost::system::errc::bad_message));
+ return;
+ }
+
+ if (! parser_.finished())
+ {
+ // Feed some headers to the callback
+ if (parser_.fields().size() > 0)
+ {
+ handle_headers();
+ if (closed_)
+ return;
+ }
+ }
+
+ if (parser_.finished ())
+ {
+ data_timer_.cancel();
+ // VFALCO NOTE: Should we cancel this one?
+ request_timer_.cancel();
+
+ if (! socket_->needs_handshake())
+ socket_->shutdown (socket::shutdown_receive);
+
+ handle_request ();
+ return;
+ }
+
+ async_read_some();
+}
+
+// Called when we have some new headers.
+void
+Peer::handle_headers ()
+{
+ impl_.handler().onHeaders (session());
+}
+
+// Called when we have a complete http request.
+void
+Peer::handle_request ()
+{
+ // This is to guarantee onHeaders is called at least once.
+ handle_headers();
+
+ if (closed_)
+ return;
+
+ // Process the HTTPRequest
+ impl_.handler().onRequest (session());
+}
+
+// Called to close the session.
+void
+Peer::handle_close ()
+{
+ closed_ = true;
+
+ // Release our additional reference
+ detach_ref_.reset();
+}
+
+//--------------------------------------------------------------------------
+//
+// Peer
+//
+
+// Called when the acceptor accepts our socket.
+void
+Peer::accept ()
+{
+ callClose_ = true;
+
+ impl_.handler().onAccept (session());
+
+ if (closed_)
+ {
+ cancel();
+ return;
+ }
+
+ request_timer_.expires_from_now (
+ boost::posix_time::seconds (
+ requestTimeoutSeconds));
+
+ request_timer_.async_wait (strand_.wrap (std::bind (
+ &Peer::handle_request_timer, shared_from_this(),
+ beast::asio::placeholders::error)));
+
+ if (socket_->needs_handshake ())
+ {
+ socket_->async_handshake (beast::asio::abstract_socket::server,
+ strand_.wrap (std::bind (&Peer::handle_handshake, shared_from_this(),
+ beast::asio::placeholders::error)));
+ }
+ else
+ {
+ async_read_some();
+ }
+}
+
+// Cancel all pending i/o and timers and send tcp shutdown.
+void
+Peer::cancel ()
+{
+ error_code ec;
+ data_timer_.cancel (ec);
+ request_timer_.cancel (ec);
+ socket_->cancel (ec);
+ socket_->shutdown (socket::shutdown_both);
+}
+
+// Called by a completion handler when error is not eof or aborted.
+void
+Peer::failed (error_code const& ec)
+{
+ errorCode_ = ec.value();
+ bassert (errorCode_ != 0);
+ cancel ();
+}
+
+// Call the async_read_some initiating function.
+void
+Peer::async_read_some ()
+{
+ // re-arm the data timer
+ // (this cancels the previous wait, if any)
+ //
+ data_timer_.expires_from_now (
+ boost::posix_time::seconds (
+ dataTimeoutSeconds));
+
+ data_timer_.async_wait (strand_.wrap (std::bind (
+ &Peer::handle_data_timer, shared_from_this(),
+ beast::asio::placeholders::error)));
+
+ // issue the read
+ //
+ boost::asio::mutable_buffers_1 buf (
+ buffer_.getData (), buffer_.getSize ());
+
+ socket_->async_read_some (buf, strand_.wrap (
+ std::bind (&Peer::handle_read, shared_from_this(),
+ beast::asio::placeholders::error,
+ beast::asio::placeholders::bytes_transferred)));
+}
+
+// Send a shared buffer
+void
+Peer::async_write (SharedBuffer const& buf)
+{
+ bassert (buf.get().size() > 0);
+
+ ++writesPending_;
+
+ // Send the copy. We pass the SharedBuffer in the last parameter
+ // so that a reference is maintained as the handler gets copied.
+ // When the final completion function returns, the reference
+ // count will drop to zero and the buffer will be freed.
+ //
+ boost::asio::async_write (*socket_,
+ boost::asio::const_buffers_1 (&(*buf)[0], buf->size()),
+ strand_.wrap (std::bind (&Peer::handle_write,
+ shared_from_this(), beast::asio::placeholders::error,
+ beast::asio::placeholders::bytes_transferred, buf)));
+}
+
+}
+}
diff --git a/src/ripple/http/impl/Peer.h b/src/ripple/http/impl/Peer.h
index 2c56564c23..427aab4c8c 100644
--- a/src/ripple/http/impl/Peer.h
+++ b/src/ripple/http/impl/Peer.h
@@ -20,29 +20,34 @@
#ifndef RIPPLE_HTTP_PEER_H_INCLUDED
#define RIPPLE_HTTP_PEER_H_INCLUDED
-#include
+#include
+#include
+#include
+#include
#include
-#include
+#include
+#include
#include
#include
-#include
+#include
#include
namespace ripple {
namespace HTTP {
// Holds the copy of buffers being sent
+// VFALCO TODO Replace with std::shared_ptr
+//
typedef beast::asio::SharedArg SharedBuffer;
/** Represents an active connection. */
class Peer
- : public beast::SharedObject
- , public beast::asio::AsyncObject
+ : public std::enable_shared_from_this
, public Session
, public beast::List ::Node
, public beast::LeakChecked
{
-public:
+private:
enum
{
// Size of our receive buffer
@@ -59,462 +64,138 @@ public:
};
- typedef beast::SharedPtr Ptr;
+ ServerImpl& impl_;
+ boost::asio::io_service::strand strand_;
+ boost::asio::deadline_timer data_timer_;
+ boost::asio::deadline_timer request_timer_;
+ std::unique_ptr socket_;
- ServerImpl& m_impl;
- boost::asio::io_service::strand m_strand;
- boost::asio::deadline_timer m_data_timer;
- boost::asio::deadline_timer m_request_timer;
- std::unique_ptr m_socket;
- beast::MemoryBlock m_buffer;
- beast::HTTPRequestParser m_parser;
- int m_writesPending;
- bool m_closed;
- bool m_callClose;
- beast::SharedPtr m_detach_ref;
- boost::optional m_work;
- int m_errorCode;
- std::atomic m_detached;
+ // VFALCO TODO Use c++11
+ beast::MemoryBlock buffer_;
+
+ beast::HTTPRequestParser parser_;
+ int writesPending_;
+ bool closed_;
+ bool callClose_;
+ std::shared_ptr detach_ref_;
+ boost::optional work_;
+ int errorCode_;
+ std::atomic detached_;
//--------------------------------------------------------------------------
- Peer (ServerImpl& impl, Port const& port)
- : m_impl (impl)
- , m_strand (m_impl.get_io_service())
- , m_data_timer (m_impl.get_io_service())
- , m_request_timer (m_impl.get_io_service())
- , m_buffer (bufferSize)
- , m_writesPending (0)
- , m_closed (false)
- , m_callClose (false)
- , m_errorCode (0)
- , m_detached (0)
- {
- tag = nullptr;
-
- int flags;
- switch (port.security)
- {
- default:
- bassertfalse;
- case Port::no_ssl: flags = MultiSocket::none; break;
- case Port::allow_ssl: flags = MultiSocket::server_ssl; break;
- case Port::require_ssl: flags = MultiSocket::server_ssl_required; break;
- }
-
- m_socket.reset (MultiSocket::New (
- m_impl.get_io_service(), port.context->get(), flags));
-
- m_impl.add (*this);
- }
-
- ~Peer ()
- {
- if (m_callClose)
- m_impl.handler().onClose (session(), m_errorCode);
-
- m_impl.remove (*this);
- }
+public:
+ Peer (ServerImpl& impl, Port const& port);
+ ~Peer ();
+private:
//--------------------------------------------------------------------------
//
// Session
//
- beast::Journal journal()
+ beast::Journal
+ journal()
{
- return m_impl.journal();
+ return impl_.journal();
}
- beast::IP::Endpoint remoteAddress()
+ beast::IP::Endpoint
+ remoteAddress()
{
return from_asio (get_socket().remote_endpoint());
}
- bool headersComplete()
+ bool
+ headersComplete()
{
- return m_parser.headersComplete();
+ return parser_.headersComplete();
}
- beast::HTTPHeaders headers()
+ beast::HTTPHeaders
+ headers()
{
- return beast::HTTPHeaders (m_parser.fields());
+ return beast::HTTPHeaders (parser_.fields());
}
- beast::SharedPtr const& request()
+ beast::SharedPtr const&
+ request()
{
- return m_parser.request();
+ return parser_.request();
}
- // Returns the Content-Body as a single buffer.
- // VFALCO NOTE This is inefficient...
- std::string content()
- {
- std::string s;
- beast::DynamicBuffer const& body (
- m_parser.request()->body ());
- s.resize (body.size ());
- boost::asio::buffer_copy (
- boost::asio::buffer (&s[0],
- s.size()), body.data ());
- return s;
- }
+ std::string
+ content();
- // Send a copy of the data.
- void write (void const* buffer, std::size_t bytes)
- {
- // Make sure this happens on an io_service thread.
- m_impl.get_io_service().dispatch (m_strand.wrap (
- boost::bind (&Peer::handle_write, Ptr (this),
- SharedBuffer (static_cast (buffer), bytes),
- CompletionCounter (this))));
- }
+ void
+ write (void const* buffer, std::size_t bytes);
- // Make the Session asynchronous
- void detach ()
- {
- if (m_detached.exchange (1) == 0)
- {
- bassert (! m_work);
- bassert (m_detach_ref.empty());
+ void
+ detach ();
- // Maintain an additional reference while detached
- m_detach_ref = this;
-
- // Prevent the io_service from running out of work.
- // The work object will be destroyed with the Peer
- // after the Session is closed and handlers complete.
- //
- m_work = boost::in_place (std::ref (
- m_impl.get_io_service()));
- }
- }
-
- // Called by the Handler to close the session.
- void close ()
- {
- // Make sure this happens on an io_service thread.
- m_impl.get_io_service().dispatch (m_strand.wrap (
- boost::bind (&Peer::handle_close, Ptr (this),
- CompletionCounter (this))));
- }
+ void
+ close ();
//--------------------------------------------------------------------------
//
// Completion Handlers
//
- // Called when the last pending completion handler returns.
- void asyncHandlersComplete ()
- {
- }
+ void
+ handle_handshake (error_code ec);
- // Called when the acceptor accepts our socket.
- void handle_accept ()
- {
- m_callClose = true;
+ void
+ handle_data_timer (error_code ec);
- m_impl.handler().onAccept (session());
+ void
+ handle_request_timer (error_code ec);
- if (m_closed)
- {
- cancel();
- return;
- }
+ void
+ handle_write (error_code ec, std::size_t bytes_transferred,
+ SharedBuffer const& buf);
- m_request_timer.expires_from_now (
- boost::posix_time::seconds (
- requestTimeoutSeconds));
+ void
+ handle_read (error_code ec, std::size_t bytes_transferred);
- m_request_timer.async_wait (m_strand.wrap (boost::bind (
- &Peer::handle_request_timer, Ptr(this),
- boost::asio::placeholders::error,
- CompletionCounter (this))));
+ void
+ handle_headers ();
- if (m_socket->needs_handshake ())
- {
- m_socket->async_handshake (beast::asio::abstract_socket::server,
- m_strand.wrap (boost::bind (&Peer::handle_handshake, Ptr(this),
- boost::asio::placeholders::error,
- CompletionCounter (this))));
- }
- else
- {
- async_read_some();
- }
- }
+ void
+ handle_request ();
- // Called from an io_service thread to write the shared buffer.
- void handle_write (SharedBuffer const& buf, CompletionCounter)
- {
- async_write (buf);
- }
-
- // Called when the handshake completes
- //
- void handle_handshake (error_code ec, CompletionCounter)
- {
- if (ec == boost::asio::error::operation_aborted)
- return;
-
- if (ec != 0)
- {
- failed (ec);
- return;
- }
-
- async_read_some();
- }
-
- // Called when the data timer expires
- //
- void handle_data_timer (error_code ec, CompletionCounter)
- {
- if (ec == boost::asio::error::operation_aborted)
- return;
-
- if (m_closed)
- return;
-
- if (ec != 0)
- {
- failed (ec);
- return;
- }
-
- failed (boost::system::errc::make_error_code (
- boost::system::errc::timed_out));
- }
-
- // Called when the request timer expires
- //
- void handle_request_timer (error_code ec, CompletionCounter)
- {
- if (ec == boost::asio::error::operation_aborted)
- return;
-
- if (m_closed)
- return;
-
- if (ec != 0)
- {
- failed (ec);
- return;
- }
-
- failed (boost::system::errc::make_error_code (
- boost::system::errc::timed_out));
- }
-
- // Called when async_write completes.
- void handle_write (error_code ec, std::size_t bytes_transferred,
- SharedBuffer buf, CompletionCounter)
- {
- if (ec == boost::asio::error::operation_aborted)
- return;
-
- if (ec != 0)
- {
- failed (ec);
- return;
- }
-
- bassert (m_writesPending > 0);
- if (--m_writesPending == 0 && m_closed)
- m_socket->shutdown (socket::shutdown_send);
- }
-
- // Called when async_read_some completes.
- void handle_read (error_code ec, std::size_t bytes_transferred, CompletionCounter)
- {
- if (ec == boost::asio::error::operation_aborted)
- return;
-
- if (ec != 0 && ec != boost::asio::error::eof)
- {
- failed (ec);
- return;
- }
-
- std::size_t const bytes_parsed (m_parser.process (
- m_buffer.getData(), bytes_transferred));
-
- if (m_parser.error() ||
- bytes_parsed != bytes_transferred)
- {
- failed (boost::system::errc::make_error_code (
- boost::system::errc::bad_message));
- return;
- }
-
- if (ec == boost::asio::error::eof)
- {
- m_parser.process_eof();
- ec = error_code();
- }
-
- if (m_parser.error())
- {
- failed (boost::system::errc::make_error_code (
- boost::system::errc::bad_message));
- return;
- }
-
- if (! m_parser.finished())
- {
- // Feed some headers to the callback
- if (m_parser.fields().size() > 0)
- {
- handle_headers();
- if (m_closed)
- return;
- }
- }
-
- if (m_parser.finished ())
- {
- m_data_timer.cancel();
- // VFALCO NOTE: Should we cancel this one?
- m_request_timer.cancel();
-
- if (! m_socket->needs_handshake())
- m_socket->shutdown (socket::shutdown_receive);
-
- handle_request ();
- return;
- }
-
- async_read_some();
- }
-
- // Called when we have some new headers.
- void handle_headers ()
- {
- m_impl.handler().onHeaders (session());
- }
-
- // Called when we have a complete http request.
- void handle_request ()
- {
- // This is to guarantee onHeaders is called at least once.
- handle_headers();
-
- if (m_closed)
- return;
-
- // Process the HTTPRequest
- m_impl.handler().onRequest (session());
- }
-
- // Called to close the session.
- void handle_close (CompletionCounter)
- {
- m_closed = true;
-
- // Release our additional reference
- m_detach_ref = nullptr;
- }
+ void
+ handle_close ();
+public:
//--------------------------------------------------------------------------
//
// Peer
//
-
- // Returns the asio socket for the peer.
- socket& get_socket()
+ socket&
+ get_socket()
{
- return m_socket->this_layer();
+ return socket_->this_layer();
}
- // Return the Session associated with this peer's session.
- Session& session ()
+ Session&
+ session ()
{
return *this;
}
- // Cancel all pending i/o and timers and send tcp shutdown.
- void cancel ()
- {
- error_code ec;
- m_data_timer.cancel (ec);
- m_request_timer.cancel (ec);
- m_socket->cancel (ec);
- m_socket->shutdown (socket::shutdown_both);
- }
+ void
+ accept ();
- // Called by a completion handler when error is not eof or aborted.
- void failed (error_code const& ec)
- {
- m_errorCode = ec.value();
- bassert (m_errorCode != 0);
- cancel ();
- }
+ void
+ cancel ();
- // Call the async_read_some initiating function.
- void async_read_some ()
- {
- // re-arm the data timer
- // (this cancels the previous wait, if any)
- //
- m_data_timer.expires_from_now (
- boost::posix_time::seconds (
- dataTimeoutSeconds));
+ void
+ failed (error_code const& ec);
- m_data_timer.async_wait (m_strand.wrap (boost::bind (
- &Peer::handle_data_timer, Ptr(this),
- boost::asio::placeholders::error,
- CompletionCounter (this))));
+ void
+ async_read_some ();
- // issue the read
- //
- boost::asio::mutable_buffers_1 buf (
- m_buffer.getData (), m_buffer.getSize ());
-
- m_socket->async_read_some (buf, m_strand.wrap (
- boost::bind (&Peer::handle_read, Ptr (this),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred,
- CompletionCounter (this))));
- }
-
- // Send a shared buffer
- void async_write (SharedBuffer const& buf)
- {
- bassert (buf.get().size() > 0);
-
- ++m_writesPending;
-
- // Send the copy. We pass the SharedBuffer in the last parameter
- // so that a reference is maintained as the handler gets copied.
- // When the final completion function returns, the reference
- // count will drop to zero and the buffer will be freed.
- //
- boost::asio::async_write (*m_socket,
- boost::asio::const_buffers_1 (&(*buf)[0], buf->size()),
- m_strand.wrap (boost::bind (&Peer::handle_write,
- Ptr (this), boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred,
- buf, CompletionCounter (this))));
- }
-
- // Send a copy of a BufferSequence
- template
- void async_write (BufferSequence const& buffers)
- {
- // Iterate over each linear vector in the BufferSequence.
- for (typename BufferSequence::const_iterator iter (buffers.begin());
- iter != buffers.end(); ++iter)
- {
- typename BufferSequence::value_type const& buffer (*iter);
-
- // Put a copy of this section of the buffer sequence into
- // a reference counted, shared container.
- //
- async_write (SharedBuffer (
- boost::asio::buffer_cast (buffer),
- boost::asio::buffer_size (buffer)));
- }
- }
+ void async_write (SharedBuffer const& buf);
};
}
diff --git a/src/ripple/http/impl/Port.cpp b/src/ripple/http/impl/Port.cpp
index 136727849d..629250ca1a 100644
--- a/src/ripple/http/impl/Port.cpp
+++ b/src/ripple/http/impl/Port.cpp
@@ -21,16 +21,16 @@ namespace ripple {
namespace HTTP {
Port::Port ()
- : port (0)
- , security (no_ssl)
+ : security (no_ssl)
+ , port (0)
, context (nullptr)
{
}
Port::Port (Port const& other)
- : port (other.port)
+ : security (other.security)
+ , port (other.port)
, addr (other.addr)
- , security (other.security)
, context (other.context)
{
}
@@ -44,14 +44,11 @@ Port& Port::operator= (Port const& other)
return *this;
}
-Port::Port (
- std::uint16_t port_,
- beast::IP::Endpoint const& addr_,
- Security security_,
- beast::asio::SSLContext* context_)
- : port (port_)
+Port::Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
+ Security security_, beast::asio::SSLContext* context_)
+ : security (security_)
+ , port (port_)
, addr (addr_)
- , security (security_)
, context (context_)
{
}
@@ -88,18 +85,5 @@ bool operator< (Port const& lhs, Port const& rhs)
return true;
}
-bool operator!= (Port const& lhs, Port const& rhs)
- { return ! (lhs == rhs); }
-
-bool operator> (Port const& lhs, Port const& rhs)
- { return rhs < lhs; }
-
-bool operator<= (Port const& lhs, Port const& rhs)
- { return ! (rhs < lhs); }
-
-bool operator>= (Port const& lhs, Port const& rhs)
- { return ! (lhs < rhs); }
-
-
}
}
diff --git a/src/ripple/http/impl/Server.cpp b/src/ripple/http/impl/Server.cpp
index 79a2235f94..cbceaf7350 100644
--- a/src/ripple/http/impl/Server.cpp
+++ b/src/ripple/http/impl/Server.cpp
@@ -17,11 +17,15 @@
*/
//==============================================================================
+#include
+#include
+#include //
+
namespace ripple {
namespace HTTP {
Server::Server (Handler& handler, beast::Journal journal)
- : m_impl (new ServerImpl (*this, handler, journal))
+ : m_impl (std::make_unique (*this, handler, journal))
{
}
@@ -30,27 +34,32 @@ Server::~Server ()
stop();
}
-beast::Journal const& Server::journal () const
+beast::Journal
+Server::journal () const
{
return m_impl->journal();
}
-Ports const& Server::getPorts () const
+Ports const&
+Server::getPorts () const
{
return m_impl->getPorts();
}
-void Server::setPorts (Ports const& ports)
+void
+Server::setPorts (Ports const& ports)
{
m_impl->setPorts (ports);
}
-void Server::stopAsync ()
+void
+Server::stopAsync ()
{
m_impl->stop(false);
}
-void Server::stop ()
+void
+Server::stop ()
{
m_impl->stop(true);
}
diff --git a/src/ripple/http/impl/ServerImpl.cpp b/src/ripple/http/impl/ServerImpl.cpp
index 21cbc3beed..f77ff26d1f 100644
--- a/src/ripple/http/impl/ServerImpl.cpp
+++ b/src/ripple/http/impl/ServerImpl.cpp
@@ -17,6 +17,8 @@
*/
//==============================================================================
+#include
+
namespace ripple {
namespace HTTP {
@@ -24,7 +26,7 @@ ServerImpl::ServerImpl (Server& server, Handler& handler, beast::Journal journal
: Thread ("HTTP::Server")
, m_server (server)
, m_handler (handler)
- , m_journal (journal)
+ , journal_ (journal)
, m_strand (m_io_service)
, m_work (boost::in_place (std::ref (m_io_service)))
, m_stopped (true)
@@ -37,11 +39,6 @@ ServerImpl::~ServerImpl ()
stopThread ();
}
-beast::Journal const& ServerImpl::journal() const
-{
- return m_journal;
-}
-
Ports const& ServerImpl::getPorts () const
{
SharedState::ConstUnlockedAccess state (m_state);
@@ -129,7 +126,7 @@ int ServerImpl::compare (Port const& lhs, Port const& rhs)
{
if (lhs < rhs)
return -1;
- else if (lhs > rhs)
+ else if (rhs < lhs)
return 1;
return 0;
}
diff --git a/src/ripple/http/impl/ServerImpl.h b/src/ripple/http/impl/ServerImpl.h
index 8eaa6d7c74..0443b32215 100644
--- a/src/ripple/http/impl/ServerImpl.h
+++ b/src/ripple/http/impl/ServerImpl.h
@@ -20,8 +20,14 @@
#ifndef RIPPLE_HTTP_SERVERIMPL_H_INCLUDED
#define RIPPLE_HTTP_SERVERIMPL_H_INCLUDED
+#include
+#include
+#include
#include
#include
+#include
+#include
+#include
namespace ripple {
namespace HTTP {
@@ -31,7 +37,7 @@ class Peer;
class ServerImpl : public beast::Thread
{
-public:
+private:
struct State
{
// Attributes for our listening ports
@@ -49,7 +55,7 @@ public:
Server& m_server;
Handler& m_handler;
- beast::Journal m_journal;
+ beast::Journal journal_;
boost::asio::io_service m_io_service;
boost::asio::io_service::strand m_strand;
boost::optional m_work;
@@ -57,24 +63,54 @@ public:
SharedState m_state;
Doors m_doors;
+public:
ServerImpl (Server& server, Handler& handler, beast::Journal journal);
~ServerImpl ();
- beast::Journal const& journal() const;
- Ports const& getPorts () const;
- void setPorts (Ports const& ports);
- bool stopping () const;
- void stop (bool wait);
- Handler& handler();
- boost::asio::io_service& get_io_service();
- void add (Peer& peer);
- void add (Door& door);
- void remove (Peer& peer);
- void remove (Door& door);
+ beast::Journal
+ journal() const
+ {
+ return journal_;
+ }
- void handle_update ();
- void update ();
- void run ();
+ Ports const&
+ getPorts () const;
+
+ void
+ setPorts (Ports const& ports);
+
+ bool
+ stopping () const;
+
+ void
+ stop (bool wait);
+
+ Handler&
+ handler();
+
+ boost::asio::io_service&
+ get_io_service();
+
+ void
+ add (Peer& peer);
+
+ void
+ add (Door& door);
+
+ void
+ remove (Peer& peer);
+
+ void
+ remove (Door& door);
+
+ void
+ handle_update ();
+
+ void
+ update ();
+
+ void
+ run ();
static int compare (Port const& lhs, Port const& rhs);
};
diff --git a/src/ripple/module/app/main/Application.cpp b/src/ripple/module/app/main/Application.cpp
index 766f663463..30f1096caf 100644
--- a/src/ripple/module/app/main/Application.cpp
+++ b/src/ripple/module/app/main/Application.cpp
@@ -801,6 +801,10 @@ public:
//
// Allow RPC connections.
//
+#if RIPPLE_ASYNC_RPC_HANDLER
+ m_rpcHTTPServer->setup (m_journal);
+
+#else
if (! getConfig ().getRpcIP().empty () && getConfig ().getRpcPort() != 0)
{
try
@@ -820,6 +824,7 @@ public:
{
m_journal.info << "RPC interface: disabled";
}
+#endif
//
// Begin connecting to network.
diff --git a/src/ripple/module/app/main/RPCHTTPServer.cpp b/src/ripple/module/app/main/RPCHTTPServer.cpp
index 5414224483..24759a2035 100644
--- a/src/ripple/module/app/main/RPCHTTPServer.cpp
+++ b/src/ripple/module/app/main/RPCHTTPServer.cpp
@@ -18,6 +18,7 @@
//==============================================================================
#include
+#include
#include
#include
#include
@@ -75,9 +76,12 @@ public:
getConfig ().getRpcPort() != 0)
{
beast::IP::Endpoint ep (beast::IP::Endpoint::from_string (getConfig().getRpcIP()));
- if (! is_unspecified (ep))
+
+ // VFALCO TODO IP address should not have an "unspecified" state
+ //if (! is_unspecified (ep))
{
HTTP::Port port;
+ port.security = HTTP::Port::allow_ssl;
port.addr = ep.at_port(0);
if (getConfig ().getRpcPort() != 0)
port.port = getConfig ().getRpcPort();
@@ -131,16 +135,24 @@ public:
void onRequest (HTTP::Session& session)
{
+ // Check user/password authorization
+ auto const headers (session.request()->headers().build_map());
+ if (! HTTPAuthorized (headers))
+ {
+ session.write (HTTPReply (403, "Forbidden"));
+ session.close();
+ return;
+ }
+
#if 0
+ // Synchronous version that doesn't use job queue
Job job;
processSession (job, session);
+
#else
session.detach();
- // The "boost::"'s are a workaround for broken versions of tr1::functional that
- // require the reference wrapper to be callable. HTTP::Session has abstract functions
- // and so references to it are not callable.
- m_jobQueue.addJob (jtRPC, "RPC", std::bind (
+ m_jobQueue.addJob (jtCLIENT, "RPC-Client", std::bind (
&RPCHTTPServerImp::processSession, this, std::placeholders::_1,
std::ref (session)));
#endif
@@ -159,8 +171,14 @@ public:
void processSession (Job& job, HTTP::Session& session)
{
+#if 0
+ // Goes through the old code
session.write (m_deprecatedHandler.processRequest (
session.content(), session.remoteAddress().at_port(0)));
+#else
+ session.write (processRequest (session.content(),
+ session.remoteAddress().at_port(0)));
+#endif
session.close();
}
@@ -172,14 +190,10 @@ public:
return HTTPReply (statusCode, description);
}
- bool isAuthorized (
- std::map const& headers)
- {
- return HTTPAuthorized (headers);
- }
-
// Stolen directly from RPCServerHandler
- std::string processRequest (std::string const& request, beast::IP::Endpoint const& remoteIPAddress)
+ std::string
+ processRequest (std::string const& request,
+ beast::IP::Endpoint const& remoteIPAddress)
{
Json::Value jvRequest;
{
@@ -247,14 +261,6 @@ public:
return HTTPReply (403, "Forbidden");
}
- // This code does all the work on the io_service thread and
- // has no rate-limiting based on source IP or anything.
- // This is a temporary safety
- if ((role != Config::ADMIN) && (getApp().getFeeTrack().isLoadedLocal()))
- {
- return HTTPReply (503, "Unable to service at this time");
- }
-
std::string response;
m_journal.debug << "Query: " << strMethod << params;
diff --git a/src/ripple/module/net/rpc/RPCUtil.cpp b/src/ripple/module/net/rpc/RPCUtil.cpp
index f837c9affe..401a927551 100644
--- a/src/ripple/module/net/rpc/RPCUtil.cpp
+++ b/src/ripple/module/net/rpc/RPCUtil.cpp
@@ -262,10 +262,14 @@ std::string DecodeBase64 (std::string s)
bool HTTPAuthorized (const std::map& mapHeaders)
{
- std::map::const_iterator it = mapHeaders.find ("authorization");
+ bool const credentialsRequired (! getConfig().RPC_USER.empty() &&
+ ! getConfig().RPC_PASSWORD.empty());
+ if (! credentialsRequired)
+ return true;
+ auto const it = mapHeaders.find ("authorization");
if ((it == mapHeaders.end ()) || (it->second.substr (0, 6) != "Basic "))
- return getConfig ().RPC_USER.empty () && getConfig ().RPC_PASSWORD.empty ();
+ return false;
std::string strUserPass64 = it->second.substr (6);
boost::trim (strUserPass64);
diff --git a/src/ripple/unity/app.cpp b/src/ripple/unity/app.cpp
index 0542c45ea9..f6928ae9ee 100644
--- a/src/ripple/unity/app.cpp
+++ b/src/ripple/unity/app.cpp
@@ -23,11 +23,12 @@
#include
#include
#include
-#include
#include
#include
#include
+#include
+
#include
#include
#include
diff --git a/src/ripple/unity/http.cpp b/src/ripple/unity/http.cpp
index d980419cbe..1ad92de1fe 100644
--- a/src/ripple/unity/http.cpp
+++ b/src/ripple/unity/http.cpp
@@ -19,19 +19,9 @@
#include
-#include
-
-#include
-
-#include
-#include
-
+#include
+#include
#include
#include
-
-#include
-#include
-#include
-#include
#include
#include
diff --git a/src/ripple/unity/http.h b/src/ripple/unity/http.h
deleted file mode 100644
index 12a900fbec..0000000000
--- a/src/ripple/unity/http.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- 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_HTTP_H_INCLUDED
-#define RIPPLE_HTTP_H_INCLUDED
-
-// VFALCO This entire file is deprecated now, I'm working on a replacement
-
-// VFALCO NOTE this sucks that we have to include asio in the header
-// just for HTTPMessage!!
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#endif