File: buflist.hpp

package info (click to toggle)
openvpn3-client 25%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,276 kB
  • sloc: cpp: 190,085; python: 7,218; ansic: 1,866; sh: 1,361; java: 402; lisp: 81; makefile: 17
file content (112 lines) | stat: -rw-r--r-- 3,049 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//    OpenVPN -- An application to securely tunnel IP networks
//               over a single port, with support for SSL/TLS-based
//               session authentication and key exchange,
//               packet encryption, packet authentication, and
//               packet compression.
//
//    Copyright (C) 2012- OpenVPN Inc.
//
//    SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//

#ifndef OPENVPN_BUFFER_BUFLIST_H
#define OPENVPN_BUFFER_BUFLIST_H

#include <list>
#include <utility>

#include <openvpn/buffer/buffer.hpp>
#include <openvpn/buffer/bufstr.hpp>

namespace openvpn {

template <template <typename...> class COLLECTION>
struct BufferCollection : public COLLECTION<BufferPtr>
{
    using COLLECTION<BufferPtr>::size;
    using COLLECTION<BufferPtr>::front;
    using COLLECTION<BufferPtr>::empty;
    using COLLECTION<BufferPtr>::back;
    using COLLECTION<BufferPtr>::emplace_back;

    BufferPtr join(const size_t headroom,
                   const size_t tailroom,
                   const bool size_1_optim) const
    {
        // special optimization if list contains
        // a single element that satisfies our
        // headroom/tailroom constraints.
        if (size_1_optim
            && size() == 1
            && front()->offset() >= headroom
            && front()->remaining() >= tailroom)
            return front();

        // first pass -- measure total size
        const size_t size = join_size();

        // allocate buffer
        auto big = BufferAllocatedRc::Create(size + headroom + tailroom, 0);
        big->init_headroom(headroom);

        // second pass -- copy data
        for (auto &b : *this)
            big->write(b->c_data(), b->size());

        return big;
    }

    BufferPtr join() const
    {
        return join(0, 0, true);
    }

    size_t join_size() const
    {
        size_t size = 0;
        for (auto &b : *this)
            size += b->size();
        return size;
    }

    std::string to_string() const
    {
        BufferPtr bp = join();
        return buf_to_string(*bp);
    }

    BufferCollection copy() const
    {
        BufferCollection ret;
        for (auto &b : *this)
            ret.emplace_back(BufferAllocatedRc::Create(*b));
        return ret;
    }

    void put_consume(BufferAllocated &buf, const size_t tailroom = 0)
    {
        const size_t s = buf.size();
        if (!s)
            return;
        if (!empty())
        {
            // special optimization if buf data fits in
            // back() unused tail capacity -- if so, append
            // buf to existing back().
            BufferPtr &b = back();
            const size_t r = b->remaining(tailroom);
            if (s < r)
            {
                b->write(buf.read_alloc(s), s);
                return;
            }
        }
        emplace_back(BufferAllocatedRc::Create(std::move(buf)));
    }
};

typedef BufferCollection<std::list> BufferList;
typedef BufferCollection<std::vector> BufferVector;
} // namespace openvpn

#endif