Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

361 lignes
10 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. #if !defined(_POSIX_C_SOURCE)
  15. #define _POSIX_C_SOURCE 201410L
  16. #endif
  17. #include <openssl/base.h>
  18. #if !defined(OPENSSL_WINDOWS)
  19. #include <arpa/inet.h>
  20. #include <fcntl.h>
  21. #include <netinet/in.h>
  22. #include <string.h>
  23. #include <sys/socket.h>
  24. #include <unistd.h>
  25. #else
  26. #include <io.h>
  27. #include <WinSock2.h>
  28. #include <WS2tcpip.h>
  29. #endif
  30. #include <openssl/bio.h>
  31. #include <openssl/crypto.h>
  32. #include <openssl/err.h>
  33. #define MIN(a, b) ((a < b) ? a : b)
  34. #if !defined(OPENSSL_WINDOWS)
  35. static int closesocket(int sock) {
  36. return close(sock);
  37. }
  38. static void print_socket_error(const char *func) {
  39. perror(func);
  40. }
  41. #else
  42. static void print_socket_error(const char *func) {
  43. fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
  44. }
  45. #endif
  46. static int test_socket_connect(void) {
  47. int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
  48. int sock;
  49. struct sockaddr_in sin;
  50. socklen_t sockaddr_len = sizeof(sin);
  51. static const char kTestMessage[] = "test";
  52. char hostname[80], buf[5];
  53. BIO *bio;
  54. memset(&sin, 0, sizeof(sin));
  55. sin.sin_family = AF_INET;
  56. if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
  57. print_socket_error("inet_pton");
  58. return 0;
  59. }
  60. if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
  61. print_socket_error("bind");
  62. return 0;
  63. }
  64. if (listen(listening_sock, 1)) {
  65. print_socket_error("listen");
  66. return 0;
  67. }
  68. if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
  69. sockaddr_len != sizeof(sin)) {
  70. print_socket_error("getsockname");
  71. return 0;
  72. }
  73. BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
  74. ntohs(sin.sin_port));
  75. bio = BIO_new_connect(hostname);
  76. if (!bio) {
  77. fprintf(stderr, "BIO_new_connect failed.\n");
  78. return 0;
  79. }
  80. if (BIO_write(bio, kTestMessage, sizeof(kTestMessage)) !=
  81. sizeof(kTestMessage)) {
  82. fprintf(stderr, "BIO_write failed.\n");
  83. BIO_print_errors_fp(stderr);
  84. return 0;
  85. }
  86. sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
  87. if (sock < 0) {
  88. print_socket_error("accept");
  89. return 0;
  90. }
  91. if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
  92. print_socket_error("read");
  93. return 0;
  94. }
  95. if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
  96. return 0;
  97. }
  98. closesocket(sock);
  99. closesocket(listening_sock);
  100. BIO_free(bio);
  101. return 1;
  102. }
  103. /* bio_read_zero_copy_wrapper is a wrapper around the zero-copy APIs to make
  104. * testing easier. */
  105. static size_t bio_read_zero_copy_wrapper(BIO *bio, uint8_t *data, size_t len) {
  106. uint8_t *read_buf;
  107. size_t read_buf_offset;
  108. size_t available_bytes;
  109. size_t len_read = 0;
  110. do {
  111. if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset,
  112. &available_bytes)) {
  113. return 0;
  114. }
  115. available_bytes = MIN(available_bytes, len - len_read);
  116. memmove(data + len_read, read_buf + read_buf_offset, available_bytes);
  117. BIO_zero_copy_get_read_buf_done(bio, available_bytes);
  118. len_read += available_bytes;
  119. } while (len - len_read > 0 && available_bytes > 0);
  120. return len_read;
  121. }
  122. /* bio_write_zero_copy_wrapper is a wrapper around the zero-copy APIs to make
  123. * testing easier. */
  124. static size_t bio_write_zero_copy_wrapper(BIO *bio, const uint8_t *data,
  125. size_t len) {
  126. uint8_t *write_buf;
  127. size_t write_buf_offset;
  128. size_t available_bytes;
  129. size_t len_written = 0;
  130. do {
  131. if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset,
  132. &available_bytes)) {
  133. return 0;
  134. }
  135. available_bytes = MIN(available_bytes, len - len_written);
  136. memmove(write_buf + write_buf_offset, data + len_written, available_bytes);
  137. BIO_zero_copy_get_write_buf_done(bio, available_bytes);
  138. len_written += available_bytes;
  139. } while (len - len_written > 0 && available_bytes > 0);
  140. return len_written;
  141. }
  142. static int test_zero_copy_bio_pairs(void) {
  143. /* Test read and write, especially triggering the ring buffer wrap-around.*/
  144. BIO* bio1;
  145. BIO* bio2;
  146. size_t i, j;
  147. uint8_t bio1_application_send_buffer[1024];
  148. uint8_t bio2_application_recv_buffer[1024];
  149. size_t total_read = 0;
  150. size_t total_write = 0;
  151. uint8_t* write_buf;
  152. size_t write_buf_offset;
  153. size_t available_bytes;
  154. size_t bytes_left;
  155. const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513};
  156. /* These trigger ring buffer wrap around. */
  157. const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512};
  158. static const size_t kBufferSize = 512;
  159. srand(1);
  160. for (i = 0; i < sizeof(bio1_application_send_buffer); i++) {
  161. bio1_application_send_buffer[i] = rand() & 255;
  162. }
  163. /* Transfer bytes from bio1_application_send_buffer to
  164. * bio2_application_recv_buffer in various ways. */
  165. for (i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
  166. for (j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]); j++) {
  167. total_write = 0;
  168. total_read = 0;
  169. BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize);
  170. total_write += bio_write_zero_copy_wrapper(
  171. bio1, bio1_application_send_buffer, kLengths[i]);
  172. /* This tests interleaved read/write calls. Do a read between zero copy
  173. * write calls. */
  174. if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset,
  175. &available_bytes)) {
  176. return 0;
  177. }
  178. /* Free kPartialLengths[j] bytes in the beginning of bio1 write buffer.
  179. * This enables ring buffer wrap around for the next write. */
  180. total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read,
  181. kPartialLengths[j]);
  182. size_t interleaved_write_len = MIN(kPartialLengths[j], available_bytes);
  183. /* Write the data for the interleaved write call. If the buffer becomes
  184. * empty after a read, the write offset is normally set to 0. Check that
  185. * this does not happen for interleaved read/write and that
  186. * |write_buf_offset| is still valid. */
  187. memcpy(write_buf + write_buf_offset,
  188. bio1_application_send_buffer + total_write, interleaved_write_len);
  189. if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) {
  190. total_write += interleaved_write_len;
  191. }
  192. /* Do another write in case |write_buf_offset| was wrapped */
  193. total_write += bio_write_zero_copy_wrapper(
  194. bio1, bio1_application_send_buffer + total_write,
  195. kPartialLengths[j] - interleaved_write_len);
  196. /* Drain the rest. */
  197. bytes_left = BIO_pending(bio2);
  198. total_read += bio_read_zero_copy_wrapper(
  199. bio2, bio2_application_recv_buffer + total_read, bytes_left);
  200. BIO_free(bio1);
  201. BIO_free(bio2);
  202. if (total_read != total_write) {
  203. fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i,
  204. (unsigned)j);
  205. return 0;
  206. }
  207. if (total_read > kLengths[i] + kPartialLengths[j]) {
  208. fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i,
  209. (unsigned)j);
  210. return 0;
  211. }
  212. if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer,
  213. total_read) != 0) {
  214. fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i,
  215. (unsigned)j);
  216. return 0;
  217. }
  218. }
  219. }
  220. return 1;
  221. }
  222. static int test_printf(void) {
  223. /* Test a short output, a very long one, and various sizes around
  224. * 256 (the size of the buffer) to ensure edge cases are correct. */
  225. static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
  226. BIO *bio;
  227. char string[1024];
  228. int ret;
  229. const uint8_t *contents;
  230. size_t i, len;
  231. bio = BIO_new(BIO_s_mem());
  232. if (!bio) {
  233. fprintf(stderr, "BIO_new failed\n");
  234. return 0;
  235. }
  236. for (i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
  237. if (kLengths[i] >= sizeof(string)) {
  238. fprintf(stderr, "Bad test string length\n");
  239. return 0;
  240. }
  241. memset(string, 'a', sizeof(string));
  242. string[kLengths[i]] = '\0';
  243. ret = BIO_printf(bio, "test %s", string);
  244. if (ret != 5 + kLengths[i]) {
  245. fprintf(stderr, "BIO_printf failed: %d\n", ret);
  246. return 0;
  247. }
  248. if (!BIO_mem_contents(bio, &contents, &len)) {
  249. fprintf(stderr, "BIO_mem_contents failed\n");
  250. return 0;
  251. }
  252. if (len != 5 + kLengths[i] ||
  253. strncmp((const char *)contents, "test ", 5) != 0 ||
  254. strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
  255. fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
  256. return 0;
  257. }
  258. if (!BIO_reset(bio)) {
  259. fprintf(stderr, "BIO_reset failed\n");
  260. return 0;
  261. }
  262. }
  263. BIO_free(bio);
  264. return 1;
  265. }
  266. int main(void) {
  267. #if defined(OPENSSL_WINDOWS)
  268. WSADATA wsa_data;
  269. WORD wsa_version;
  270. int wsa_err;
  271. #endif
  272. CRYPTO_library_init();
  273. ERR_load_crypto_strings();
  274. #if defined(OPENSSL_WINDOWS)
  275. /* Initialize Winsock. */
  276. wsa_version = MAKEWORD(2, 2);
  277. wsa_err = WSAStartup(wsa_version, &wsa_data);
  278. if (wsa_err != 0) {
  279. fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
  280. return 1;
  281. }
  282. if (wsa_data.wVersion != wsa_version) {
  283. fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
  284. return 1;
  285. }
  286. #endif
  287. if (!test_socket_connect()) {
  288. return 1;
  289. }
  290. if (!test_printf()) {
  291. return 1;
  292. }
  293. if (!test_zero_copy_bio_pairs()) {
  294. return 1;
  295. }
  296. printf("PASS\n");
  297. return 0;
  298. }