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:
36 {
37 }
38
39 long ctrl(BIO *b, int cmd, long num, void *ptr)
40 {
41 long ret = 1;
42
43 switch (cmd)
44 {
45 case BIO_CTRL_RESET:
46 clear();
47 break;
48 case BIO_CTRL_EOF:
49 ret = (long)empty();
50 break;
51 case BIO_C_SET_BUF_MEM_EOF_RETURN:
52 return_eof_on_empty = (num == 0);
53 break;
54 case BIO_CTRL_GET_CLOSE:
55 ret = BIO_get_shutdown(b);
56 break;
57 case BIO_CTRL_SET_CLOSE:
58 BIO_set_shutdown(b, (int)num);
59 break;
60 case BIO_CTRL_WPENDING:
61 ret = 0L;
62 break;
63 case BIO_CTRL_PENDING:
64 ret = (long)pending();
65 break;
66 case BIO_CTRL_DUP:
67 case BIO_CTRL_FLUSH:
68 ret = 1;
69 break;
70 default:
71 // OPENVPN_LOG("*** MemQ-stream unimplemented ctrl method=" << cmd);
72 ret = 0;
73 break;
74 }
75 return (ret);
76 }
77
78 bool return_eof_on_empty = false;
79};
80
82{
83 public:
84 inline static int memq_method_type = -1;
85 inline static BIO_METHOD *memq_method = nullptr;
86
87
88 static inline int memq_new(BIO *b)
89 {
90 MemQ *bmq = new (std::nothrow) MemQ();
91 if (!bmq)
92 return 0;
93 BIO_set_shutdown(b, 1);
94 BIO_set_init(b, 1);
95 BIO_set_data(b, (void *)bmq);
96 return 1;
97 }
98
99 static inline int memq_free(BIO *b)
100 {
101 if (b == nullptr)
102 return (0);
103 if (BIO_get_shutdown(b))
104 {
105 MemQ *bmq = (MemQ *)(BIO_get_data(b));
106 if (BIO_get_init(b) && (bmq != nullptr))
107 {
108 delete bmq;
109 BIO_set_data(b, nullptr);
110 }
111 }
112 return 1;
113 }
114
115 static inline int memq_write(BIO *b, const char *in, int len)
116 {
117 MemQ *bmq = (MemQ *)(BIO_get_data(b));
118 if (in)
119 {
120 BIO_clear_retry_flags(b);
121 try
122 {
123 if (len)
124 bmq->write((const unsigned char *)in, (size_t)len);
125 return len;
126 }
127 catch (...)
128 {
129 BIOerr(BIO_F_MEM_WRITE, BIO_R_INVALID_ARGUMENT);
130 return -1;
131 }
132 }
133 else
134 {
135 BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER);
136 return -1;
137 }
138 }
139
140 static inline int memq_read(BIO *b, char *out, int size)
141 {
142 MemQ *bmq = (MemQ *)(BIO_get_data(b));
143 int ret = -1;
144 BIO_clear_retry_flags(b);
145 if (!bmq->empty())
146 {
147 try
148 {
149 ret = (int)bmq->read((unsigned char *)out, (size_t)size);
150 }
151 catch (...)
152 {
153 BIOerr(memq_method_type, BIO_R_INVALID_ARGUMENT);
154 return -1;
155 }
156 }
157 else
158 {
159 if (!bmq->return_eof_on_empty)
160 BIO_set_retry_read(b);
161 }
162 return ret;
163 }
164
165 static inline long memq_ctrl(BIO *b, int cmd, long arg1, void *arg2)
166 {
167 MemQ *bmq = (MemQ *)(BIO_get_data(b));
168 return bmq->ctrl(b, cmd, arg1, arg2);
169 }
170
171 static inline int memq_puts(BIO *b, const char *str)
172 {
173 int ret = -1;
174 auto len = std::strlen(str);
175 if (is_safe_conversion<int>(len))
176 {
177 ret = memq_write(b, str, static_cast<int>(len));
178 }
179 return ret;
180 }
181
182 static inline void init_static()
183 {
184 memq_method_type = BIO_get_new_index();
185 memq_method = BIO_meth_new(memq_method_type, "stream memory queue");
186 BIO_meth_set_write(memq_method, memq_write);
187 BIO_meth_set_read(memq_method, memq_read);
188 BIO_meth_set_puts(memq_method, memq_puts);
189 BIO_meth_set_create(memq_method, memq_new);
190 BIO_meth_set_destroy(memq_method, memq_free);
191 BIO_meth_set_gets(memq_method, nullptr);
192 BIO_meth_set_ctrl(memq_method, memq_ctrl);
193 }
194
195 static inline void free_bio_method()
196 {
197 BIO_meth_free(memq_method);
198 memq_method = nullptr;
199 }
200}; // class bio_memq_internal
201
202inline void init_static()
203{
205}
206
207inline BIO_METHOD *BIO_s_memq(void)
208{
210}
211
212inline MemQ *memq_from_bio(BIO *b)
213{
214 if (BIO_method_type(b) == bio_memq_internal::memq_method_type)
215 return (MemQ *)(BIO_get_data(b));
216 else
217 return nullptr;
218}
219
220inline const MemQ *const_memq_from_bio(const BIO *b)
221{
222 if (BIO_method_type(b) == bio_memq_internal::memq_method_type)
223 return (const MemQ *)(BIO_get_data(const_cast<BIO *>(b)));
224 else
225 return nullptr;
226}
227} // 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