OpenVPN 3 Core Library
Loading...
Searching...
No Matches
bio_memq_stream.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// This code implements an OpenSSL BIO object for streams based on the
13// MemQ buffer queue object.
14
15#pragma once
16
17#include <cstring> // for std::strlen and others
18
19#include <openssl/err.h>
20#include <openssl/bio.h>
21
27
29
31
32class MemQ : public MemQStream
33{
34 public:
35 MemQ() = default;
36
37 long ctrl(BIO *b, int cmd, long num, void *ptr)
38 {
39 long ret = 1;
40
41 switch (cmd)
42 {
43 case BIO_CTRL_RESET:
44 clear();
45 break;
46 case BIO_CTRL_EOF:
47 ret = (long)empty();
48 break;
49 case BIO_C_SET_BUF_MEM_EOF_RETURN:
50 return_eof_on_empty = (num == 0);
51 break;
52 case BIO_CTRL_GET_CLOSE:
53 ret = BIO_get_shutdown(b);
54 break;
55 case BIO_CTRL_SET_CLOSE:
56 BIO_set_shutdown(b, (int)num);
57 break;
58 case BIO_CTRL_WPENDING:
59 ret = 0L;
60 break;
61 case BIO_CTRL_PENDING:
62 ret = (long)pending();
63 break;
64 case BIO_CTRL_DUP:
65 case BIO_CTRL_FLUSH:
66 ret = 1;
67 break;
68 default:
69 // OPENVPN_LOG("*** MemQ-stream unimplemented ctrl method=" << cmd);
70 ret = 0;
71 break;
72 }
73 return (ret);
74 }
75
76 bool return_eof_on_empty = false;
77};
78
80{
81 public:
82 inline static int memq_method_type = -1;
83 inline static BIO_METHOD *memq_method = nullptr;
84
85
86 static inline int memq_new(BIO *b)
87 {
88 MemQ *bmq = new (std::nothrow) MemQ();
89 if (!bmq)
90 return 0;
91 BIO_set_shutdown(b, 1);
92 BIO_set_init(b, 1);
93 BIO_set_data(b, (void *)bmq);
94 return 1;
95 }
96
97 static inline int memq_free(BIO *b)
98 {
99 if (b == nullptr)
100 return (0);
101 if (BIO_get_shutdown(b))
102 {
103 MemQ *bmq = (MemQ *)(BIO_get_data(b));
104 if (BIO_get_init(b) && (bmq != nullptr))
105 {
106 delete bmq;
107 BIO_set_data(b, nullptr);
108 }
109 }
110 return 1;
111 }
112
113 static inline int memq_write(BIO *b, const char *in, int len)
114 {
115 MemQ *bmq = (MemQ *)(BIO_get_data(b));
116 if (in)
117 {
118 BIO_clear_retry_flags(b);
119 try
120 {
121 if (len)
122 bmq->write((const unsigned char *)in, (size_t)len);
123 return len;
124 }
125 catch (...)
126 {
127 BIOerr(BIO_F_MEM_WRITE, BIO_R_INVALID_ARGUMENT);
128 return -1;
129 }
130 }
131 else
132 {
133 BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER);
134 return -1;
135 }
136 }
137
138 static inline int memq_read(BIO *b, char *out, int size)
139 {
140 MemQ *bmq = (MemQ *)(BIO_get_data(b));
141 int ret = -1;
142 BIO_clear_retry_flags(b);
143 if (!bmq->empty())
144 {
145 try
146 {
147 ret = (int)bmq->read((unsigned char *)out, (size_t)size);
148 }
149 catch (...)
150 {
151 BIOerr(memq_method_type, BIO_R_INVALID_ARGUMENT);
152 return -1;
153 }
154 }
155 else
156 {
157 if (!bmq->return_eof_on_empty)
158 BIO_set_retry_read(b);
159 }
160 return ret;
161 }
162
163 static inline long memq_ctrl(BIO *b, int cmd, long arg1, void *arg2)
164 {
165 MemQ *bmq = (MemQ *)(BIO_get_data(b));
166 return bmq->ctrl(b, cmd, arg1, arg2);
167 }
168
169 static inline int memq_puts(BIO *b, const char *str)
170 {
171 int ret = -1;
172 auto len = std::strlen(str);
173 if (is_safe_conversion<int>(len))
174 {
175 ret = memq_write(b, str, static_cast<int>(len));
176 }
177 return ret;
178 }
179
180 static inline void init_static()
181 {
182 memq_method_type = BIO_get_new_index();
183 memq_method = BIO_meth_new(memq_method_type, "stream memory queue");
184 BIO_meth_set_write(memq_method, memq_write);
185 BIO_meth_set_read(memq_method, memq_read);
186 BIO_meth_set_puts(memq_method, memq_puts);
187 BIO_meth_set_create(memq_method, memq_new);
188 BIO_meth_set_destroy(memq_method, memq_free);
189 BIO_meth_set_gets(memq_method, nullptr);
190 BIO_meth_set_ctrl(memq_method, memq_ctrl);
191 }
192
193 static inline void free_bio_method()
194 {
195 BIO_meth_free(memq_method);
196 memq_method = nullptr;
197 }
198}; // class bio_memq_internal
199
200inline void init_static()
201{
203}
204
205inline BIO_METHOD *BIO_s_memq(void)
206{
208}
209
210inline MemQ *memq_from_bio(BIO *b)
211{
212 if (BIO_method_type(b) == bio_memq_internal::memq_method_type)
213 return (MemQ *)(BIO_get_data(b));
214 return nullptr;
215}
216
217inline const MemQ *const_memq_from_bio(const BIO *b)
218{
219 if (BIO_method_type(b) == bio_memq_internal::memq_method_type)
220 return (const MemQ *)(BIO_get_data(const_cast<BIO *>(b)));
221 return nullptr;
222}
223} // namespace openvpn::bmq_stream
bool empty() const
Definition memq.hpp:37
void write(const unsigned char *data, size_t size)
size_t read(unsigned char *data, size_t len)
size_t pending() const
long ctrl(BIO *b, int cmd, long num, void *ptr)
static long memq_ctrl(BIO *b, int cmd, long arg1, void *arg2)
static int memq_puts(BIO *b, const char *str)
static int memq_read(BIO *b, char *out, int size)
static int memq_write(BIO *b, const char *in, int len)
BIO_METHOD * BIO_s_memq(void)
MemQ * memq_from_bio(BIO *b)
const MemQ * const_memq_from_bio(const BIO *b)
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'
std::string ret
static std::stringstream out
Definition test_path.cpp:10