mirror of
https://github.com/curl/curl.git
synced 2026-07-30 19:18:09 +03:00
Merge 0560afe5c1 into 7d5398f764
This commit is contained in:
commit
961881dae3
11 changed files with 321 additions and 7 deletions
|
|
@ -124,11 +124,6 @@ for each redirect.
|
|||
|
||||
[curl issue 6743](https://github.com/curl/curl/issues/6743)
|
||||
|
||||
## CURLINFO_PAUSE_STATE
|
||||
|
||||
Return information about the transfer's current pause state, in both
|
||||
directions. See [curl issue 2588](https://github.com/curl/curl/issues/2588)
|
||||
|
||||
## Expose tried IP addresses that failed
|
||||
|
||||
When libcurl fails to connect to a host, it could offer the application the
|
||||
|
|
|
|||
|
|
@ -189,6 +189,10 @@ See CURLINFO_NUM_CONNECTS(3)
|
|||
|
||||
The errno from the last failure to connect. See CURLINFO_OS_ERRNO(3)
|
||||
|
||||
## CURLINFO_PAUSE_STATE
|
||||
|
||||
The current pause state of the transfer. See CURLINFO_PAUSE_STATE(3)
|
||||
|
||||
## CURLINFO_POSTTRANSFER_TIME_T
|
||||
|
||||
The time it took from the start until the last byte is sent by libcurl.
|
||||
|
|
|
|||
79
docs/libcurl/opts/CURLINFO_PAUSE_STATE.md
Normal file
79
docs/libcurl/opts/CURLINFO_PAUSE_STATE.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
SPDX-License-Identifier: curl
|
||||
Title: CURLINFO_PAUSE_STATE
|
||||
Section: 3
|
||||
Source: libcurl
|
||||
See-also:
|
||||
- curl_easy_getinfo (3)
|
||||
- curl_easy_pause (3)
|
||||
Protocol:
|
||||
- All
|
||||
Added-in: 8.22.0
|
||||
---
|
||||
|
||||
# NAME
|
||||
|
||||
CURLINFO_PAUSE_STATE - get the current pause state
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
~~~c
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PAUSE_STATE,
|
||||
unsigned int *bitmask);
|
||||
~~~
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Pass a pointer to a long to receive a bitmask describing the current pause
|
||||
state of the transfer. The bitmask uses the same values as curl_easy_pause(3):
|
||||
|
||||
CURLPAUSE_RECV
|
||||
|
||||
: Receiving is paused.
|
||||
|
||||
CURLPAUSE_SEND
|
||||
|
||||
: Sending is paused.
|
||||
|
||||
If neither direction is paused, the returned value is zero.
|
||||
|
||||
This includes pauses set with curl_easy_pause(3) as well as pauses requested
|
||||
by read or write callbacks returning CURL_READFUNC_PAUSE or
|
||||
CURL_WRITEFUNC_PAUSE.
|
||||
|
||||
This may be used from within a callback during an active transfer. An easy
|
||||
handle must not be used from multiple threads simultaneously.
|
||||
|
||||
# %PROTOCOLS%
|
||||
|
||||
# EXAMPLE
|
||||
|
||||
~~~c
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
long paused;
|
||||
CURLcode result = curl_easy_getinfo(curl, CURLINFO_PAUSE_STATE, &paused);
|
||||
if(!result) {
|
||||
if(paused & CURLPAUSE_RECV)
|
||||
printf("Receiving is paused\n");
|
||||
if(paused & CURLPAUSE_SEND)
|
||||
printf("Sending is paused\n");
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
# %AVAILABILITY%
|
||||
|
||||
# RETURN VALUE
|
||||
|
||||
curl_easy_getinfo(3) returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non-zero means an error occurred, see
|
||||
libcurl-errors(3).
|
||||
|
|
@ -58,6 +58,7 @@ man_MANS = \
|
|||
CURLINFO_NAMELOOKUP_TIME_T.3 \
|
||||
CURLINFO_NUM_CONNECTS.3 \
|
||||
CURLINFO_OS_ERRNO.3 \
|
||||
CURLINFO_PAUSE_STATE.3 \
|
||||
CURLINFO_PRETRANSFER_TIME.3 \
|
||||
CURLINFO_PRETRANSFER_TIME_T.3 \
|
||||
CURLINFO_POSTTRANSFER_TIME_T.3 \
|
||||
|
|
|
|||
|
|
@ -470,6 +470,7 @@ CURLINFO_NONE 7.4.1
|
|||
CURLINFO_NUM_CONNECTS 7.12.3
|
||||
CURLINFO_OFF_T 7.55.0
|
||||
CURLINFO_OS_ERRNO 7.12.2
|
||||
CURLINFO_PAUSE_STATE 8.22.0
|
||||
CURLINFO_POSTTRANSFER_TIME_T 8.10.0
|
||||
CURLINFO_PRETRANSFER_TIME 7.4.1
|
||||
CURLINFO_PRETRANSFER_TIME_T 7.61.0
|
||||
|
|
|
|||
|
|
@ -3020,7 +3020,8 @@ typedef enum {
|
|||
CURLINFO_HTTPAUTH_USED = CURLINFO_LONG + 69,
|
||||
CURLINFO_PROXYAUTH_USED = CURLINFO_LONG + 70,
|
||||
CURLINFO_SIZE_DELIVERED = CURLINFO_OFF_T + 71,
|
||||
CURLINFO_LASTONE = 71
|
||||
CURLINFO_PAUSE_STATE = CURLINFO_LONG + 72,
|
||||
CURLINFO_LASTONE = 72
|
||||
} CURLINFO;
|
||||
|
||||
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "cfilters.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "connect.h" /* Curl_getconnectinfo() */
|
||||
#include "transfer.h"
|
||||
#include "bufref.h"
|
||||
#include "curlx/strparse.h"
|
||||
|
||||
|
|
@ -370,6 +371,13 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
|
|||
#endif
|
||||
;
|
||||
break;
|
||||
case CURLINFO_PAUSE_STATE:
|
||||
*param_longp = 0;
|
||||
if(Curl_xfer_recv_is_paused(data))
|
||||
*param_longp |= CURLPAUSE_RECV;
|
||||
if(Curl_xfer_send_is_paused(data))
|
||||
*param_longp |= CURLPAUSE_SEND;
|
||||
break;
|
||||
default:
|
||||
return CURLE_UNKNOWN_OPTION;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ test3223 test3224 test3225 test3226 test3227 test3228 test3229 \
|
|||
\
|
||||
test3300 test3301 test3302 test3303 test3304 test3305 test3306 \
|
||||
\
|
||||
test3400 test3401 \
|
||||
test3400 test3401 test3403 \
|
||||
\
|
||||
test4000 test4001 \
|
||||
\
|
||||
|
|
|
|||
62
tests/data/test3403
Normal file
62
tests/data/test3403
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="US-ASCII"?>
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
HTTP GET
|
||||
CURLINFO_PAUSE_STATE
|
||||
CURLPAUSE_RECV
|
||||
CURLPAUSE_SEND
|
||||
chunked Transfer-Encoding
|
||||
DELAY
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 200 OK swsclose%CR
|
||||
Transfer-Encoding: chunked%CR
|
||||
%CR
|
||||
4%CR
|
||||
data%CR
|
||||
5%CR
|
||||
d474
|
||||
%CR
|
||||
0%CR
|
||||
%CR
|
||||
</data>
|
||||
<datacheck>
|
||||
Got bytes but pausing!
|
||||
datad474
|
||||
</datacheck>
|
||||
<servercmd>
|
||||
writedelay: 10
|
||||
</servercmd>
|
||||
</reply>
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<tool>
|
||||
lib%TESTNUMBER
|
||||
</tool>
|
||||
<name>
|
||||
CURLINFO_PAUSE_STATE during paused transfer
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HTTPPORT/%TESTNUMBER
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<protocol crlf="headers">
|
||||
GET /%TESTNUMBER HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
||||
|
|
@ -125,4 +125,5 @@ TESTS_C = \
|
|||
lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c \
|
||||
lib3100.c lib3101.c lib3102.c lib3103.c lib3104.c lib3105.c \
|
||||
lib3207.c lib3208.c \
|
||||
lib3403.c \
|
||||
lib5000.c lib5004.c
|
||||
|
|
|
|||
162
tests/libtest/lib3403.c
Normal file
162
tests/libtest/lib3403.c
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "first.h"
|
||||
|
||||
#include "testtrace.h"
|
||||
|
||||
struct t3403_state {
|
||||
CURL *curl;
|
||||
int errors;
|
||||
int write_calls;
|
||||
int xfer_while_recv_paused;
|
||||
int checked_unpaused;
|
||||
int checked_send_paused;
|
||||
};
|
||||
|
||||
static int check_pause_state(struct t3403_state *st, long expected,
|
||||
const char *label)
|
||||
{
|
||||
long state = -1;
|
||||
CURLcode result = curl_easy_getinfo(st->curl, CURLINFO_PAUSE_STATE, &state);
|
||||
|
||||
if(result != CURLE_OK) {
|
||||
curl_mfprintf(stderr, "%s: getinfo failed (%d)\n", label, (int)result);
|
||||
st->errors++;
|
||||
return 1;
|
||||
}
|
||||
if(state != expected) {
|
||||
curl_mfprintf(stderr, "%s: expected %ld, got %ld\n",
|
||||
label, expected, state);
|
||||
st->errors++;
|
||||
return 1;
|
||||
}
|
||||
curl_mfprintf(stderr, "%s: pause state %ld OK\n", label, state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t3403_xferinfo(void *userp,
|
||||
curl_off_t dltotal,
|
||||
curl_off_t dlnow,
|
||||
curl_off_t ultotal,
|
||||
curl_off_t ulnow)
|
||||
{
|
||||
struct t3403_state *st = (struct t3403_state *)userp;
|
||||
|
||||
(void)dltotal;
|
||||
(void)dlnow;
|
||||
(void)ultotal;
|
||||
(void)ulnow;
|
||||
|
||||
if(st->write_calls == 1 && !st->xfer_while_recv_paused) {
|
||||
st->xfer_while_recv_paused = 1;
|
||||
check_pause_state(st, CURLPAUSE_RECV, "recv paused via write callback");
|
||||
curl_easy_pause(st->curl, CURLPAUSE_CONT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(st->write_calls >= 2 && !st->checked_unpaused) {
|
||||
st->checked_unpaused = 1;
|
||||
check_pause_state(st, 0, "unpaused after CONT");
|
||||
curl_easy_pause(st->curl, CURLPAUSE_SEND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(st->checked_unpaused && !st->checked_send_paused) {
|
||||
st->checked_send_paused = 1;
|
||||
check_pause_state(st, CURLPAUSE_SEND, "send paused explicitly");
|
||||
curl_easy_pause(st->curl, CURLPAUSE_CONT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t t3403_write_cb(char *ptr, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
struct t3403_state *st = (struct t3403_state *)userp;
|
||||
size_t len = size * nmemb;
|
||||
|
||||
st->write_calls++;
|
||||
if(st->write_calls == 1) {
|
||||
if(len)
|
||||
curl_mprintf("Got bytes but pausing!\n");
|
||||
return CURL_WRITEFUNC_PAUSE;
|
||||
}
|
||||
|
||||
fwrite(ptr, size, nmemb, stdout);
|
||||
return len;
|
||||
}
|
||||
|
||||
static CURLcode test_lib3403(const char *URL)
|
||||
{
|
||||
CURL *curl = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct t3403_state st;
|
||||
|
||||
start_test_timing();
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
|
||||
global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
easy_init(curl);
|
||||
st.curl = curl;
|
||||
|
||||
check_pause_state(&st, 0, "before transfer");
|
||||
|
||||
easy_setopt(curl, CURLOPT_URL, URL);
|
||||
easy_setopt(curl, CURLOPT_WRITEFUNCTION, t3403_write_cb);
|
||||
easy_setopt(curl, CURLOPT_WRITEDATA, &st);
|
||||
easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, t3403_xferinfo);
|
||||
easy_setopt(curl, CURLOPT_XFERINFODATA, &st);
|
||||
easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||
|
||||
debug_config.nohex = TRUE;
|
||||
debug_config.tracetime = TRUE;
|
||||
easy_setopt(curl, CURLOPT_DEBUGDATA, &debug_config);
|
||||
easy_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb);
|
||||
easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
|
||||
result = curl_easy_perform(curl);
|
||||
|
||||
check_pause_state(&st, 0, "after transfer");
|
||||
|
||||
if(!st.xfer_while_recv_paused || !st.checked_unpaused ||
|
||||
!st.checked_send_paused) {
|
||||
curl_mfprintf(stderr, "missing pause state checks "
|
||||
"(recv=%d unpaused=%d send=%d)\n",
|
||||
st.xfer_while_recv_paused, st.checked_unpaused,
|
||||
st.checked_send_paused);
|
||||
st.errors++;
|
||||
}
|
||||
|
||||
if(st.errors)
|
||||
result = TEST_ERR_FAILURE;
|
||||
|
||||
test_cleanup:
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
curl_global_cleanup();
|
||||
|
||||
return result;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue