root/tls/session.hh

Revision 81c6e32180ba6f1018c28ae75b7281fd38121812, 10.6 KB (checked in by Antti-Juhani Kaijanaho <antti-juhani@…>, 21 months ago)

Exception-proof destructors.

Hopefully addresses #78.

Signed-off-by: Antti-Juhani Kaijanaho <antti-juhani@…>

  • Property mode set to 100644
Line 
1/*  This file is part of Alue, the multiprotocol Internet discussion daemon
2
3    Copyright © 2009, 2010 Antti-Juhani Kaijanaho
4
5    Alue is free software: you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    Alue is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with Alue.  If not, see <http://www.gnu.org/licenses/>.
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
34namespace 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 /* GUARD_TLS_SESSION_HH */
Note: See TracBrowser for help on using the browser.