tap_bio.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
  3. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  4. *
  5. * Licensed under the OpenSSL license (the "License"). You may not use
  6. * this file except in compliance with the License. You can obtain a copy
  7. * in the file LICENSE in the source distribution or at
  8. * https://www.openssl.org/source/license.html
  9. */
  10. #include <string.h>
  11. #include "tu_local.h"
  12. static int tap_write_ex(BIO *b, const char *buf, size_t size, size_t *in_size);
  13. static int tap_read_ex(BIO *b, char *buf, size_t size, size_t *out_size);
  14. static int tap_puts(BIO *b, const char *str);
  15. static int tap_gets(BIO *b, char *str, int size);
  16. static long tap_ctrl(BIO *b, int cmd, long arg1, void *arg2);
  17. static int tap_new(BIO *b);
  18. static int tap_free(BIO *b);
  19. static long tap_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
  20. const BIO_METHOD *BIO_f_tap(void)
  21. {
  22. static BIO_METHOD *tap = NULL;
  23. if (tap == NULL) {
  24. tap = BIO_meth_new(BIO_TYPE_START | BIO_TYPE_FILTER, "tap");
  25. if (tap != NULL) {
  26. BIO_meth_set_write_ex(tap, tap_write_ex);
  27. BIO_meth_set_read_ex(tap, tap_read_ex);
  28. BIO_meth_set_puts(tap, tap_puts);
  29. BIO_meth_set_gets(tap, tap_gets);
  30. BIO_meth_set_ctrl(tap, tap_ctrl);
  31. BIO_meth_set_create(tap, tap_new);
  32. BIO_meth_set_destroy(tap, tap_free);
  33. BIO_meth_set_callback_ctrl(tap, tap_callback_ctrl);
  34. }
  35. }
  36. return tap;
  37. }
  38. static int tap_new(BIO *b)
  39. {
  40. BIO_set_data(b, NULL);
  41. BIO_set_init(b, 1);
  42. return 1;
  43. }
  44. static int tap_free(BIO *b)
  45. {
  46. if (b == NULL)
  47. return 0;
  48. BIO_set_data(b, NULL);
  49. BIO_set_init(b, 0);
  50. return 1;
  51. }
  52. static int tap_read_ex(BIO *b, char *buf, size_t size, size_t *out_size)
  53. {
  54. BIO *next = BIO_next(b);
  55. int ret = 0;
  56. ret = BIO_read_ex(next, buf, size, out_size);
  57. BIO_clear_retry_flags(b);
  58. BIO_copy_next_retry(b);
  59. return ret;
  60. }
  61. /*
  62. * Output a string to the specified bio and return 1 if successful.
  63. */
  64. static int write_string(BIO *b, const char *buf, size_t n)
  65. {
  66. size_t m;
  67. return BIO_write_ex(b, buf, n, &m) != 0 && m == n;
  68. }
  69. /*
  70. * Write some data.
  71. *
  72. * This function implements a simple state machine that detects new lines.
  73. * It indents the output and prefixes it with a '#' character.
  74. *
  75. * It returns the number of input characters that were output in in_size.
  76. * More characters than this will likely have been output however any calling
  77. * code will be unable to correctly assess the actual number of characters
  78. * emitted and would be prone to failure if the actual number were returned.
  79. *
  80. * The BIO_data field is used as our state. If it is NULL, we've just
  81. * seen a new line. If it is not NULL, we're processing characters in a line.
  82. */
  83. static int tap_write_ex(BIO *b, const char *buf, size_t size, size_t *in_size)
  84. {
  85. BIO *next = BIO_next(b);
  86. size_t i;
  87. int j;
  88. for (i = 0; i < size; i++) {
  89. if (BIO_get_data(b) == NULL) {
  90. BIO_set_data(b, "");
  91. for (j = 0; j < subtest_level(); j++)
  92. if (!write_string(next, " ", 1))
  93. goto err;
  94. if (!write_string(next, "# ", 2))
  95. goto err;
  96. }
  97. if (!write_string(next, buf + i, 1))
  98. goto err;
  99. if (buf[i] == '\n')
  100. BIO_set_data(b, NULL);
  101. }
  102. *in_size = i;
  103. return 1;
  104. err:
  105. *in_size = i;
  106. return 0;
  107. }
  108. static long tap_ctrl(BIO *b, int cmd, long num, void *ptr)
  109. {
  110. BIO *next = BIO_next(b);
  111. switch (cmd) {
  112. case BIO_CTRL_RESET:
  113. BIO_set_data(b, NULL);
  114. break;
  115. default:
  116. break;
  117. }
  118. return BIO_ctrl(next, cmd, num, ptr);
  119. }
  120. static long tap_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
  121. {
  122. return BIO_callback_ctrl(BIO_next(b), cmd, fp);
  123. }
  124. static int tap_gets(BIO *b, char *buf, int size)
  125. {
  126. return BIO_gets(BIO_next(b), buf, size);
  127. }
  128. static int tap_puts(BIO *b, const char *str)
  129. {
  130. size_t m;
  131. if (!tap_write_ex(b, str, strlen(str), &m))
  132. return 0;
  133. return m;
  134. }