Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/tests/http/clients/upload-pausing.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
* upload pausing
26
* </DESC>
27
*/
28
/* This is based on the PoC client of issue #11769
29
*/
30
#include <curl/curl.h>
31
32
#include <stdio.h>
33
#include <string.h>
34
#include <stdlib.h>
35
36
#ifndef _MSC_VER
37
/* somewhat Unix-specific */
38
#include <unistd.h> /* getopt() */
39
#endif
40
41
#ifndef _MSC_VER
42
static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)
43
{
44
/*
45
* This is the trace look that is similar to what libcurl makes on its
46
* own.
47
*/
48
static const char * const s_infotype[] = {
49
"* ", "< ", "> ", "{ ", "} ", "{ ", "} "
50
};
51
if(idsbuf && *idsbuf)
52
fprintf(log, "%s%s", idsbuf, s_infotype[type]);
53
else
54
fputs(s_infotype[type], log);
55
}
56
57
#define TRC_IDS_FORMAT_IDS_1 "[%" CURL_FORMAT_CURL_OFF_T "-x] "
58
#define TRC_IDS_FORMAT_IDS_2 "[%" CURL_FORMAT_CURL_OFF_T "-%" \
59
CURL_FORMAT_CURL_OFF_T "] "
60
/*
61
** callback for CURLOPT_DEBUGFUNCTION
62
*/
63
static int debug_cb(CURL *handle, curl_infotype type,
64
char *data, size_t size,
65
void *userdata)
66
{
67
FILE *output = stderr;
68
static int newl = 0;
69
static int traced_data = 0;
70
char idsbuf[60];
71
curl_off_t xfer_id, conn_id;
72
73
(void)handle; /* not used */
74
(void)userdata;
75
76
if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
77
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
78
conn_id >= 0) {
79
curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id,
80
conn_id);
81
}
82
else {
83
curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
84
}
85
}
86
else
87
idsbuf[0] = 0;
88
89
switch(type) {
90
case CURLINFO_HEADER_OUT:
91
if(size > 0) {
92
size_t st = 0;
93
size_t i;
94
for(i = 0; i < size - 1; i++) {
95
if(data[i] == '\n') { /* LF */
96
if(!newl) {
97
log_line_start(output, idsbuf, type);
98
}
99
(void)fwrite(data + st, i - st + 1, 1, output);
100
st = i + 1;
101
newl = 0;
102
}
103
}
104
if(!newl)
105
log_line_start(output, idsbuf, type);
106
(void)fwrite(data + st, i - st + 1, 1, output);
107
}
108
newl = (size && (data[size - 1] != '\n')) ? 1 : 0;
109
traced_data = 0;
110
break;
111
case CURLINFO_TEXT:
112
case CURLINFO_HEADER_IN:
113
if(!newl)
114
log_line_start(output, idsbuf, type);
115
(void)fwrite(data, size, 1, output);
116
newl = (size && (data[size - 1] != '\n')) ? 1 : 0;
117
traced_data = 0;
118
break;
119
case CURLINFO_DATA_OUT:
120
case CURLINFO_DATA_IN:
121
case CURLINFO_SSL_DATA_IN:
122
case CURLINFO_SSL_DATA_OUT:
123
if(!traced_data) {
124
if(!newl)
125
log_line_start(output, idsbuf, type);
126
fprintf(output, "[%ld bytes data]\n", (long)size);
127
newl = 0;
128
traced_data = 1;
129
}
130
break;
131
default: /* nada */
132
newl = 0;
133
traced_data = 1;
134
break;
135
}
136
137
return 0;
138
}
139
140
#define PAUSE_READ_AFTER 1
141
static size_t total_read = 0;
142
143
static size_t read_callback(char *ptr, size_t size, size_t nmemb,
144
void *userdata)
145
{
146
(void)size;
147
(void)nmemb;
148
(void)userdata;
149
if(total_read >= PAUSE_READ_AFTER) {
150
fprintf(stderr, "read_callback, return PAUSE\n");
151
return CURL_READFUNC_PAUSE;
152
}
153
else {
154
ptr[0] = '\n';
155
++total_read;
156
fprintf(stderr, "read_callback, return 1 byte\n");
157
return 1;
158
}
159
}
160
161
static int progress_callback(void *clientp,
162
curl_off_t dltotal,
163
curl_off_t dlnow,
164
curl_off_t ultotal,
165
curl_off_t ulnow)
166
{
167
(void)dltotal;
168
(void)dlnow;
169
(void)ultotal;
170
(void)ulnow;
171
(void)clientp;
172
#if 0
173
/* Used to unpause on progress, but keeping for now. */
174
{
175
CURL *curl = (CURL *)clientp;
176
curl_easy_pause(curl, CURLPAUSE_CONT);
177
/* curl_easy_pause(curl, CURLPAUSE_RECV_CONT); */
178
}
179
#endif
180
return 0;
181
}
182
183
static void usage(const char *msg)
184
{
185
if(msg)
186
fprintf(stderr, "%s\n", msg);
187
fprintf(stderr,
188
"usage: [options] url\n"
189
" upload and pause, options:\n"
190
" -V http_version (http/1.1, h2, h3) http version to use\n"
191
);
192
}
193
194
#define ERR() \
195
do { \
196
fprintf(stderr, "something unexpected went wrong - bailing out!\n"); \
197
return 2; \
198
} while(0)
199
200
#endif /* !_MSC_VER */
201
202
int main(int argc, char *argv[])
203
{
204
#ifndef _MSC_VER
205
CURL *curl;
206
CURLcode rc = CURLE_OK;
207
CURLU *cu;
208
struct curl_slist *resolve = NULL;
209
char resolve_buf[1024];
210
char *url, *host = NULL, *port = NULL;
211
long http_version = CURL_HTTP_VERSION_1_1;
212
int ch;
213
214
while((ch = getopt(argc, argv, "V:")) != -1) {
215
switch(ch) {
216
case 'V': {
217
if(!strcmp("http/1.1", optarg))
218
http_version = CURL_HTTP_VERSION_1_1;
219
else if(!strcmp("h2", optarg))
220
http_version = CURL_HTTP_VERSION_2_0;
221
else if(!strcmp("h3", optarg))
222
http_version = CURL_HTTP_VERSION_3ONLY;
223
else {
224
usage("invalid http version");
225
return 1;
226
}
227
break;
228
}
229
default:
230
usage("invalid option");
231
return 1;
232
}
233
}
234
argc -= optind;
235
argv += optind;
236
237
if(argc != 1) {
238
usage("not enough arguments");
239
return 2;
240
}
241
url = argv[0];
242
243
curl_global_init(CURL_GLOBAL_DEFAULT);
244
curl_global_trace("ids,time");
245
246
cu = curl_url();
247
if(!cu) {
248
fprintf(stderr, "out of memory\n");
249
return 1;
250
}
251
if(curl_url_set(cu, CURLUPART_URL, url, 0)) {
252
fprintf(stderr, "not a URL: '%s'\n", url);
253
return 1;
254
}
255
if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {
256
fprintf(stderr, "could not get host of '%s'\n", url);
257
return 1;
258
}
259
if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {
260
fprintf(stderr, "could not get port of '%s'\n", url);
261
return 1;
262
}
263
memset(&resolve, 0, sizeof(resolve));
264
curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",
265
host, port);
266
resolve = curl_slist_append(resolve, resolve_buf);
267
268
curl = curl_easy_init();
269
if(!curl) {
270
fprintf(stderr, "out of memory\n");
271
return 1;
272
}
273
/* We want to use our own read function. */
274
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
275
276
/* It will help us to continue the read function. */
277
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
278
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, curl);
279
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
280
281
/* It will help us to ensure that keepalive does not help. */
282
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
283
curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 1L);
284
curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 1L);
285
curl_easy_setopt(curl, CURLOPT_TCP_KEEPCNT, 1L);
286
287
/* Enable uploading. */
288
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
289
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
290
291
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
292
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
293
294
if(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L) != CURLE_OK ||
295
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_cb)
296
!= CURLE_OK ||
297
curl_easy_setopt(curl, CURLOPT_RESOLVE, resolve) != CURLE_OK)
298
ERR();
299
300
curl_easy_setopt(curl, CURLOPT_URL, url);
301
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, http_version);
302
303
rc = curl_easy_perform(curl);
304
305
if(curl) {
306
curl_easy_cleanup(curl);
307
}
308
309
curl_slist_free_all(resolve);
310
curl_free(host);
311
curl_free(port);
312
curl_url_cleanup(cu);
313
curl_global_cleanup();
314
315
return (int)rc;
316
#else
317
(void)argc;
318
(void)argv;
319
fprintf(stderr, "Not supported with this compiler.\n");
320
return 1;
321
#endif /* !_MSC_VER */
322
}
323
324