Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

181 строка
3.8 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/mem.h>
  18. namespace {
  19. extern const BIO_METHOD g_async_bio_method;
  20. struct AsyncBio {
  21. bool datagram;
  22. size_t read_quota;
  23. size_t write_quota;
  24. };
  25. AsyncBio *GetData(BIO *bio) {
  26. if (bio->method != &g_async_bio_method) {
  27. return NULL;
  28. }
  29. return (AsyncBio *)bio->ptr;
  30. }
  31. static int AsyncWrite(BIO *bio, const char *in, int inl) {
  32. AsyncBio *a = GetData(bio);
  33. if (a == NULL || bio->next_bio == NULL) {
  34. return 0;
  35. }
  36. if (a->datagram) {
  37. // Perform writes synchronously; the DTLS implementation drops any packets
  38. // that failed to send.
  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. bio->init = 1;
  96. bio->ptr = (char *)a;
  97. return 1;
  98. }
  99. static int AsyncFree(BIO *bio) {
  100. if (bio == NULL) {
  101. return 0;
  102. }
  103. OPENSSL_free(bio->ptr);
  104. bio->ptr = NULL;
  105. bio->init = 0;
  106. bio->flags = 0;
  107. return 1;
  108. }
  109. static long AsyncCallbackCtrl(BIO *bio, int cmd, bio_info_cb fp) {
  110. if (bio->next_bio == NULL) {
  111. return 0;
  112. }
  113. return BIO_callback_ctrl(bio->next_bio, cmd, fp);
  114. }
  115. const BIO_METHOD g_async_bio_method = {
  116. BIO_TYPE_FILTER,
  117. "async bio",
  118. AsyncWrite,
  119. AsyncRead,
  120. NULL /* puts */,
  121. NULL /* gets */,
  122. AsyncCtrl,
  123. AsyncNew,
  124. AsyncFree,
  125. AsyncCallbackCtrl,
  126. };
  127. } // namespace
  128. ScopedBIO AsyncBioCreate() {
  129. return ScopedBIO(BIO_new(&g_async_bio_method));
  130. }
  131. ScopedBIO AsyncBioCreateDatagram() {
  132. ScopedBIO ret(BIO_new(&g_async_bio_method));
  133. if (!ret) {
  134. return nullptr;
  135. }
  136. GetData(ret.get())->datagram = true;
  137. return ret;
  138. }
  139. void AsyncBioAllowRead(BIO *bio, size_t count) {
  140. AsyncBio *a = GetData(bio);
  141. if (a == NULL) {
  142. return;
  143. }
  144. a->read_quota += count;
  145. }
  146. void AsyncBioAllowWrite(BIO *bio, size_t count) {
  147. AsyncBio *a = GetData(bio);
  148. if (a == NULL) {
  149. return;
  150. }
  151. a->write_quota += count;
  152. }