Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/tests/libtest/lib1533.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
25
/*
26
* This test sends data with CURLOPT_KEEP_SENDING_ON_ERROR.
27
* The server responds with an early error response.
28
* The test is successful if the connection can be reused for the next request,
29
* because this implies that the data has been sent completely to the server.
30
*/
31
32
#include "test.h"
33
34
#include "memdebug.h"
35
36
struct cb_data {
37
CURL *easy_handle;
38
int response_received;
39
int paused;
40
size_t remaining_bytes;
41
};
42
43
44
static void reset_data(struct cb_data *data, CURL *curl)
45
{
46
data->easy_handle = curl;
47
data->response_received = 0;
48
data->paused = 0;
49
data->remaining_bytes = 3;
50
}
51
52
53
static size_t read_callback(char *ptr, size_t size, size_t nitems,
54
void *userdata)
55
{
56
struct cb_data *data = (struct cb_data *)userdata;
57
58
/* wait until the server has sent all response headers */
59
if(data->response_received) {
60
size_t totalsize = nitems * size;
61
62
size_t bytes_to_send = data->remaining_bytes;
63
if(bytes_to_send > totalsize) {
64
bytes_to_send = totalsize;
65
}
66
67
memset(ptr, 'a', bytes_to_send);
68
data->remaining_bytes -= bytes_to_send;
69
70
return bytes_to_send;
71
}
72
else {
73
data->paused = 1;
74
return CURL_READFUNC_PAUSE;
75
}
76
}
77
78
79
static size_t write_callback(char *ptr, size_t size, size_t nmemb,
80
void *userdata)
81
{
82
struct cb_data *data = (struct cb_data *)userdata;
83
size_t totalsize = nmemb * size;
84
85
/* unused parameter */
86
(void)ptr;
87
88
/* all response headers have been received */
89
data->response_received = 1;
90
91
if(data->paused) {
92
/* continue to send request body data */
93
data->paused = 0;
94
curl_easy_pause(data->easy_handle, CURLPAUSE_CONT);
95
}
96
97
return totalsize;
98
}
99
100
101
static CURLcode perform_and_check_connections(CURL *curl,
102
const char *description,
103
long expected_connections)
104
{
105
CURLcode res;
106
long connections = 0;
107
108
res = curl_easy_perform(curl);
109
if(res != CURLE_OK) {
110
curl_mfprintf(stderr, "curl_easy_perform() failed with %d\n", res);
111
return TEST_ERR_MAJOR_BAD;
112
}
113
114
res = curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &connections);
115
if(res != CURLE_OK) {
116
curl_mfprintf(stderr, "curl_easy_getinfo() failed\n");
117
return TEST_ERR_MAJOR_BAD;
118
}
119
120
curl_mfprintf(stderr,
121
"%s: expected: %ld connections; actual: %ld connections\n",
122
description, expected_connections, connections);
123
124
if(connections != expected_connections) {
125
return TEST_ERR_FAILURE;
126
}
127
128
return TEST_ERR_SUCCESS;
129
}
130
131
132
CURLcode test(char *URL)
133
{
134
struct cb_data data;
135
CURL *curl = NULL;
136
CURLcode res = TEST_ERR_FAILURE;
137
CURLcode result;
138
139
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
140
curl_mfprintf(stderr, "curl_global_init() failed\n");
141
return TEST_ERR_MAJOR_BAD;
142
}
143
144
curl = curl_easy_init();
145
if(!curl) {
146
curl_mfprintf(stderr, "curl_easy_init() failed\n");
147
curl_global_cleanup();
148
return TEST_ERR_MAJOR_BAD;
149
}
150
151
reset_data(&data, curl);
152
153
test_setopt(curl, CURLOPT_URL, URL);
154
test_setopt(curl, CURLOPT_POST, 1L);
155
test_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
156
(curl_off_t)data.remaining_bytes);
157
test_setopt(curl, CURLOPT_VERBOSE, 1L);
158
test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
159
test_setopt(curl, CURLOPT_READDATA, &data);
160
test_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
161
test_setopt(curl, CURLOPT_WRITEDATA, &data);
162
163
result = perform_and_check_connections(curl,
164
"First request without CURLOPT_KEEP_SENDING_ON_ERROR", 1);
165
if(result != TEST_ERR_SUCCESS) {
166
res = result;
167
goto test_cleanup;
168
}
169
170
reset_data(&data, curl);
171
172
result = perform_and_check_connections(curl,
173
"Second request without CURLOPT_KEEP_SENDING_ON_ERROR", 1);
174
if(result != TEST_ERR_SUCCESS) {
175
res = result;
176
goto test_cleanup;
177
}
178
179
test_setopt(curl, CURLOPT_KEEP_SENDING_ON_ERROR, 1L);
180
181
reset_data(&data, curl);
182
183
result = perform_and_check_connections(curl,
184
"First request with CURLOPT_KEEP_SENDING_ON_ERROR", 1);
185
if(result != TEST_ERR_SUCCESS) {
186
res = result;
187
goto test_cleanup;
188
}
189
190
reset_data(&data, curl);
191
192
result = perform_and_check_connections(curl,
193
"Second request with CURLOPT_KEEP_SENDING_ON_ERROR", 0);
194
if(result != TEST_ERR_SUCCESS) {
195
res = result;
196
goto test_cleanup;
197
}
198
199
res = TEST_ERR_SUCCESS;
200
201
test_cleanup:
202
203
curl_easy_cleanup(curl);
204
205
curl_global_cleanup();
206
207
return res;
208
}
209
210