Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/tests/http/clients/h2-upgrade-extreme.c
2066 views
1
/***************************************************************************
2
* _ _ ____ _
3
* Project ___| | | | _ \| |
4
* / __| | | | |_) | |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
7
*
8
* Copyright (C) Daniel Stenberg, <[email protected]>, 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
* SPDX-License-Identifier: curl
22
*
23
***************************************************************************/
24
/* <DESC>
25
* HTTP/2 Upgrade test
26
* </DESC>
27
*/
28
#include <curl/curl.h>
29
30
#include <stdio.h>
31
#include <stdlib.h>
32
33
static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)
34
{
35
/*
36
* This is the trace look that is similar to what libcurl makes on its
37
* own.
38
*/
39
static const char * const s_infotype[] = {
40
"* ", "< ", "> ", "{ ", "} ", "{ ", "} "
41
};
42
if(idsbuf && *idsbuf)
43
fprintf(log, "%s%s", idsbuf, s_infotype[type]);
44
else
45
fputs(s_infotype[type], log);
46
}
47
48
#define TRC_IDS_FORMAT_IDS_1 "[%" CURL_FORMAT_CURL_OFF_T "-x] "
49
#define TRC_IDS_FORMAT_IDS_2 "[%" CURL_FORMAT_CURL_OFF_T "-%" \
50
CURL_FORMAT_CURL_OFF_T "] "
51
/*
52
** callback for CURLOPT_DEBUGFUNCTION
53
*/
54
static int debug_cb(CURL *handle, curl_infotype type,
55
char *data, size_t size,
56
void *userdata)
57
{
58
FILE *output = stderr;
59
static int newl = 0;
60
static int traced_data = 0;
61
char idsbuf[60];
62
curl_off_t xfer_id, conn_id;
63
64
(void)handle; /* not used */
65
(void)userdata;
66
67
if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
68
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
69
conn_id >= 0) {
70
curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id,
71
conn_id);
72
}
73
else {
74
curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
75
}
76
}
77
else
78
idsbuf[0] = 0;
79
80
switch(type) {
81
case CURLINFO_HEADER_OUT:
82
if(size > 0) {
83
size_t st = 0;
84
size_t i;
85
for(i = 0; i < size - 1; i++) {
86
if(data[i] == '\n') { /* LF */
87
if(!newl) {
88
log_line_start(output, idsbuf, type);
89
}
90
(void)fwrite(data + st, i - st + 1, 1, output);
91
st = i + 1;
92
newl = 0;
93
}
94
}
95
if(!newl)
96
log_line_start(output, idsbuf, type);
97
(void)fwrite(data + st, i - st + 1, 1, output);
98
}
99
newl = (size && (data[size - 1] != '\n')) ? 1 : 0;
100
traced_data = 0;
101
break;
102
case CURLINFO_TEXT:
103
case CURLINFO_HEADER_IN:
104
if(!newl)
105
log_line_start(output, idsbuf, type);
106
(void)fwrite(data, size, 1, output);
107
newl = (size && (data[size - 1] != '\n')) ? 1 : 0;
108
traced_data = 0;
109
break;
110
case CURLINFO_DATA_OUT:
111
case CURLINFO_DATA_IN:
112
case CURLINFO_SSL_DATA_IN:
113
case CURLINFO_SSL_DATA_OUT:
114
if(!traced_data) {
115
if(!newl)
116
log_line_start(output, idsbuf, type);
117
fprintf(output, "[%ld bytes data]\n", (long)size);
118
newl = 0;
119
traced_data = 1;
120
}
121
break;
122
default: /* nada */
123
newl = 0;
124
traced_data = 1;
125
break;
126
}
127
128
return 0;
129
}
130
131
static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *opaque)
132
{
133
(void)ptr;
134
(void)opaque;
135
return size * nmemb;
136
}
137
138
int main(int argc, char *argv[])
139
{
140
const char *url;
141
CURLM *multi = NULL;
142
CURL *easy;
143
CURLMcode mc;
144
int running_handles = 0, start_count, numfds;
145
CURLMsg *msg;
146
int msgs_in_queue;
147
char range[128];
148
int exitcode = 1;
149
150
if(argc != 2) {
151
fprintf(stderr, "%s URL\n", argv[0]);
152
return 2;
153
}
154
155
url = argv[1];
156
multi = curl_multi_init();
157
if(!multi) {
158
fprintf(stderr, "curl_multi_init failed\n");
159
goto cleanup;
160
}
161
162
start_count = 200;
163
do {
164
if(start_count) {
165
easy = curl_easy_init();
166
if(!easy) {
167
fprintf(stderr, "curl_easy_init failed\n");
168
goto cleanup;
169
}
170
curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
171
curl_easy_setopt(easy, CURLOPT_DEBUGFUNCTION, debug_cb);
172
curl_easy_setopt(easy, CURLOPT_URL, url);
173
curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1L);
174
curl_easy_setopt(easy, CURLOPT_AUTOREFERER, 1L);
175
curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
176
curl_easy_setopt(easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
177
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_cb);
178
curl_easy_setopt(easy, CURLOPT_WRITEDATA, NULL);
179
curl_easy_setopt(easy, CURLOPT_HTTPGET, 1L);
180
curl_msnprintf(range, sizeof(range),
181
"%" CURL_FORMAT_CURL_OFF_TU "-"
182
"%" CURL_FORMAT_CURL_OFF_TU,
183
(curl_off_t)0,
184
(curl_off_t)16384);
185
curl_easy_setopt(easy, CURLOPT_RANGE, range);
186
187
mc = curl_multi_add_handle(multi, easy);
188
if(mc != CURLM_OK) {
189
fprintf(stderr, "curl_multi_add_handle: %s\n",
190
curl_multi_strerror(mc));
191
curl_easy_cleanup(easy);
192
goto cleanup;
193
}
194
--start_count;
195
}
196
197
mc = curl_multi_perform(multi, &running_handles);
198
if(mc != CURLM_OK) {
199
fprintf(stderr, "curl_multi_perform: %s\n",
200
curl_multi_strerror(mc));
201
goto cleanup;
202
}
203
204
if(running_handles) {
205
mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);
206
if(mc != CURLM_OK) {
207
fprintf(stderr, "curl_multi_poll: %s\n",
208
curl_multi_strerror(mc));
209
goto cleanup;
210
}
211
}
212
213
/* Check for finished handles and remove. */
214
/* !checksrc! disable EQUALSNULL 1 */
215
while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {
216
if(msg->msg == CURLMSG_DONE) {
217
long status = 0;
218
curl_off_t xfer_id;
219
curl_easy_getinfo(msg->easy_handle, CURLINFO_XFER_ID, &xfer_id);
220
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &status);
221
if(msg->data.result == CURLE_SEND_ERROR ||
222
msg->data.result == CURLE_RECV_ERROR) {
223
/* We get these if the server had a GOAWAY in transit on
224
* re-using a connection */
225
}
226
else if(msg->data.result) {
227
fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
228
": failed with %d\n", xfer_id, msg->data.result);
229
goto cleanup;
230
}
231
else if(status != 206) {
232
fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
233
": wrong http status %ld (expected 206)\n", xfer_id, status);
234
goto cleanup;
235
}
236
curl_multi_remove_handle(multi, msg->easy_handle);
237
curl_easy_cleanup(msg->easy_handle);
238
fprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T" retiring "
239
"(%d now running)\n", xfer_id, running_handles);
240
}
241
}
242
243
fprintf(stderr, "running_handles=%d, yet_to_start=%d\n",
244
running_handles, start_count);
245
246
} while(running_handles > 0 || start_count);
247
248
fprintf(stderr, "exiting\n");
249
exitcode = EXIT_SUCCESS;
250
251
cleanup:
252
253
if(multi) {
254
CURL **list = curl_multi_get_handles(multi);
255
if(list) {
256
int i;
257
for(i = 0; list[i]; i++) {
258
curl_multi_remove_handle(multi, list[i]);
259
curl_easy_cleanup(list[i]);
260
}
261
curl_free(list);
262
}
263
curl_multi_cleanup(multi);
264
}
265
266
return exitcode;
267
}
268
269