test-http2.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #include "client.h"
  2. #include "server.h"
  3. #include "smartdns/dns.h"
  4. #include "smartdns/http2.h"
  5. #include "gtest/gtest.h"
  6. #include <arpa/inet.h>
  7. #include <netinet/in.h>
  8. #include <sys/socket.h>
  9. #include <thread>
  10. // Test HTTP/2 with bind-https server (simulating upstream HTTPS server)
  11. TEST(HTTP2, BindServerHTTP2)
  12. {
  13. Defer
  14. {
  15. unlink("/tmp/smartdns-cert.pem");
  16. unlink("/tmp/smartdns-key.pem");
  17. };
  18. smartdns::Server server_wrap;
  19. smartdns::Server server;
  20. // Start main SmartDNS instance that queries upstream HTTPS server
  21. server.Start(R"""(bind [::]:61053
  22. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn h2
  23. log-level debug
  24. )""");
  25. // Start upstream HTTPS server (bind-https)
  26. server_wrap.Start(R"""(bind-https [::]:60053 -alpn h2
  27. address /example.com/1.2.3.4
  28. address /test.com/5.6.7.8
  29. log-level debug
  30. )""");
  31. smartdns::Client client;
  32. // Test first query
  33. ASSERT_TRUE(client.Query("example.com", 61053));
  34. std::cout << client.GetResult() << std::endl;
  35. ASSERT_EQ(client.GetAnswerNum(), 1);
  36. EXPECT_EQ(client.GetStatus(), "NOERROR");
  37. EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
  38. // Test second query to verify connection reuse
  39. ASSERT_TRUE(client.Query("test.com", 61053));
  40. std::cout << client.GetResult() << std::endl;
  41. ASSERT_EQ(client.GetAnswerNum(), 1);
  42. EXPECT_EQ(client.GetStatus(), "NOERROR");
  43. EXPECT_EQ(client.GetAnswer()[0].GetData(), "5.6.7.8");
  44. }
  45. TEST(HTTP2, ServerMultiStream)
  46. {
  47. smartdns::Server server_wrap;
  48. smartdns::Server server;
  49. // Start main SmartDNS instance
  50. server.Start(R"""(bind [::]:61053
  51. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn h2
  52. log-level debug
  53. )""");
  54. // Start upstream HTTPS server (bind-https)
  55. server_wrap.Start(R"""(bind-https [::]:60053 -alpn h2
  56. address /example.com/1.2.3.4
  57. address /test.com/5.6.7.8
  58. log-level debug
  59. )""");
  60. smartdns::Client client;
  61. // Send multiple concurrent queries
  62. // Note: The smartdns::Client might be synchronous, so we might need threads or a way to send async.
  63. // But we can verify that multiple queries on the same connection work (multiplexing).
  64. // The previous test already verified connection reuse.
  65. // To verify concurrency, we'd need to delay the response on the server, which is hard with bind-https.
  66. // However, we can at least verify that sending many queries quickly works.
  67. for (int i = 0; i < 10; i++) {
  68. ASSERT_TRUE(client.Query("example.com", 61053));
  69. EXPECT_EQ(client.GetStatus(), "NOERROR");
  70. EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
  71. }
  72. }
  73. TEST(HTTP2, ServerALPNConfig)
  74. {
  75. smartdns::Server server_wrap;
  76. smartdns::Server server;
  77. // Case 1: Server supports h2, client requests h2 -> h2
  78. server.Start(R"""(bind [::]:61053
  79. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn h2
  80. log-level debug
  81. )""");
  82. server_wrap.Start(R"""(bind-https [::]:60053 -alpn h2
  83. address /example.com/1.2.3.4
  84. log-level debug
  85. )""");
  86. smartdns::Client client;
  87. ASSERT_TRUE(client.Query("example.com", 61053));
  88. EXPECT_EQ(client.GetStatus(), "NOERROR");
  89. }
  90. TEST(HTTP2, ServerALPNFallback)
  91. {
  92. smartdns::Server server_wrap;
  93. smartdns::Server server;
  94. // Case 2: Server supports http/1.1 only, client requests h2 -> fallback or fail?
  95. // If client requests h2 only, it should fail.
  96. // If client requests h2,http/1.1, it should fallback.
  97. server.Start(R"""(bind [::]:61053
  98. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn h2,http/1.1
  99. log-level debug
  100. )""");
  101. server_wrap.Start(R"""(bind-https [::]:60053 -alpn http/1.1
  102. address /example.com/1.2.3.4
  103. log-level debug
  104. )""");
  105. smartdns::Client client;
  106. ASSERT_TRUE(client.Query("example.com", 61053));
  107. EXPECT_EQ(client.GetStatus(), "NOERROR");
  108. }
  109. // Test client only supports HTTP/1.1, server supports both
  110. TEST(HTTP2, ClientHTTP1Only)
  111. {
  112. smartdns::Server server_wrap;
  113. smartdns::Server server;
  114. // Client only supports http/1.1, server supports both h2 and http/1.1
  115. server.Start(R"""(bind [::]:61053
  116. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn http/1.1
  117. log-level debug
  118. )""");
  119. server_wrap.Start(R"""(bind-https [::]:60053 -alpn h2,http/1.1
  120. address /example.com/1.2.3.4
  121. log-level debug
  122. )""");
  123. smartdns::Client client;
  124. ASSERT_TRUE(client.Query("example.com", 61053));
  125. EXPECT_EQ(client.GetStatus(), "NOERROR");
  126. EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
  127. }
  128. // Test both client and server only support HTTP/1.1
  129. TEST(HTTP2, BothHTTP1Only)
  130. {
  131. smartdns::Server server_wrap;
  132. smartdns::Server server;
  133. // Both client and server only support http/1.1
  134. server.Start(R"""(bind [::]:61053
  135. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn http/1.1
  136. log-level debug
  137. )""");
  138. server_wrap.Start(R"""(bind-https [::]:60053 -alpn http/1.1
  139. address /example.com/1.2.3.4
  140. address /test2.com/9.10.11.12
  141. log-level debug
  142. )""");
  143. smartdns::Client client;
  144. // First query
  145. ASSERT_TRUE(client.Query("example.com", 61053));
  146. EXPECT_EQ(client.GetStatus(), "NOERROR");
  147. EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
  148. // Second query to verify connection reuse with HTTP/1.1
  149. ASSERT_TRUE(client.Query("test2.com", 61053));
  150. EXPECT_EQ(client.GetStatus(), "NOERROR");
  151. EXPECT_EQ(client.GetAnswer()[0].GetData(), "9.10.11.12");
  152. }
  153. // Test concurrent queries from multiple clients
  154. TEST(HTTP2, ConcurrentClients)
  155. {
  156. smartdns::Server server_wrap;
  157. smartdns::Server server;
  158. server.Start(R"""(bind [::]:61053
  159. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn h2
  160. log-level debug
  161. )""");
  162. server_wrap.Start(R"""(bind-https [::]:60053 -alpn h2
  163. address /example.com/1.2.3.4
  164. address /test.com/5.6.7.8
  165. log-level debug
  166. )""");
  167. // Create multiple threads to query simultaneously
  168. std::vector<std::thread> threads;
  169. std::atomic<int> success_count{0};
  170. for (int i = 0; i < 5; i++) {
  171. threads.emplace_back([&success_count, i]() {
  172. smartdns::Client client;
  173. const char* domain = (i % 2 == 0) ? "example.com" : "test.com";
  174. const char* expected_ip = (i % 2 == 0) ? "1.2.3.4" : "5.6.7.8";
  175. if (client.Query(domain, 61053)) {
  176. if (client.GetStatus() == "NOERROR" &&
  177. client.GetAnswerNum() > 0 &&
  178. client.GetAnswer()[0].GetData() == expected_ip) {
  179. success_count++;
  180. }
  181. }
  182. });
  183. }
  184. for (auto& t : threads) {
  185. t.join();
  186. }
  187. EXPECT_EQ(success_count.load(), 5);
  188. }
  189. // Test mixed HTTP/2 and HTTP/1.1 queries
  190. TEST(HTTP2, MixedProtocolQueries)
  191. {
  192. smartdns::Server server_wrap_h2;
  193. smartdns::Server server_wrap_http1;
  194. smartdns::Server server;
  195. // Main server supports both protocols
  196. server.Start(R"""(bind [::]:61053
  197. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn h2,http/1.1
  198. server https://127.0.0.1:60054/dns-query -no-check-certificate -alpn http/1.1
  199. log-level debug
  200. )""");
  201. // First upstream supports HTTP/2
  202. server_wrap_h2.Start(R"""(bind-https [::]:60053 -alpn h2
  203. address /h2-domain.com/1.1.1.1
  204. log-level debug
  205. )""");
  206. // Second upstream supports HTTP/1.1 only
  207. server_wrap_http1.Start(R"""(bind-https [::]:60054 -alpn http/1.1
  208. address /http1-domain.com/2.2.2.2
  209. log-level debug
  210. )""");
  211. smartdns::Client client;
  212. // Query from HTTP/2 server
  213. ASSERT_TRUE(client.Query("h2-domain.com", 61053));
  214. EXPECT_EQ(client.GetStatus(), "NOERROR");
  215. EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.1.1.1");
  216. // Query from HTTP/1.1 server
  217. ASSERT_TRUE(client.Query("http1-domain.com", 61053));
  218. EXPECT_EQ(client.GetStatus(), "NOERROR");
  219. EXPECT_EQ(client.GetAnswer()[0].GetData(), "2.2.2.2");
  220. }
  221. // Test connection reuse for HTTP/2
  222. TEST(HTTP2, ConnectionReuse)
  223. {
  224. smartdns::Server server_wrap;
  225. smartdns::Server server;
  226. server.Start(R"""(bind [::]:61053
  227. server https://127.0.0.1:60053/dns-query -no-check-certificate -alpn h2
  228. log-level debug
  229. )""");
  230. server_wrap.Start(R"""(bind-https [::]:60053 -alpn h2
  231. address /domain1.com/1.1.1.1
  232. address /domain2.com/2.2.2.2
  233. address /domain3.com/3.3.3.3
  234. log-level debug
  235. )""");
  236. smartdns::Client client;
  237. // Multiple queries that should reuse the same HTTP/2 connection
  238. for (int i = 1; i <= 3; i++) {
  239. std::string domain = "domain" + std::to_string(i) + ".com";
  240. std::string expected_ip = std::to_string(i) + "." + std::to_string(i) + "." + std::to_string(i) + "." + std::to_string(i);
  241. ASSERT_TRUE(client.Query(domain.c_str(), 61053));
  242. EXPECT_EQ(client.GetStatus(), "NOERROR");
  243. EXPECT_EQ(client.GetAnswer()[0].GetData(), expected_ip);
  244. }
  245. }
  246. // Test default ALPN behavior (no explicit -alpn parameter)
  247. TEST(HTTP2, DefaultALPN)
  248. {
  249. smartdns::Server server_wrap;
  250. smartdns::Server server;
  251. // Client doesn't specify ALPN (should default to supporting both)
  252. server.Start(R"""(bind [::]:61053
  253. server https://127.0.0.1:60053/dns-query -no-check-certificate
  254. log-level debug
  255. )""");
  256. // Server supports both (no explicit -alpn, should default to h2,http/1.1)
  257. server_wrap.Start(R"""(bind-https [::]:60053
  258. address /example.com/1.2.3.4
  259. log-level debug
  260. )""");
  261. smartdns::Client client;
  262. ASSERT_TRUE(client.Query("example.com", 61053));
  263. EXPECT_EQ(client.GetStatus(), "NOERROR");
  264. EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
  265. }