quic_client_test.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <stdio.h>
  10. #include <openssl/ssl.h>
  11. #include <openssl/quic.h>
  12. #include <openssl/bio.h>
  13. #include "internal/common.h"
  14. #include "internal/sockets.h"
  15. #include "internal/time.h"
  16. #include "testutil.h"
  17. static const char msg1[] = "GET LICENSE.txt\r\n";
  18. static char msg2[16000];
  19. static int is_want(SSL *s, int ret)
  20. {
  21. int ec = SSL_get_error(s, ret);
  22. return ec == SSL_ERROR_WANT_READ || ec == SSL_ERROR_WANT_WRITE;
  23. }
  24. static int test_quic_client(void)
  25. {
  26. int testresult = 0, ret;
  27. int c_fd = INVALID_SOCKET;
  28. BIO *c_net_bio = NULL, *c_net_bio_own = NULL;
  29. BIO_ADDR *s_addr_ = NULL;
  30. struct in_addr ina = {0};
  31. SSL_CTX *c_ctx = NULL;
  32. SSL *c_ssl = NULL;
  33. short port = 4433;
  34. int c_connected = 0, c_write_done = 0, c_shutdown = 0;
  35. size_t l = 0, c_total_read = 0;
  36. OSSL_TIME start_time;
  37. unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '0', '.', '9' };
  38. ina.s_addr = htonl(0x7f000001UL);
  39. /* Setup test client. */
  40. c_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0);
  41. if (!TEST_int_ne(c_fd, INVALID_SOCKET))
  42. goto err;
  43. if (!TEST_true(BIO_socket_nbio(c_fd, 1)))
  44. goto err;
  45. if (!TEST_ptr(s_addr_ = BIO_ADDR_new()))
  46. goto err;
  47. if (!TEST_true(BIO_ADDR_rawmake(s_addr_, AF_INET, &ina, sizeof(ina),
  48. htons(port))))
  49. goto err;
  50. if (!TEST_ptr(c_net_bio = c_net_bio_own = BIO_new_dgram(c_fd, 0)))
  51. goto err;
  52. if (!BIO_dgram_set_peer(c_net_bio, s_addr_))
  53. goto err;
  54. if (!TEST_ptr(c_ctx = SSL_CTX_new(OSSL_QUIC_client_method())))
  55. goto err;
  56. if (!TEST_ptr(c_ssl = SSL_new(c_ctx)))
  57. goto err;
  58. /* 0 is a success for SSL_set_alpn_protos() */
  59. if (!TEST_false(SSL_set_alpn_protos(c_ssl, alpn, sizeof(alpn))))
  60. goto err;
  61. /* Takes ownership of our reference to the BIO. */
  62. SSL_set0_rbio(c_ssl, c_net_bio);
  63. /* Get another reference to be transferred in the SSL_set0_wbio call. */
  64. if (!TEST_true(BIO_up_ref(c_net_bio))) {
  65. c_net_bio_own = NULL; /* SSL_free will free the first reference. */
  66. goto err;
  67. }
  68. SSL_set0_wbio(c_ssl, c_net_bio);
  69. c_net_bio_own = NULL;
  70. if (!TEST_true(SSL_set_blocking_mode(c_ssl, 0)))
  71. goto err;
  72. start_time = ossl_time_now();
  73. for (;;) {
  74. if (ossl_time_compare(ossl_time_subtract(ossl_time_now(), start_time),
  75. ossl_ms2time(10000)) >= 0) {
  76. TEST_error("timeout while attempting QUIC client test");
  77. goto err;
  78. }
  79. if (!c_connected) {
  80. ret = SSL_connect(c_ssl);
  81. if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
  82. goto err;
  83. if (ret == 1) {
  84. c_connected = 1;
  85. TEST_info("Connected!");
  86. }
  87. }
  88. if (c_connected && !c_write_done) {
  89. if (!TEST_int_eq(SSL_write(c_ssl, msg1, sizeof(msg1) - 1),
  90. (int)sizeof(msg1) - 1))
  91. goto err;
  92. if (!TEST_true(SSL_stream_conclude(c_ssl, 0)))
  93. goto err;
  94. c_write_done = 1;
  95. }
  96. if (c_write_done && !c_shutdown && c_total_read < sizeof(msg2) - 1) {
  97. ret = SSL_read_ex(c_ssl, msg2 + c_total_read,
  98. sizeof(msg2) - 1 - c_total_read, &l);
  99. if (ret != 1) {
  100. if (SSL_get_error(c_ssl, ret) == SSL_ERROR_ZERO_RETURN) {
  101. c_shutdown = 1;
  102. TEST_info("Message: \n%s\n", msg2);
  103. } else if (!TEST_true(is_want(c_ssl, ret))) {
  104. goto err;
  105. }
  106. } else {
  107. c_total_read += l;
  108. if (!TEST_size_t_lt(c_total_read, sizeof(msg2) - 1))
  109. goto err;
  110. }
  111. }
  112. if (c_shutdown) {
  113. ret = SSL_shutdown(c_ssl);
  114. if (ret == 1)
  115. break;
  116. }
  117. /*
  118. * This is inefficient because we spin until things work without
  119. * blocking but this is just a test.
  120. */
  121. OSSL_sleep(0);
  122. SSL_handle_events(c_ssl);
  123. }
  124. testresult = 1;
  125. err:
  126. SSL_free(c_ssl);
  127. SSL_CTX_free(c_ctx);
  128. BIO_ADDR_free(s_addr_);
  129. BIO_free(c_net_bio_own);
  130. if (c_fd != INVALID_SOCKET)
  131. BIO_closesocket(c_fd);
  132. return testresult;
  133. }
  134. OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
  135. int setup_tests(void)
  136. {
  137. if (!test_skip_common_options()) {
  138. TEST_error("Error parsing test options\n");
  139. return 0;
  140. }
  141. ADD_TEST(test_quic_client);
  142. return 1;
  143. }