blob: a8a55edbc26757f4410a055b14d44d90f46f89cf [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
Ed Tanous911ac312017-08-15 09:37:42 -07002#include "crow/logging.h"
3#include "crow/settings.h"
Ed Tanous7045c8d2017-04-03 10:04:37 -07004#include <boost/asio.hpp>
5#ifdef CROW_ENABLE_SSL
6#include <boost/asio/ssl.hpp>
7#endif
Ed Tanous7045c8d2017-04-03 10:04:37 -07008namespace crow {
9using namespace boost;
10using tcp = asio::ip::tcp;
11
12struct SocketAdaptor {
Ed Tanous911ac312017-08-15 09:37:42 -070013 using secure = std::false_type;
Ed Tanous7045c8d2017-04-03 10:04:37 -070014 using context = void;
Ed Tanous911ac312017-08-15 09:37:42 -070015 SocketAdaptor(boost::asio::io_service& io_service, context* /*unused*/)
Ed Tanous7045c8d2017-04-03 10:04:37 -070016 : socket_(io_service) {}
17
18 boost::asio::io_service& get_io_service() { return socket_.get_io_service(); }
19
20 tcp::socket& raw_socket() { return socket_; }
21
22 tcp::socket& socket() { return socket_; }
23
24 tcp::endpoint remote_endpoint() { return socket_.remote_endpoint(); }
25
26 bool is_open() { return socket_.is_open(); }
27
28 void close() { socket_.close(); }
29
30 template <typename F>
31 void start(F f) {
32 f(boost::system::error_code());
33 }
34
35 tcp::socket socket_;
36};
37
Ed Tanousb4a7bfa2017-04-04 17:23:00 -070038struct TestSocketAdaptor {
Ed Tanous911ac312017-08-15 09:37:42 -070039 using secure = std::false_type;
Ed Tanousb4a7bfa2017-04-04 17:23:00 -070040 using context = void;
Ed Tanous911ac312017-08-15 09:37:42 -070041 TestSocketAdaptor(boost::asio::io_service& io_service, context* /*unused*/)
Ed Tanousb4a7bfa2017-04-04 17:23:00 -070042 : socket_(io_service) {}
43
44 boost::asio::io_service& get_io_service() { return socket_.get_io_service(); }
45
46 tcp::socket& raw_socket() { return socket_; }
47
48 tcp::socket& socket() { return socket_; }
49
50 tcp::endpoint remote_endpoint() { return socket_.remote_endpoint(); }
51
52 bool is_open() { return socket_.is_open(); }
53
54 void close() { socket_.close(); }
55
56 template <typename F>
57 void start(F f) {
58 f(boost::system::error_code());
59 }
60
61 tcp::socket socket_;
62};
63
Ed Tanous7045c8d2017-04-03 10:04:37 -070064#ifdef CROW_ENABLE_SSL
65struct SSLAdaptor {
Ed Tanous911ac312017-08-15 09:37:42 -070066 using secure = std::true_type;
Ed Tanous7045c8d2017-04-03 10:04:37 -070067 using context = boost::asio::ssl::context;
68 using ssl_socket_t = boost::asio::ssl::stream<tcp::socket>;
69 SSLAdaptor(boost::asio::io_service& io_service, context* ctx)
70 : ssl_socket_(new ssl_socket_t(io_service, *ctx)) {}
71
72 boost::asio::ssl::stream<tcp::socket>& socket() { return *ssl_socket_; }
73
74 tcp::socket::lowest_layer_type& raw_socket() {
75 return ssl_socket_->lowest_layer();
76 }
77
78 tcp::endpoint remote_endpoint() { return raw_socket().remote_endpoint(); }
79
Ed Tanous9140a672017-04-24 17:01:32 -070080 bool is_open() {
81 /*TODO(ed) this is a bit of a cheat.
82 There are cases when running a websocket where ssl_socket_ might have
83 std::move() called on it (to transfer ownership to websocket::Connection)
84 and be empty. This (and the check on close()) is a cheat to do something
85 sane in this scenario. the correct fix would likely involve changing the
86 http parser to return a specific code meaning "has been upgraded" so that
87 the do_read function knows not to try to close the connection which would
Ed Tanous911ac312017-08-15 09:37:42 -070088 fail, because the adapter is gone. As is, do_read believes the parse
Ed Tanous9140a672017-04-24 17:01:32 -070089 failed, because is_open now returns False (which could also mean the client
90 disconnected during parse)
Ed Tanous4c3cbc62017-05-16 09:17:42 -070091 UPdate: The parser does in fact have an "is_upgrade" method that is intended
Ed Tanous0d485ef2017-05-23 09:23:53 -070092 for exactly this purpose. Todo is now to make do_read obey the flag
Ed Tanous911ac312017-08-15 09:37:42 -070093 appropriately so this code can be changed back.
Ed Tanous9140a672017-04-24 17:01:32 -070094 */
95 if (ssl_socket_ != nullptr) {
96 return ssl_socket_->lowest_layer().is_open();
Ed Tanous9140a672017-04-24 17:01:32 -070097 }
Ed Tanous911ac312017-08-15 09:37:42 -070098 return false;
Ed Tanous9140a672017-04-24 17:01:32 -070099 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700100
Ed Tanous9140a672017-04-24 17:01:32 -0700101 void close() {
102 if (ssl_socket_ == nullptr) {
103 return;
104 }
Ed Tanous0d485ef2017-05-23 09:23:53 -0700105 boost::system::error_code ec;
106
Ed Tanous911ac312017-08-15 09:37:42 -0700107 // Shut it down
Ed Tanous0d485ef2017-05-23 09:23:53 -0700108 this->ssl_socket_->lowest_layer().close();
Ed Tanous9140a672017-04-24 17:01:32 -0700109 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700110
111 boost::asio::io_service& get_io_service() {
112 return raw_socket().get_io_service();
113 }
114
115 template <typename F>
116 void start(F f) {
117 ssl_socket_->async_handshake(
118 boost::asio::ssl::stream_base::server,
119 [f](const boost::system::error_code& ec) { f(ec); });
120 }
121
122 std::unique_ptr<boost::asio::ssl::stream<tcp::socket>> ssl_socket_;
123};
124#endif
Ed Tanous911ac312017-08-15 09:37:42 -0700125} // namespace crow