From 6ae38db4edd965d4caf88b85b5667f19dd7af237 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 23 Jan 2013 13:35:55 -0800 Subject: [PATCH 1/3] Socket with auto-detect SSL on inbound, SSL and non-SSL outbound. Compiles, but totally untested. # ../websocketpp/src/sockets/tls-hybrid.hpp --- src/cpp/ripple/AutoSocket.cpp | 28 +++++++++++ src/cpp/ripple/AutoSocket.h | 94 +++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/cpp/ripple/AutoSocket.cpp create mode 100644 src/cpp/ripple/AutoSocket.h diff --git a/src/cpp/ripple/AutoSocket.cpp b/src/cpp/ripple/AutoSocket.cpp new file mode 100644 index 000000000..f421937fa --- /dev/null +++ b/src/cpp/ripple/AutoSocket.cpp @@ -0,0 +1,28 @@ + +#include "AutoSocket.h" + +#include + +void AutoSocket::handle_autodetect(const error_code& ec) +{ + if (ec) + { + if (mCallback) + mCallback(ec); + return; + } + + if ((mBuffer[0] < 127) && (mBuffer[0] > 31) && + (mBuffer[1] < 127) && (mBuffer[1] > 31) && + (mBuffer[2] < 127) && (mBuffer[2] > 31) && + (mBuffer[3] < 127) && (mBuffer[3] > 31)) + { // non-SSL + if (mCallback) + mCallback(ec); + } + else + { // ssl + mSecure = true; + SSLSocket().async_handshake(ssl_socket::server, mCallback); + } +} diff --git a/src/cpp/ripple/AutoSocket.h b/src/cpp/ripple/AutoSocket.h new file mode 100644 index 000000000..019618dbd --- /dev/null +++ b/src/cpp/ripple/AutoSocket.h @@ -0,0 +1,94 @@ +#ifndef __AUTOSOCKET_H_ +#define __AUTOSOCKET_H_ + +#include + +#include +#include +#include +#include + +// Socket wrapper that supports both SSL and non-SSL connections. +// Generally, handle it as you would an SSL connection. +// For outbound non-SSL connections, just don't call async_handshake. + +namespace basio = boost::asio; +namespace bassl = basio::ssl; + +class AutoSocket +{ +public: + typedef bassl::stream ssl_socket; + typedef ssl_socket::next_layer_type plain_socket; + typedef boost::system::error_code error_code; + typedef boost::function callback; + +protected: + ssl_socket mSocket; + bool mSecure; + callback mCallback; + + std::vector mBuffer; + +public: + AutoSocket(basio::io_service& s, bassl::context& c) : mSocket(s, c), mSecure(false), mBuffer(4) { ; } + + bool isSecure() { return mSecure; } + ssl_socket& SSLSocket() { return mSocket; } + plain_socket& PlainSocket() { return mSocket.next_layer(); } + + void async_handshake(ssl_socket::handshake_type type, callback cbFunc) + { + mSecure = true; + if (type == ssl_socket::client) + SSLSocket().async_handshake(type, cbFunc); + else + { + mCallback = cbFunc; + PlainSocket().async_receive(basio::buffer(mBuffer), basio::socket_base::message_peek, + boost::bind(&AutoSocket::handle_autodetect, this, basio::placeholders::error)); + + } + } + + template StreamType& getSocket() + { + if (isSecure()) + return SSLSocket(); + if (!isSecure()) + return PlainSocket(); + } + + template void async_shutdown(ShutdownHandler handler) + { + if (isSecure()) + SSLSocket().async_shutdown(handler); + else + { + PlainSocket().shutdown(plain_socket::shutdown_both); + if (handler) + mSocket.get_io_service().post(handler); + } + } + + template void async_read_some(const Seq& buffers, Handler handler) + { + if (isSecure()) + SSLSocket().async_read_some(buffers, handler); + else + PlainSocket().async_read_some(buffers, handler); + } + + template void async_write_some(const Seq& buffers, Handler handler) + { + if (isSecure()) + SSLSocket().async_write_some(buffers, handler); + else + PlainSocket().async_write_some(buffers, handler); + } + +protected: + void handle_autodetect(const error_code&); +}; + +#endif From 9aaa3cc2fa0ddf95e3c9b6e96d021baf35eb2c49 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 23 Jan 2013 13:50:33 -0800 Subject: [PATCH 2/3] Buglet. --- src/cpp/ripple/AutoSocket.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/ripple/AutoSocket.cpp b/src/cpp/ripple/AutoSocket.cpp index f421937fa..732716194 100644 --- a/src/cpp/ripple/AutoSocket.cpp +++ b/src/cpp/ripple/AutoSocket.cpp @@ -17,6 +17,7 @@ void AutoSocket::handle_autodetect(const error_code& ec) (mBuffer[2] < 127) && (mBuffer[2] > 31) && (mBuffer[3] < 127) && (mBuffer[3] > 31)) { // non-SSL + mSecure = false; if (mCallback) mCallback(ec); } @@ -26,3 +27,5 @@ void AutoSocket::handle_autodetect(const error_code& ec) SSLSocket().async_handshake(ssl_socket::server, mCallback); } } + +// vim:ts=4 From c9bdcc3cfdafb1bc71e864658e04931371cc44bf Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 23 Jan 2013 14:14:28 -0800 Subject: [PATCH 3/3] Tweaks. --- src/cpp/ripple/AutoSocket.cpp | 1 + src/cpp/ripple/AutoSocket.h | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cpp/ripple/AutoSocket.cpp b/src/cpp/ripple/AutoSocket.cpp index 732716194..dd553a4c5 100644 --- a/src/cpp/ripple/AutoSocket.cpp +++ b/src/cpp/ripple/AutoSocket.cpp @@ -25,6 +25,7 @@ void AutoSocket::handle_autodetect(const error_code& ec) { // ssl mSecure = true; SSLSocket().async_handshake(ssl_socket::server, mCallback); + mCallback = callback(); } } diff --git a/src/cpp/ripple/AutoSocket.h b/src/cpp/ripple/AutoSocket.h index 019618dbd..d8529ea28 100644 --- a/src/cpp/ripple/AutoSocket.h +++ b/src/cpp/ripple/AutoSocket.h @@ -10,7 +10,8 @@ // Socket wrapper that supports both SSL and non-SSL connections. // Generally, handle it as you would an SSL connection. -// For outbound non-SSL connections, just don't call async_handshake. +// To force a non-SSL connection, just don't call async_handshake. +// To force SSL only inbound, call setSSLOnly. namespace basio = boost::asio; namespace bassl = basio::ssl; @@ -37,10 +38,12 @@ public: ssl_socket& SSLSocket() { return mSocket; } plain_socket& PlainSocket() { return mSocket.next_layer(); } + void setSSLOnly() { mBuffer.clear(); } + void async_handshake(ssl_socket::handshake_type type, callback cbFunc) { mSecure = true; - if (type == ssl_socket::client) + if ((type == ssl_socket::client) || (mBuffer.empty())) SSLSocket().async_handshake(type, cbFunc); else { @@ -92,3 +95,5 @@ protected: }; #endif + +// vim:ts=4