| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | #ifndef GUARD_TLS_SESSION_HH |
|---|
| 21 | #define GUARD_TLS_SESSION_HH |
|---|
| 22 | |
|---|
| 23 | #include "ringbuf.hh" |
|---|
| 24 | #include "error_category.hh" |
|---|
| 25 | #include "init.hh" |
|---|
| 26 | |
|---|
| 27 | #include <boost/asio.hpp> |
|---|
| 28 | #include <boost/bind.hpp> |
|---|
| 29 | #include <boost/shared_ptr.hpp> |
|---|
| 30 | #include <boost/enable_shared_from_this.hpp> |
|---|
| 31 | #include <gnutls/gnutls.h> |
|---|
| 32 | #include <queue> |
|---|
| 33 | |
|---|
| 34 | namespace tls |
|---|
| 35 | { |
|---|
| 36 | enum conn_end { server, client }; |
|---|
| 37 | |
|---|
| 38 | template <typename Stream> |
|---|
| 39 | class session_impl : |
|---|
| 40 | private boost::noncopyable, |
|---|
| 41 | public boost::enable_shared_from_this<session_impl<Stream> > |
|---|
| 42 | { |
|---|
| 43 | enum { ringbufsize = 4096 }; |
|---|
| 44 | public: |
|---|
| 45 | typedef boost::shared_ptr<session_impl<Stream> > ptr; |
|---|
| 46 | |
|---|
| 47 | template <typename StreamInit> |
|---|
| 48 | session_impl(StreamInit si, tls::init &tls_init, conn_end ce) |
|---|
| 49 | : pre_handshake(true) |
|---|
| 50 | , post_shutdown(false) |
|---|
| 51 | , stream(si) |
|---|
| 52 | , strand(stream.get_io_service()) |
|---|
| 53 | , ins(ringbufsize) |
|---|
| 54 | , read_active(false) |
|---|
| 55 | , outs(ringbufsize) |
|---|
| 56 | , write_active(false) |
|---|
| 57 | { init(tls_init, ce); } |
|---|
| 58 | |
|---|
| 59 | session_impl(Stream si, tls::init &tls_init, conn_end ce) |
|---|
| 60 | : pre_handshake(true) |
|---|
| 61 | , post_shutdown(false) |
|---|
| 62 | , stream(si) |
|---|
| 63 | , strand(stream.get_io_service()) |
|---|
| 64 | , ins(ringbufsize) |
|---|
| 65 | , read_active(false) |
|---|
| 66 | , outs(ringbufsize) |
|---|
| 67 | , write_active(false) |
|---|
| 68 | { init(tls_init, ce); } |
|---|
| 69 | |
|---|
| 70 | void kill(); |
|---|
| 71 | |
|---|
| 72 | ~session_impl(); |
|---|
| 73 | |
|---|
| 74 | template <typename Handler> |
|---|
| 75 | void async_handshake(Handler); |
|---|
| 76 | |
|---|
| 77 | template <typename Handler> |
|---|
| 78 | void async_shutdown(Handler); |
|---|
| 79 | |
|---|
| 80 | template <typename MutableBufferSequence, typename Handler> |
|---|
| 81 | void async_read_some(MutableBufferSequence mbs, |
|---|
| 82 | Handler handler); |
|---|
| 83 | |
|---|
| 84 | template <typename ConstBufferSequence, typename Handler> |
|---|
| 85 | void async_write_some(ConstBufferSequence cbs, Handler handler); |
|---|
| 86 | |
|---|
| 87 | boost::asio::io_service &get_io_service() const |
|---|
| 88 | { return stream.get_io_service(); } |
|---|
| 89 | |
|---|
| 90 | boost::asio::io_service &io_service() const |
|---|
| 91 | { return stream.io_service(); } |
|---|
| 92 | |
|---|
| 93 | private: |
|---|
| 94 | bool pre_handshake; |
|---|
| 95 | bool post_shutdown; |
|---|
| 96 | |
|---|
| 97 | void check_sanity(); |
|---|
| 98 | |
|---|
| 99 | Stream stream; |
|---|
| 100 | boost::asio::io_service::strand strand; |
|---|
| 101 | |
|---|
| 102 | gnutls_session_t gs; |
|---|
| 103 | |
|---|
| 104 | ringbuf ins; |
|---|
| 105 | bool read_active; |
|---|
| 106 | |
|---|
| 107 | ringbuf outs; |
|---|
| 108 | bool write_active; |
|---|
| 109 | |
|---|
| 110 | boost::system::error_code pending_error; |
|---|
| 111 | |
|---|
| 112 | class initiator_base |
|---|
| 113 | { |
|---|
| 114 | protected: |
|---|
| 115 | ptr sess; |
|---|
| 116 | public: |
|---|
| 117 | initiator_base(ptr s) |
|---|
| 118 | : sess(s) |
|---|
| 119 | {} |
|---|
| 120 | virtual void operator() |
|---|
| 121 | (boost::shared_ptr<initiator_base>) = 0; |
|---|
| 122 | |
|---|
| 123 | virtual void kill |
|---|
| 124 | (boost::shared_ptr<initiator_base>) = 0; |
|---|
| 125 | }; |
|---|
| 126 | |
|---|
| 127 | class action |
|---|
| 128 | { |
|---|
| 129 | boost::shared_ptr<initiator_base> ib; |
|---|
| 130 | public: |
|---|
| 131 | typedef void result_type; |
|---|
| 132 | |
|---|
| 133 | explicit action(boost::shared_ptr<initiator_base> ib) |
|---|
| 134 | : ib(ib) |
|---|
| 135 | {} |
|---|
| 136 | |
|---|
| 137 | void operator()() { return (*ib)(ib); } |
|---|
| 138 | |
|---|
| 139 | void kill() { return ib->kill(ib); } |
|---|
| 140 | }; |
|---|
| 141 | |
|---|
| 142 | std::queue<action> pending_actions; |
|---|
| 143 | |
|---|
| 144 | void init(tls::init &tls_init, conn_end ce); |
|---|
| 145 | |
|---|
| 146 | static ssize_t push_static(void * th, const void *b, size_t n) { |
|---|
| 147 | return static_cast<session_impl *>(th)->push(b, n); |
|---|
| 148 | } |
|---|
| 149 | ssize_t push(const void *b, size_t); |
|---|
| 150 | static ssize_t pull_static(void * th, void *b, size_t n) { |
|---|
| 151 | return static_cast<session_impl *>(th)->pull(b, n); |
|---|
| 152 | } |
|---|
| 153 | ssize_t pull(void *b, size_t); |
|---|
| 154 | |
|---|
| 155 | static void received_some(ptr, |
|---|
| 156 | boost::system::error_code ec, size_t); |
|---|
| 157 | static void sent_some(ptr, |
|---|
| 158 | boost::system::error_code ec, size_t); |
|---|
| 159 | |
|---|
| 160 | void post_io_actions(); |
|---|
| 161 | void post_write(); |
|---|
| 162 | void post_read(); |
|---|
| 163 | void post_pending_actions(); |
|---|
| 164 | void kill_pending_actions(); |
|---|
| 165 | |
|---|
| 166 | template <typename Handler> |
|---|
| 167 | class initiator : public initiator_base |
|---|
| 168 | { |
|---|
| 169 | protected: |
|---|
| 170 | Handler handler; |
|---|
| 171 | virtual int gnutls_action() = 0; |
|---|
| 172 | public: |
|---|
| 173 | initiator(ptr s, Handler h) |
|---|
| 174 | : initiator_base(s), handler(h) |
|---|
| 175 | {} |
|---|
| 176 | void operator()(boost::shared_ptr<initiator_base>); |
|---|
| 177 | void kill(boost::shared_ptr<initiator_base>); |
|---|
| 178 | }; |
|---|
| 179 | |
|---|
| 180 | template <typename Handler> |
|---|
| 181 | class handshake_initiator : public initiator<Handler> |
|---|
| 182 | { |
|---|
| 183 | public: |
|---|
| 184 | handshake_initiator(ptr s, Handler h) |
|---|
| 185 | : initiator<Handler>(s, h) |
|---|
| 186 | {} |
|---|
| 187 | protected: |
|---|
| 188 | int gnutls_action(); |
|---|
| 189 | }; |
|---|
| 190 | |
|---|
| 191 | template <typename Handler> |
|---|
| 192 | class shutdown_initiator : public initiator<Handler> |
|---|
| 193 | { |
|---|
| 194 | public: |
|---|
| 195 | shutdown_initiator(ptr s, Handler h) |
|---|
| 196 | : initiator<Handler>(s, h) |
|---|
| 197 | {} |
|---|
| 198 | protected: |
|---|
| 199 | int gnutls_action(); |
|---|
| 200 | }; |
|---|
| 201 | |
|---|
| 202 | template <typename Handler> |
|---|
| 203 | class io_initiator : public initiator_base |
|---|
| 204 | { |
|---|
| 205 | protected: |
|---|
| 206 | Handler handler; |
|---|
| 207 | virtual int gnutls_action() = 0; |
|---|
| 208 | public: |
|---|
| 209 | io_initiator(ptr s, Handler h) |
|---|
| 210 | : initiator_base(s), handler(h) |
|---|
| 211 | {} |
|---|
| 212 | void operator()(boost::shared_ptr<initiator_base>); |
|---|
| 213 | void kill(boost::shared_ptr<initiator_base>); |
|---|
| 214 | }; |
|---|
| 215 | |
|---|
| 216 | template <typename Handler> |
|---|
| 217 | class read_initiator : public io_initiator<Handler> |
|---|
| 218 | { |
|---|
| 219 | boost::asio::mutable_buffer mb; |
|---|
| 220 | int gnutls_action(); |
|---|
| 221 | public: |
|---|
| 222 | read_initiator(ptr s, |
|---|
| 223 | boost::asio::mutable_buffer mb, |
|---|
| 224 | Handler h) |
|---|
| 225 | : io_initiator<Handler>(s, h) |
|---|
| 226 | , mb(mb) |
|---|
| 227 | {} |
|---|
| 228 | }; |
|---|
| 229 | template <typename Handler> |
|---|
| 230 | class write_initiator : public io_initiator<Handler> |
|---|
| 231 | { |
|---|
| 232 | boost::asio::const_buffer cb; |
|---|
| 233 | int gnutls_action(); |
|---|
| 234 | public: |
|---|
| 235 | write_initiator(ptr s, |
|---|
| 236 | boost::asio::const_buffer cb, |
|---|
| 237 | Handler h) |
|---|
| 238 | : io_initiator<Handler>(s, h) |
|---|
| 239 | , cb(cb) |
|---|
| 240 | {} |
|---|
| 241 | }; |
|---|
| 242 | }; |
|---|
| 243 | |
|---|
| 244 | template <typename Stream> |
|---|
| 245 | class session : private boost::noncopyable |
|---|
| 246 | { |
|---|
| 247 | typename session_impl<Stream>::ptr impl; |
|---|
| 248 | public: |
|---|
| 249 | template <typename StreamInit> |
|---|
| 250 | session(StreamInit si, tls::init &tls_init, conn_end ce) |
|---|
| 251 | : impl(new session_impl<Stream>(si, tls_init, ce)) |
|---|
| 252 | {} |
|---|
| 253 | |
|---|
| 254 | session(Stream si, tls::init &tls_init, conn_end ce) |
|---|
| 255 | : impl(new session_impl<Stream>(si, tls_init, ce)) |
|---|
| 256 | {} |
|---|
| 257 | |
|---|
| 258 | ~session() { |
|---|
| 259 | try |
|---|
| 260 | { |
|---|
| 261 | impl->kill(); |
|---|
| 262 | } |
|---|
| 263 | catch (std::exception) |
|---|
| 264 | {} |
|---|
| 265 | } |
|---|
| 266 | |
|---|
| 267 | void kill() { impl->kill(); } |
|---|
| 268 | |
|---|
| 269 | template <typename Handler> |
|---|
| 270 | void async_handshake(Handler h) { impl->async_handshake(h); } |
|---|
| 271 | |
|---|
| 272 | template <typename Handler> |
|---|
| 273 | void async_shutdown(Handler h) { impl->async_shutdown(h); } |
|---|
| 274 | |
|---|
| 275 | template <typename MutableBufferSequence, typename Handler> |
|---|
| 276 | void async_read_some(MutableBufferSequence mbs, |
|---|
| 277 | Handler handler) |
|---|
| 278 | { impl->async_read_some(mbs, handler); } |
|---|
| 279 | |
|---|
| 280 | template <typename ConstBufferSequence, typename Handler> |
|---|
| 281 | void async_write_some(ConstBufferSequence cbs, Handler handler) |
|---|
| 282 | { impl->async_write_some(cbs, handler); } |
|---|
| 283 | |
|---|
| 284 | boost::asio::io_service &get_io_service() const |
|---|
| 285 | { return impl->get_io_service(); } |
|---|
| 286 | |
|---|
| 287 | boost::asio::io_service &io_service() const |
|---|
| 288 | { return impl->io_service(); } |
|---|
| 289 | }; |
|---|
| 290 | |
|---|
| 291 | } |
|---|
| 292 | |
|---|
| 293 | #endif |
|---|