root/tls/ringbuf.cc

Revision 08f5bd75ad170e6b8177b93e98f40d0f8a51b9d2, 2.8 KB (checked in by Antti-Juhani Kaijanaho <antti-juhani@…>, 22 months ago)

[tls::session] Use ring buffers instead of dynamically growing buffers

This way enbuffering cannot throw bad_alloc.

Closes #69.

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 © 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#include "ringbuf.hh"
21
22namespace {
23        typedef boost::asio::mutable_buffer mb;
24        typedef boost::asio::const_buffer cb;
25        using boost::asio::buffer_cast;
26        using boost::asio::buffer_size;
27}
28
29namespace tls
30{
31
32        std::vector<mb> ringbuf::write_area()
33        {
34                std::vector<mb> rv;
35                if (n == N) return rv;
36                if (wrs1() > 0) rv.push_back(mb(wra1(), wrs1()));
37                if (wrs2() > 0) rv.push_back(mb(wra2(), wrs2()));
38                return rv;
39        }
40        std::vector<cb> ringbuf::read_area() const
41        {
42                std::vector<cb> rv;
43                if (n == 0) return rv;
44                if (rds1() > 0) rv.push_back(cb(rda1(), rds1()));
45                if (rds2() > 0) rv.push_back(cb(rda2(), rds2()));
46                return rv;
47        }
48        size_t ringbuf::get(unsigned char *out, size_t k)
49        {
50                size_t rv = 0;
51                std::vector<cb> cbs = read_area();
52                for (size_t i = 0; i < cbs.size() && rv < k; i++)
53                {
54                        size_t nuff = buffer_size(cbs[i]);
55                        if (nuff > k - rv) nuff = k - rv;
56                        std::memcpy(out + rv,
57                                    buffer_cast<const unsigned char *>(cbs[i]),
58                                    nuff);
59                        rv += nuff;
60                }
61                read(rv);
62                return rv;
63        }
64        size_t ringbuf::put(const unsigned char *in, size_t k)
65        {
66                size_t rv = 0;
67                std::vector<mb> mbs = write_area();
68                for (size_t i = 0; i < mbs.size() && rv < k; i++)
69                {
70                        size_t nuff = buffer_size(mbs[i]);
71                        if (nuff > k - rv) nuff = k - rv;
72                        std::memcpy(buffer_cast<unsigned char *>(mbs[i]),
73                                    in + rv, nuff);
74                        rv += nuff;
75                }
76                written(rv);
77                return rv;
78        }
79}
Note: See TracBrowser for help on using the browser.