mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
adds HTTP request sending to connections
This commit is contained in:
@@ -30,9 +30,13 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <websocketpp/random/random_device.hpp>
|
||||
|
||||
#include <websocketpp/config/core.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <websocketpp/http/request.hpp>
|
||||
|
||||
struct stub_config : public websocketpp::config::core {
|
||||
typedef core::concurrency_type concurrency_type;
|
||||
|
||||
@@ -46,7 +50,8 @@ struct stub_config : public websocketpp::config::core {
|
||||
typedef core::alog_type alog_type;
|
||||
typedef core::elog_type elog_type;
|
||||
|
||||
typedef core::rng_type rng_type;
|
||||
//typedef core::rng_type rng_type;
|
||||
typedef websocketpp::random::random_device::int_generator<uint32_t,concurrency_type> rng_type;
|
||||
|
||||
typedef core::transport_type transport_type;
|
||||
|
||||
@@ -86,3 +91,52 @@ BOOST_AUTO_TEST_CASE( get_connection ) {
|
||||
BOOST_CHECK_EQUAL( con->get_secure() , false );
|
||||
BOOST_CHECK_EQUAL( con->get_resource() , "/" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( connect_con ) {
|
||||
client c;
|
||||
websocketpp::lib::error_code ec;
|
||||
std::stringstream out;
|
||||
std::string o;
|
||||
|
||||
c.register_ostream(&out);
|
||||
|
||||
connection_ptr con = c.get_connection("ws://localhost/", ec);
|
||||
c.connect(con);
|
||||
|
||||
o = out.str();
|
||||
websocketpp::http::parser::request r;
|
||||
r.consume(o.data(),o.size());
|
||||
|
||||
BOOST_CHECK( r.ready() );
|
||||
BOOST_CHECK_EQUAL( r.get_method(), "GET");
|
||||
BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1");
|
||||
BOOST_CHECK_EQUAL( r.get_uri(), "/");
|
||||
|
||||
BOOST_CHECK_EQUAL( r.get_header("Host"), "localhost");
|
||||
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Version"), "13");
|
||||
BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade");
|
||||
BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket");
|
||||
|
||||
// Key is randomly generated & User-Agent will change so just check that
|
||||
// they are not empty.
|
||||
BOOST_CHECK_NE( r.get_header("Sec-WebSocket-Key"), "");
|
||||
BOOST_CHECK_NE( r.get_header("User-Agent"), "" );
|
||||
|
||||
// connection should have written out an opening handshake request and be in
|
||||
// the read response internal state
|
||||
|
||||
std::cout << "output: " << out.str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// test cases
|
||||
// - adding headers
|
||||
// - adding Upgrade header
|
||||
// - adding Connection header
|
||||
// - adding Sec-WebSocket-Version, Sec-WebSocket-Key, or Host header
|
||||
// - other Sec* headers?
|
||||
// - User Agent header?
|
||||
|
||||
|
||||
// Origin support
|
||||
// Subprotocol requests
|
||||
@@ -157,6 +157,7 @@ public:
|
||||
typedef typename con_msg_manager_type::ptr con_msg_manager_ptr;
|
||||
|
||||
/// Type of RNG
|
||||
typedef typename config::rng_type rng_type;
|
||||
|
||||
typedef processor::processor<config> processor_type;
|
||||
typedef lib::shared_ptr<processor_type> processor_ptr;
|
||||
@@ -672,6 +673,7 @@ public:
|
||||
size_t bytes_transferred);
|
||||
|
||||
void handle_send_http_response(const lib::error_code& ec);
|
||||
void handle_send_http_request(const lib::error_code& ec);
|
||||
|
||||
|
||||
/// Get array of WebSocket protocol versions that this connection supports.
|
||||
@@ -757,6 +759,9 @@ private:
|
||||
/// Completes m_response, serializes it, and sends it out on the wire.
|
||||
void send_http_response();
|
||||
|
||||
/// Sends an opening WebSocket connect request
|
||||
void send_http_request();
|
||||
|
||||
/// Alternate path for send_http_response in error conditions
|
||||
void send_http_response_error();
|
||||
|
||||
@@ -893,7 +898,11 @@ private:
|
||||
size_t m_buf_cursor;
|
||||
termination_handler m_termination_handler;
|
||||
con_msg_manager_ptr m_msg_manager;
|
||||
|
||||
|
||||
// TODO: this is not memory efficient. this value is not used after the
|
||||
// handshake.
|
||||
std::string m_handshake_buffer;
|
||||
|
||||
/// Pointer to the processor object for this connection
|
||||
/**
|
||||
* The processor provides functionality that is specific to the WebSocket
|
||||
|
||||
@@ -465,7 +465,10 @@ void connection<config>::handle_transport_init(const lib::error_code& ec) {
|
||||
if (m_is_server) {
|
||||
this->read(1);
|
||||
} else {
|
||||
// call prepare HTTP request
|
||||
// We are a client. Set the processor to the version specified in the
|
||||
// config file and send a handshake request.
|
||||
m_processor = get_processor(config::client_version);
|
||||
this->send_http_request();
|
||||
}
|
||||
|
||||
// TODO: Begin websocket handshake
|
||||
@@ -929,25 +932,23 @@ void connection<config>::send_http_response() {
|
||||
|
||||
// Set some common headers
|
||||
m_response.replace_header("Server",m_user_agent);
|
||||
|
||||
std::string raw;
|
||||
|
||||
|
||||
// have the processor generate the raw bytes for the wire (if it exists)
|
||||
if (m_processor) {
|
||||
raw = m_processor->get_raw(m_response);
|
||||
m_handshake_buffer = m_processor->get_raw(m_response);
|
||||
} else {
|
||||
// a processor wont exist for raw HTTP responses.
|
||||
raw = m_response.raw();
|
||||
m_handshake_buffer = m_response.raw();
|
||||
}
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,"Raw Handshake response:\n"+raw);
|
||||
m_alog.write(log::alevel::devel,"Raw Handshake response:\n"+m_handshake_buffer);
|
||||
}
|
||||
|
||||
// write raw bytes
|
||||
transport_con_type::async_write(
|
||||
raw.c_str(),
|
||||
raw.size(),
|
||||
m_handshake_buffer.data(),
|
||||
m_handshake_buffer.size(),
|
||||
lib::bind(
|
||||
&type::handle_send_http_response,
|
||||
type::shared_from_this(),
|
||||
@@ -1009,6 +1010,111 @@ void connection<config>::handle_send_http_response(
|
||||
this->handle_read_frame(lib::error_code(), m_buf_cursor);
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::send_http_request() {
|
||||
m_alog.write(log::alevel::devel,"connection send_http_request");
|
||||
|
||||
// TODO: origin header
|
||||
// TODO: subprotocol requests
|
||||
|
||||
// Generate client key
|
||||
// set client key header
|
||||
|
||||
// Set User-Agent header
|
||||
|
||||
|
||||
|
||||
// Have the protocol processor fill in the appropriate fields based on the
|
||||
// selected client version
|
||||
if (m_processor) {
|
||||
lib::error_code ec;
|
||||
ec = m_processor->handshake_request(m_request,m_uri);
|
||||
|
||||
if (ec) {
|
||||
m_elog.write(log::elevel::fatal,
|
||||
"Internal library error: processor error: "+ec.message());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
m_elog.write(log::elevel::fatal,
|
||||
"Internal library error: missing processor");
|
||||
return;
|
||||
}
|
||||
|
||||
// Unless the user has overridden the user agent, send generic WS++
|
||||
if (m_request.get_header("User-Agent") == "") {
|
||||
m_request.replace_header("User-Agent",m_user_agent);
|
||||
}
|
||||
|
||||
m_handshake_buffer = m_request.raw();
|
||||
|
||||
if (m_alog.static_test(log::alevel::devel)) {
|
||||
m_alog.write(log::alevel::devel,
|
||||
"Raw Handshake response:\n"+m_handshake_buffer);
|
||||
}
|
||||
|
||||
transport_con_type::async_write(
|
||||
m_handshake_buffer.data(),
|
||||
m_handshake_buffer.size(),
|
||||
lib::bind(
|
||||
&type::handle_send_http_request,
|
||||
type::shared_from_this(),
|
||||
lib::placeholders::_1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::handle_send_http_request(const lib::error_code& ec) {
|
||||
m_alog.write(log::alevel::devel,"handle_send_http_request");
|
||||
|
||||
/*this->atomic_state_check(
|
||||
istate::PROCESS_HTTP_REQUEST,
|
||||
"handle_send_http_response must be called from PROCESS_HTTP_REQUEST state"
|
||||
);
|
||||
|
||||
if (ec) {
|
||||
m_elog.write(log::elevel::rerror,
|
||||
"error in handle_send_http_response: "+ec.message());
|
||||
this->terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
this->log_open_result();
|
||||
|
||||
if (m_response.get_status_code() != http::status_code::SWITCHING_PROTOCOLS)
|
||||
{
|
||||
if (m_processor) {
|
||||
// if this was not a websocket connection, we have written
|
||||
// the expected response and the connection can be closed.
|
||||
} else {
|
||||
// this was a websocket connection that ended in an error
|
||||
std::stringstream s;
|
||||
s << "Handshake ended with HTTP error: "
|
||||
<< m_response.get_status_code();
|
||||
m_elog.write(log::elevel::rerror,s.str());
|
||||
}
|
||||
this->terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: cancel handshake timer
|
||||
|
||||
this->atomic_state_change(
|
||||
istate::PROCESS_HTTP_REQUEST,
|
||||
istate::PROCESS_CONNECTION,
|
||||
session::state::CONNECTING,
|
||||
session::state::OPEN,
|
||||
"handle_send_http_response must be called from PROCESS_HTTP_REQUEST state"
|
||||
);
|
||||
|
||||
if (m_open_handler) {
|
||||
m_open_handler(m_connection_hdl);
|
||||
}
|
||||
|
||||
this->handle_read_frame(lib::error_code(), m_buf_cursor);*/
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::terminate() {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user