async_bio.cc
Go to the documentation of this file.
1 /* Copyright (c) 2014, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include "async_bio.h"
16 
17 #include <errno.h>
18 #include <string.h>
19 
20 #include <openssl/bio.h>
21 #include <openssl/mem.h>
22 
23 #include "../../crypto/internal.h"
24 
25 
26 namespace {
27 
28 extern const BIO_METHOD g_async_bio_method;
29 
30 struct AsyncBio {
31  bool datagram;
32  bool enforce_write_quota;
33  size_t read_quota;
34  size_t write_quota;
35 };
36 
37 AsyncBio *GetData(BIO *bio) {
38  if (bio->method != &g_async_bio_method) {
39  return NULL;
40  }
41  return (AsyncBio *)bio->ptr;
42 }
43 
44 static int AsyncWrite(BIO *bio, const char *in, int inl) {
45  AsyncBio *a = GetData(bio);
46  if (a == NULL || bio->next_bio == NULL) {
47  return 0;
48  }
49 
50  if (!a->enforce_write_quota) {
51  return BIO_write(bio->next_bio, in, inl);
52  }
53 
55 
56  if (a->write_quota == 0) {
58  errno = EAGAIN;
59  return -1;
60  }
61 
62  if (!a->datagram && (size_t)inl > a->write_quota) {
63  inl = a->write_quota;
64  }
65  int ret = BIO_write(bio->next_bio, in, inl);
66  if (ret <= 0) {
68  } else {
69  a->write_quota -= (a->datagram ? 1 : ret);
70  }
71  return ret;
72 }
73 
74 static int AsyncRead(BIO *bio, char *out, int outl) {
75  AsyncBio *a = GetData(bio);
76  if (a == NULL || bio->next_bio == NULL) {
77  return 0;
78  }
79 
81 
82  if (a->read_quota == 0) {
83  BIO_set_retry_read(bio);
84  errno = EAGAIN;
85  return -1;
86  }
87 
88  if (!a->datagram && (size_t)outl > a->read_quota) {
89  outl = a->read_quota;
90  }
91  int ret = BIO_read(bio->next_bio, out, outl);
92  if (ret <= 0) {
94  } else {
95  a->read_quota -= (a->datagram ? 1 : ret);
96  }
97  return ret;
98 }
99 
100 static long AsyncCtrl(BIO *bio, int cmd, long num, void *ptr) {
101  if (bio->next_bio == NULL) {
102  return 0;
103  }
105  int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
106  BIO_copy_next_retry(bio);
107  return ret;
108 }
109 
110 static int AsyncNew(BIO *bio) {
111  AsyncBio *a = (AsyncBio *)OPENSSL_malloc(sizeof(*a));
112  if (a == NULL) {
113  return 0;
114  }
115  OPENSSL_memset(a, 0, sizeof(*a));
116  a->enforce_write_quota = true;
117  bio->init = 1;
118  bio->ptr = (char *)a;
119  return 1;
120 }
121 
122 static int AsyncFree(BIO *bio) {
123  if (bio == NULL) {
124  return 0;
125  }
126 
127  OPENSSL_free(bio->ptr);
128  bio->ptr = NULL;
129  bio->init = 0;
130  bio->flags = 0;
131  return 1;
132 }
133 
134 static long AsyncCallbackCtrl(BIO *bio, int cmd, bio_info_cb fp) {
135  if (bio->next_bio == NULL) {
136  return 0;
137  }
138  return BIO_callback_ctrl(bio->next_bio, cmd, fp);
139 }
140 
141 const BIO_METHOD g_async_bio_method = {
143  "async bio",
144  AsyncWrite,
145  AsyncRead,
146  NULL /* puts */,
147  NULL /* gets */,
148  AsyncCtrl,
149  AsyncNew,
150  AsyncFree,
151  AsyncCallbackCtrl,
152 };
153 
154 } // namespace
155 
156 bssl::UniquePtr<BIO> AsyncBioCreate() {
157  return bssl::UniquePtr<BIO>(BIO_new(&g_async_bio_method));
158 }
159 
160 bssl::UniquePtr<BIO> AsyncBioCreateDatagram() {
161  bssl::UniquePtr<BIO> ret(BIO_new(&g_async_bio_method));
162  if (!ret) {
163  return nullptr;
164  }
165  GetData(ret.get())->datagram = true;
166  return ret;
167 }
168 
169 void AsyncBioAllowRead(BIO *bio, size_t count) {
170  AsyncBio *a = GetData(bio);
171  if (a == NULL) {
172  return;
173  }
174  a->read_quota += count;
175 }
176 
177 void AsyncBioAllowWrite(BIO *bio, size_t count) {
178  AsyncBio *a = GetData(bio);
179  if (a == NULL) {
180  return;
181  }
182  a->write_quota += count;
183 }
184 
185 void AsyncBioEnforceWriteQuota(BIO *bio, bool enforce) {
186  AsyncBio *a = GetData(bio);
187  if (a == NULL) {
188  return;
189  }
190  a->enforce_write_quota = enforce;
191 }
bio_method_st
Definition: bio.h:808
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
bio_info_cb
long(* bio_info_cb)(BIO *bio, int event, const char *parg, int cmd, long larg, long return_value)
Definition: bio.h:246
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
bio_st::next_bio
BIO * next_bio
Definition: bio.h:841
bio_st
Definition: bio.h:822
bio_st::ptr
void * ptr
Definition: bio.h:838
bio_st::flags
int flags
Definition: bio.h:832
BIO_TYPE_FILTER
#define BIO_TYPE_FILTER
Definition: bio.h:801
BIO_set_retry_write
#define BIO_set_retry_write
Definition: boringssl_prefix_symbols.h:856
AsyncBioCreateDatagram
bssl::UniquePtr< BIO > AsyncBioCreateDatagram()
Definition: async_bio.cc:160
bio.h
string.h
bio_st::init
int init
Definition: bio.h:826
BIO_write
#define BIO_write
Definition: boringssl_prefix_symbols.h:870
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
AsyncBioEnforceWriteQuota
void AsyncBioEnforceWriteQuota(BIO *bio, bool enforce)
Definition: async_bio.cc:185
BIO_read
#define BIO_read
Definition: boringssl_prefix_symbols.h:831
OPENSSL_memset
static void * OPENSSL_memset(void *dst, int c, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:835
async_bio.h
BIO_copy_next_retry
#define BIO_copy_next_retry
Definition: boringssl_prefix_symbols.h:778
OPENSSL_malloc
#define OPENSSL_malloc
Definition: boringssl_prefix_symbols.h:1885
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
AsyncBioAllowWrite
void AsyncBioAllowWrite(BIO *bio, size_t count)
Definition: async_bio.cc:177
BIO_ctrl
#define BIO_ctrl
Definition: boringssl_prefix_symbols.h:779
bio_st::method
const BIO_METHOD * method
Definition: bio.h:823
regen-readme.cmd
cmd
Definition: regen-readme.py:21
BIO_callback_ctrl
#define BIO_callback_ctrl
Definition: boringssl_prefix_symbols.h:775
BIO_new
#define BIO_new
Definition: boringssl_prefix_symbols.h:814
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
AsyncBioAllowRead
void AsyncBioAllowRead(BIO *bio, size_t count)
Definition: async_bio.cc:169
AsyncBioCreate
bssl::UniquePtr< BIO > AsyncBioCreate()
Definition: async_bio.cc:156
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
absl::span_internal::GetData
constexpr auto GetData(C &c) noexcept -> decltype(GetDataImpl(c, 0))
Definition: abseil-cpp/absl/types/internal/span.h:49
xds_manager.num
num
Definition: xds_manager.py:56
mem.h
OPENSSL_free
#define OPENSSL_free
Definition: boringssl_prefix_symbols.h:1869
BIO_set_retry_read
#define BIO_set_retry_read
Definition: boringssl_prefix_symbols.h:853
errno.h
BIO_clear_retry_flags
#define BIO_clear_retry_flags
Definition: boringssl_prefix_symbols.h:777


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:35