async_bio.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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. #include "async_bio.h"
  15. #include <errno.h>
  16. #include <string.h>
  17. #include <openssl/bio.h>
  18. #include <openssl/mem.h>
  19. #include "../../crypto/internal.h"
  20. namespace {
  21. extern const BIO_METHOD g_async_bio_method;
  22. struct AsyncBio {
  23. bool datagram;
  24. bool enforce_write_quota;
  25. size_t read_quota;
  26. size_t write_quota;
  27. };
  28. AsyncBio *GetData(BIO *bio) {
  29. if (bio->method != &g_async_bio_method) {
  30. return NULL;
  31. }
  32. return (AsyncBio *)bio->ptr;
  33. }
  34. static int AsyncWrite(BIO *bio, const char *in, int inl) {
  35. AsyncBio *a = GetData(bio);
  36. if (a == NULL || bio->next_bio == NULL) {
  37. return 0;
  38. }
  39. if (!a->enforce_write_quota) {
  40. return BIO_write(bio->next_bio, in, inl);
  41. }
  42. BIO_clear_retry_flags(bio);
  43. if (a->write_quota == 0) {
  44. BIO_set_retry_write(bio);
  45. errno = EAGAIN;
  46. return -1;
  47. }
  48. if (!a->datagram && (size_t)inl > a->write_quota) {
  49. inl = a->write_quota;
  50. }
  51. int ret = BIO_write(bio->next_bio, in, inl);
  52. if (ret <= 0) {
  53. BIO_copy_next_retry(bio);
  54. } else {
  55. a->write_quota -= (a->datagram ? 1 : ret);
  56. }
  57. return ret;
  58. }
  59. static int AsyncRead(BIO *bio, char *out, int outl) {
  60. AsyncBio *a = GetData(bio);
  61. if (a == NULL || bio->next_bio == NULL) {
  62. return 0;
  63. }
  64. BIO_clear_retry_flags(bio);
  65. if (a->read_quota == 0) {
  66. BIO_set_retry_read(bio);
  67. errno = EAGAIN;
  68. return -1;
  69. }
  70. if (!a->datagram && (size_t)outl > a->read_quota) {
  71. outl = a->read_quota;
  72. }
  73. int ret = BIO_read(bio->next_bio, out, outl);
  74. if (ret <= 0) {
  75. BIO_copy_next_retry(bio);
  76. } else {
  77. a->read_quota -= (a->datagram ? 1 : ret);
  78. }
  79. return ret;
  80. }
  81. static long AsyncCtrl(BIO *bio, int cmd, long num, void *ptr) {
  82. if (bio->next_bio == NULL) {
  83. return 0;
  84. }
  85. BIO_clear_retry_flags(bio);
  86. int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
  87. BIO_copy_next_retry(bio);
  88. return ret;
  89. }
  90. static int AsyncNew(BIO *bio) {
  91. AsyncBio *a = (AsyncBio *)OPENSSL_malloc(sizeof(*a));
  92. if (a == NULL) {
  93. return 0;
  94. }
  95. OPENSSL_memset(a, 0, sizeof(*a));
  96. a->enforce_write_quota = true;
  97. bio->init = 1;
  98. bio->ptr = (char *)a;
  99. return 1;
  100. }
  101. static int AsyncFree(BIO *bio) {
  102. if (bio == NULL) {
  103. return 0;
  104. }
  105. OPENSSL_free(bio->ptr);
  106. bio->ptr = NULL;
  107. bio->init = 0;
  108. bio->flags = 0;
  109. return 1;
  110. }
  111. static long AsyncCallbackCtrl(BIO *bio, int cmd, bio_info_cb fp) {
  112. if (bio->next_bio == NULL) {
  113. return 0;
  114. }
  115. return BIO_callback_ctrl(bio->next_bio, cmd, fp);
  116. }
  117. const BIO_METHOD g_async_bio_method = {
  118. BIO_TYPE_FILTER,
  119. "async bio",
  120. AsyncWrite,
  121. AsyncRead,
  122. NULL /* puts */,
  123. NULL /* gets */,
  124. AsyncCtrl,
  125. AsyncNew,
  126. AsyncFree,
  127. AsyncCallbackCtrl,
  128. };
  129. } // namespace
  130. bssl::UniquePtr<BIO> AsyncBioCreate() {
  131. return bssl::UniquePtr<BIO>(BIO_new(&g_async_bio_method));
  132. }
  133. bssl::UniquePtr<BIO> AsyncBioCreateDatagram() {
  134. bssl::UniquePtr<BIO> ret(BIO_new(&g_async_bio_method));
  135. if (!ret) {
  136. return nullptr;
  137. }
  138. GetData(ret.get())->datagram = true;
  139. return ret;
  140. }
  141. void AsyncBioAllowRead(BIO *bio, size_t count) {
  142. AsyncBio *a = GetData(bio);
  143. if (a == NULL) {
  144. return;
  145. }
  146. a->read_quota += count;
  147. }
  148. void AsyncBioAllowWrite(BIO *bio, size_t count) {
  149. AsyncBio *a = GetData(bio);
  150. if (a == NULL) {
  151. return;
  152. }
  153. a->write_quota += count;
  154. }
  155. void AsyncBioEnforceWriteQuota(BIO *bio, bool enforce) {
  156. AsyncBio *a = GetData(bio);
  157. if (a == NULL) {
  158. return;
  159. }
  160. a->enforce_write_quota = enforce;
  161. }