Skip to content

Commit

Permalink
Merge pull request #134 from bitshares/jmj_844b
Browse files Browse the repository at this point in the history
Log host information from websocket requests
  • Loading branch information
abitmore committed May 2, 2020
2 parents ed22e1e + ea96a5a commit c00824a
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 117 deletions.
26 changes: 12 additions & 14 deletions include/fc/network/http/websocket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace fc { namespace http {
class websocket_tls_client_impl;
} // namespace detail

// TODO refactor code, move stuff used by server or client only to derived class(es),
// E.G. it seems get_request_header and on_http* are for server only.
class websocket_connection
{
public:
Expand All @@ -32,7 +34,11 @@ namespace fc { namespace http {

virtual std::string get_request_header(const std::string& key) = 0;

const std::string& get_remote_endpoint_string()const { return _remote_endpoint; }

fc::signal<void()> closed;
protected:
std::string _remote_endpoint; // for logging
private:
boost::any _session_data;
std::function<void(const std::string&)> _on_message;
Expand All @@ -45,7 +51,7 @@ namespace fc { namespace http {
class websocket_server
{
public:
websocket_server();
websocket_server(const std::string& forward_header_key);
~websocket_server();

void on_connection( const on_connection_handler& handler);
Expand All @@ -66,15 +72,15 @@ namespace fc { namespace http {
class websocket_tls_server
{
public:
websocket_tls_server( const std::string& server_pem = std::string(),
const std::string& ssl_password = std::string());
websocket_tls_server( const std::string& server_pem,
const std::string& ssl_password,
const std::string& forward_header_key );
~websocket_tls_server();

void on_connection( const on_connection_handler& handler);
void listen( uint16_t port );
void listen( const fc::ip::endpoint& ep );
void start_accept();

private:
friend class detail::websocket_tls_server_impl;
std::unique_ptr<detail::websocket_tls_server_impl> my;
Expand All @@ -91,19 +97,11 @@ namespace fc { namespace http {

void close();
void synchronous_close();
void append_header(const std::string& key, const std::string& value);
private:
std::unique_ptr<detail::websocket_client_impl> my;
std::unique_ptr<detail::websocket_tls_client_impl> smy;
};
class websocket_tls_client
{
public:
websocket_tls_client( const std::string& ca_filename = "_default" );
~websocket_tls_client();

websocket_connection_ptr connect( const std::string& uri );
private:
std::unique_ptr<detail::websocket_tls_client_impl> my;
std::vector<std::pair<std::string,std::string>> headers;
};

} }
7 changes: 7 additions & 0 deletions src/log/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ namespace fc {
void logger::add_appender( const appender::ptr& a )
{ my->_appenders.push_back(a); }

void logger::remove_appender( const appender::ptr& a )
{
auto item = std::find(my->_appenders.begin(), my->_appenders.end(), a);
if (item != my->_appenders.end())
my->_appenders.erase(item);
}

std::vector<appender::ptr> logger::get_appenders()const
{
return my->_appenders;
Expand Down
204 changes: 104 additions & 100 deletions src/network/http/websocket.cpp

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ target_link_libraries( hmac_test fc )
add_executable( ecc_test crypto/ecc_test.cpp )
target_link_libraries( ecc_test fc )

add_executable( ws_test_server ws_test_server.cpp )
target_link_libraries( ws_test_server fc )

add_executable( ws_test_client ws_test_client.cpp )
target_link_libraries( ws_test_client fc )

#add_executable( test_aes aes_test.cpp )
#target_link_libraries( test_aes fc ${rt_library} ${pthread_library} )
#add_executable( test_sleep sleep.cpp )
Expand Down
4 changes: 2 additions & 2 deletions tests/api_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(login_test) {
try {
fc::api<fc::test::calculator> calc_api( std::make_shared<fc::test::some_calculator>() );

auto server = std::make_shared<fc::http::websocket_server>();
auto server = std::make_shared<fc::http::websocket_server>("");
server->on_connection([&]( const websocket_connection_ptr& c ){
auto wsc = std::make_shared<websocket_api_connection>(c, MAX_DEPTH);
auto login = std::make_shared<fc::test::login_api>();
Expand Down Expand Up @@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(optionals_test) {
BOOST_CHECK_EQUAL(oapi->bar("a", "b", "c"), "[\"a\",\"b\",\"c\"]");
BOOST_CHECK_EQUAL(oapi->bar("a", {}, "c"), "[\"a\",null,\"c\"]");

auto server = std::make_shared<fc::http::websocket_server>();
auto server = std::make_shared<fc::http::websocket_server>("");
server->on_connection([&]( const websocket_connection_ptr& c ){
auto wsc = std::make_shared<websocket_api_connection>(c, MAX_DEPTH);
wsc->register_api(fc::api<fc::test::optionals_api>(optionals));
Expand Down
110 changes: 109 additions & 1 deletion tests/network/http/websocket_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,112 @@
#include <fc/network/http/websocket.hpp>

#include <iostream>
#include <fc/log/logger.hpp>
#include <fc/log/console_appender.hpp>

BOOST_AUTO_TEST_SUITE(fc_network)

BOOST_AUTO_TEST_CASE(websocket_test)
{
// set up logging
fc::appender::ptr ca(new fc::console_appender);
fc::logger l = fc::logger::get("rpc");
l.add_appender( ca );

fc::http::websocket_client client;
fc::http::websocket_connection_ptr s_conn, c_conn;
int port;
{
fc::http::websocket_server server;
// even with this key set, if the remote does not provide it, it will revert to
// the remote endpoint
fc::http::websocket_server server("MyProxyHeaderKey");
server.on_connection([&]( const fc::http::websocket_connection_ptr& c ){
s_conn = c;
c->on_message_handler([&](const std::string& s){
c->send_message("echo: " + s);
});
c->on_http_handler([&](const std::string& s){
fc::http::reply reply;
reply.body_as_string = "http-echo: " + s;
return reply;
});
});

server.listen( 0 );
port = server.get_listening_port();

server.start_accept();

std::string echo;
c_conn = client.connect( "ws://localhost:" + fc::to_string(port) );
c_conn->on_message_handler([&](const std::string& s){
echo = s;
});
c_conn->send_message( "hello world" );
fc::usleep( fc::milliseconds(100) );
BOOST_CHECK_EQUAL("echo: hello world", echo);
c_conn->send_message( "again" );
fc::usleep( fc::milliseconds(100) );
BOOST_CHECK_EQUAL("echo: again", echo);

s_conn->close(0, "test");
fc::usleep( fc::milliseconds(100) );
BOOST_CHECK_THROW(c_conn->send_message( "again" ), fc::exception);

c_conn = client.connect( "ws://localhost:" + fc::to_string(port) );
c_conn->on_message_handler([&](const std::string& s){
echo = s;
});
c_conn->send_message( "hello world" );
fc::usleep( fc::milliseconds(100) );
BOOST_CHECK_EQUAL("echo: hello world", echo);

// Testing on_http
std::string server_endpoint_string = "127.0.0.1:" + fc::to_string(port);
fc::ip::endpoint server_endpoint = fc::ip::endpoint::from_string( server_endpoint_string );
fc::http::connection c_http_conn;
c_http_conn.connect_to( server_endpoint );

std::string url = "http://localhost:" + fc::to_string(port);
fc::http::reply reply = c_http_conn.request( "POST", url, "hello world again" );
std::string reply_body( reply.body.begin(), reply.body.end() );
BOOST_CHECK_EQUAL(200, reply.status);
BOOST_CHECK_EQUAL("http-echo: hello world again", reply_body );
}

BOOST_CHECK_THROW(c_conn->send_message( "again" ), fc::assert_exception);
BOOST_CHECK_THROW(client.connect( "ws://localhost:" + fc::to_string(port) ), fc::exception);
l.remove_appender(ca);
}

BOOST_AUTO_TEST_CASE(websocket_test_with_proxy_header)
{
// set up logging
fc::appender::ptr ca(new fc::console_appender);
fc::logger l = fc::logger::get("rpc");
auto old_log_level = l.get_log_level();
l.set_log_level( fc::log_level::info );
l.add_appender( ca );

fc::http::websocket_client client;
// add the proxy header element
client.append_header("MyProxyHeaderKey", "MyServer:8080");

fc::http::websocket_connection_ptr s_conn, c_conn;
int port;
{
// the server will be on the lookout for the key in the header
fc::http::websocket_server server("MyProxyHeaderKey");
server.on_connection([&]( const fc::http::websocket_connection_ptr& c ){
s_conn = c;
c->on_message_handler([&](const std::string& s){
c->send_message("echo: " + s);
});
c->on_http_handler([&](const std::string& s){
fc::http::reply reply;
reply.body_as_string = "http-echo: " + s;
return reply;
});
});

server.listen( 0 );
Expand Down Expand Up @@ -48,10 +139,27 @@ BOOST_AUTO_TEST_CASE(websocket_test)
c_conn->send_message( "hello world" );
fc::usleep( fc::milliseconds(100) );
BOOST_CHECK_EQUAL("echo: hello world", echo);

// Testing on_http
std::string server_endpoint_string = "127.0.0.1:" + fc::to_string(port);
fc::ip::endpoint server_endpoint = fc::ip::endpoint::from_string( server_endpoint_string );
fc::http::connection c_http_conn;
c_http_conn.connect_to( server_endpoint );

std::string url = "http://localhost:" + fc::to_string(port);
fc::http::header fwd("MyProxyHeaderKey", "MyServer:8080");
fc::http::headers headers {fwd};
fc::http::reply reply = c_http_conn.request( "POST", url, "hello world again", headers );
std::string reply_body( reply.body.begin(), reply.body.end() );
BOOST_CHECK_EQUAL(200, reply.status);
BOOST_CHECK_EQUAL("http-echo: hello world again", reply_body );
}

BOOST_CHECK_THROW(c_conn->send_message( "again" ), fc::assert_exception);
BOOST_CHECK_THROW(client.connect( "ws://localhost:" + fc::to_string(port) ), fc::exception);

l.remove_appender(ca);
l.set_log_level(old_log_level);
}

BOOST_AUTO_TEST_SUITE_END()
41 changes: 41 additions & 0 deletions tests/ws_test_client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <fc/network/http/websocket.hpp>
#include <websocketpp/error.hpp>

#include <iostream>
#include <string>
#include <fc/log/logger.hpp>
#include <fc/log/console_appender.hpp>

int main(int argc, char** argv)
{
try
{
// set up logging
fc::appender::ptr ca(new fc::console_appender);
fc::logger l = fc::logger::get("rpc");
l.add_appender( ca );

fc::http::websocket_client client;
fc::http::websocket_connection_ptr s_conn, c_conn;
std::string url = argv[1];
wlog( "Connecting to server at url ${url}", ("url", url) );
c_conn = client.connect( "ws://" + url );

std::string echo;
c_conn->on_message_handler([&](const std::string& s){
echo = s;
});
c_conn->send_message( "hello world" );
fc::usleep( fc::milliseconds(500) );
if (echo != std::string("echo: hello world") )
wlog( "Test1 failed, echo value: [${echo}]", ("echo", echo) );
c_conn->send_message( "again" );
fc::usleep( fc::milliseconds(500) );
if ("echo: again" != echo)
wlog( "Test2 failed, echo value: [${echo}]", ("echo", echo) );
}
catch (const websocketpp::exception& ex)
{
elog( "websocketpp::exception thrown: ${err}", ("err", ex.what()) );
}
}
33 changes: 33 additions & 0 deletions tests/ws_test_server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <fc/network/http/websocket.hpp>
#include <fc/asio.hpp>

#include <iostream>
#include <chrono>
#include <fc/log/logger.hpp>
#include <fc/log/console_appender.hpp>

int main(int argc, char** argv)
{
// set up logging
fc::appender::ptr ca(new fc::console_appender);
fc::logger l = fc::logger::get("rpc");
l.add_appender( ca );

fc::http::websocket_server server("MyForwardHeaderKey");

server.on_connection([&]( const fc::http::websocket_connection_ptr& c ){
c->on_message_handler([&](const std::string& s){
c->send_message("echo: " + s);
});
});

server.listen( 0 );
server.start_accept();

wlog( "Port: ${port}", ("port", server.get_listening_port()) );

while( true )
{
fc::usleep( fc::microseconds(100) );
}
}

0 comments on commit c00824a

Please sign in to comment.