1 | /*************************************************************************** |
2 | * _ _ ____ _ |
3 | * Project ___| | | | _ \| | |
4 | * / __| | | | |_) | | |
5 | * | (__| |_| | _ <| |___ |
6 | * \___|\___/|_| \_\_____| |
7 | * |
8 | * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. |
9 | * |
10 | * This software is licensed as described in the file COPYING, which |
11 | * you should have received as part of this distribution. The terms |
12 | * are also available at https://curl.se/docs/copyright.html. |
13 | * |
14 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
15 | * copies of the Software, and permit persons to whom the Software is |
16 | * furnished to do so, under the terms of the COPYING file. |
17 | * |
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
19 | * KIND, either express or implied. |
20 | * |
21 | ***************************************************************************/ |
22 | |
23 | /* |
24 | * Check for bugs #1303 and #1327: libcurl should never remove DNS entries |
25 | * created via CURLOPT_RESOLVE, neither after DNS_CACHE_TIMEOUT elapses |
26 | * (test1515) nor a dead connection is detected (test1616). |
27 | */ |
28 | |
29 | #include "test.h" |
30 | #include "testutil.h" |
31 | #include "warnless.h" |
32 | #include "memdebug.h" |
33 | |
34 | #define TEST_HANG_TIMEOUT 60 * 1000 |
35 | |
36 | #define DNS_TIMEOUT 1 |
37 | |
38 | #if defined(WIN32) || defined(_WIN32) |
39 | #define sleep(sec) Sleep ((sec)*1000) |
40 | #endif |
41 | |
42 | static int debug_callback(CURL *curl, curl_infotype info, char *msg, |
43 | size_t len, void *ptr) |
44 | { |
45 | (void)curl; |
46 | (void)ptr; |
47 | |
48 | if(info == CURLINFO_TEXT) |
49 | fprintf(stderr, "debug: %.*s" , (int) len, msg); |
50 | |
51 | return 0; |
52 | } |
53 | |
54 | static int do_one_request(CURLM *m, char *URL, char *resolve) |
55 | { |
56 | CURL *curls; |
57 | struct curl_slist *resolve_list = NULL; |
58 | int still_running; |
59 | int res = 0; |
60 | CURLMsg *msg; |
61 | int msgs_left; |
62 | |
63 | resolve_list = curl_slist_append(resolve_list, resolve); |
64 | |
65 | easy_init(curls); |
66 | |
67 | easy_setopt(curls, CURLOPT_URL, URL); |
68 | easy_setopt(curls, CURLOPT_RESOLVE, resolve_list); |
69 | easy_setopt(curls, CURLOPT_DEBUGFUNCTION, debug_callback); |
70 | easy_setopt(curls, CURLOPT_VERBOSE, 1); |
71 | easy_setopt(curls, CURLOPT_DNS_CACHE_TIMEOUT, DNS_TIMEOUT); |
72 | |
73 | multi_add_handle(m, curls); |
74 | multi_perform(m, &still_running); |
75 | |
76 | abort_on_test_timeout(); |
77 | |
78 | while(still_running) { |
79 | struct timeval timeout; |
80 | fd_set fdread, fdwrite, fdexcep; |
81 | int maxfd = -99; |
82 | |
83 | FD_ZERO(&fdread); |
84 | FD_ZERO(&fdwrite); |
85 | FD_ZERO(&fdexcep); |
86 | timeout.tv_sec = 1; |
87 | timeout.tv_usec = 0; |
88 | |
89 | multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd); |
90 | select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); |
91 | |
92 | abort_on_test_timeout(); |
93 | multi_perform(m, &still_running); |
94 | |
95 | abort_on_test_timeout(); |
96 | } |
97 | |
98 | do { |
99 | msg = curl_multi_info_read(m, &msgs_left); |
100 | if(msg && msg->msg == CURLMSG_DONE && msg->easy_handle == curls) { |
101 | res = msg->data.result; |
102 | break; |
103 | } |
104 | } while(msg); |
105 | |
106 | test_cleanup: |
107 | |
108 | curl_multi_remove_handle(m, curls); |
109 | curl_easy_cleanup(curls); |
110 | curl_slist_free_all(resolve_list); |
111 | |
112 | return res; |
113 | } |
114 | |
115 | int test(char *URL) |
116 | { |
117 | CURLM *multi = NULL; |
118 | int res = 0; |
119 | char *address = libtest_arg2; |
120 | char *port = libtest_arg3; |
121 | char *path = URL; |
122 | char dns_entry[256]; |
123 | int i; |
124 | int count = 2; |
125 | |
126 | msnprintf(dns_entry, sizeof(dns_entry), "testserver.example.com:%s:%s" , |
127 | port, address); |
128 | |
129 | start_test_timing(); |
130 | |
131 | global_init(CURL_GLOBAL_ALL); |
132 | multi_init(multi); |
133 | |
134 | for(i = 1; i <= count; i++) { |
135 | char target_url[256]; |
136 | msnprintf(target_url, sizeof(target_url), |
137 | "http://testserver.example.com:%s/%s%04d" , port, path, i); |
138 | |
139 | /* second request must succeed like the first one */ |
140 | res = do_one_request(multi, target_url, dns_entry); |
141 | if(res) |
142 | goto test_cleanup; |
143 | |
144 | if(i < count) |
145 | sleep(DNS_TIMEOUT + 1); |
146 | } |
147 | |
148 | test_cleanup: |
149 | |
150 | curl_multi_cleanup(multi); |
151 | curl_global_cleanup(); |
152 | |
153 | return (int) res; |
154 | } |
155 | |