Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

190 wiersze
4.0 KiB

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