Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/src/tool_cb_rea.c
2065 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
#include "tool_setup.h"
25
26
#ifdef HAVE_SYS_SELECT_H
27
#include <sys/select.h>
28
#endif
29
30
#include <curlx.h>
31
32
#include "tool_cfgable.h"
33
#include "tool_cb_rea.h"
34
#include "tool_operate.h"
35
#include "tool_util.h"
36
#include "tool_msgs.h"
37
#include "tool_sleep.h"
38
39
#include <memdebug.h> /* keep this as LAST include */
40
41
/*
42
** callback for CURLOPT_READFUNCTION
43
*/
44
45
size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
46
{
47
ssize_t rc = 0;
48
struct per_transfer *per = userdata;
49
struct OperationConfig *config = per->config;
50
51
if((per->uploadfilesize != -1) &&
52
(per->uploadedsofar == per->uploadfilesize)) {
53
/* done */
54
return 0;
55
}
56
57
if(config->timeout_ms) {
58
struct curltime now = curlx_now();
59
long msdelta = (long)curlx_timediff(now, per->start);
60
61
if(msdelta > config->timeout_ms)
62
/* timeout */
63
return 0;
64
#ifndef _WIN32
65
/* this logic waits on read activity on a file descriptor that is not a
66
socket which makes it not work with select() on Windows */
67
else {
68
fd_set bits;
69
struct timeval timeout;
70
long wait = config->timeout_ms - msdelta;
71
72
/* wait this long at the most */
73
timeout.tv_sec = wait/1000;
74
timeout.tv_usec = (int)((wait%1000)*1000);
75
76
FD_ZERO(&bits);
77
#if defined(__DJGPP__)
78
#pragma GCC diagnostic push
79
#pragma GCC diagnostic ignored "-Warith-conversion"
80
#endif
81
FD_SET(per->infd, &bits);
82
#if defined(__DJGPP__)
83
#pragma GCC diagnostic pop
84
#endif
85
if(!select(per->infd + 1, &bits, NULL, NULL, &timeout))
86
return 0; /* timeout */
87
}
88
#endif
89
}
90
91
rc = read(per->infd, buffer, sz*nmemb);
92
if(rc < 0) {
93
if(errno == EAGAIN) {
94
CURL_SETERRNO(0);
95
config->readbusy = TRUE;
96
return CURL_READFUNC_PAUSE;
97
}
98
/* since size_t is unsigned we cannot return negative values fine */
99
rc = 0;
100
}
101
if((per->uploadfilesize != -1) &&
102
(per->uploadedsofar + rc > per->uploadfilesize)) {
103
/* do not allow uploading more than originally set out to do */
104
curl_off_t delta = per->uploadedsofar + rc - per->uploadfilesize;
105
warnf(per->config->global, "File size larger in the end than when "
106
"started. Dropping at least %" CURL_FORMAT_CURL_OFF_T " bytes",
107
delta);
108
rc = (ssize_t)(per->uploadfilesize - per->uploadedsofar);
109
}
110
config->readbusy = FALSE;
111
112
/* when select() returned zero here, it timed out */
113
return (size_t)rc;
114
}
115
116
/*
117
** callback for CURLOPT_XFERINFOFUNCTION used to unpause busy reads
118
*/
119
120
int tool_readbusy_cb(void *clientp,
121
curl_off_t dltotal, curl_off_t dlnow,
122
curl_off_t ultotal, curl_off_t ulnow)
123
{
124
struct per_transfer *per = clientp;
125
struct OperationConfig *config = per->config;
126
127
(void)dltotal; /* unused */
128
(void)dlnow; /* unused */
129
(void)ultotal; /* unused */
130
(void)ulnow; /* unused */
131
132
if(config->readbusy) {
133
/* lame code to keep the rate down because the input might not deliver
134
anything, get paused again and come back here immediately */
135
static timediff_t rate = 500;
136
static struct curltime prev;
137
static curl_off_t ulprev;
138
139
if(ulprev == ulnow) {
140
/* it did not upload anything since last call */
141
struct curltime now = curlx_now();
142
if(prev.tv_sec)
143
/* get a rolling average rate */
144
rate -= rate/4 - curlx_timediff(now, prev)/4;
145
prev = now;
146
}
147
else {
148
rate = 50;
149
ulprev = ulnow;
150
}
151
if(rate >= 50) {
152
/* keeps the looping down to 20 times per second in the crazy case */
153
config->readbusy = FALSE;
154
curl_easy_pause(per->curl, CURLPAUSE_CONT);
155
}
156
else
157
/* sleep half a period */
158
tool_go_sleep(25);
159
}
160
161
return per->noprogress ? 0 : CURL_PROGRESSFUNC_CONTINUE;
162
}
163
164