]>
Commit | Line | Data |
---|---|---|
9ecf53e1 YT |
1 | /*************************************************************************** |
2 | * _ _ ____ _ | |
3 | * Project ___| | | | _ \| | | |
4 | * / __| | | | |_) | | | |
5 | * | (__| |_| | _ <| |___ | |
6 | * \___|\___/|_| \_\_____| | |
7 | * | |
2bc1d775 | 8 | * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. |
9ecf53e1 YT |
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 | |
4d2f8006 | 12 | * are also available at https://curl.se/docs/copyright.html. |
9ecf53e1 YT |
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 | * | |
ad9bc597 MM |
21 | * SPDX-License-Identifier: curl |
22 | * | |
9ecf53e1 | 23 | ***************************************************************************/ |
919c97fa | 24 | #include "tool_setup.h" |
9ecf53e1 | 25 | |
a55256cf DS |
26 | #ifdef HAVE_SYS_SELECT_H |
27 | #include <sys/select.h> | |
28 | #endif | |
29 | ||
c6702c7d YT |
30 | #define ENABLE_CURLX_PRINTF |
31 | /* use our own printf() functions */ | |
32 | #include "curlx.h" | |
9ecf53e1 | 33 | |
c6702c7d YT |
34 | #include "tool_cfgable.h" |
35 | #include "tool_cb_rea.h" | |
9a2cbf30 | 36 | #include "tool_operate.h" |
a55256cf | 37 | #include "tool_util.h" |
1f85420a | 38 | #include "tool_msgs.h" |
5f4aaf8b | 39 | #include "tool_sleep.h" |
9ecf53e1 | 40 | |
4a5aa668 | 41 | #include "memdebug.h" /* keep this as LAST include */ |
c6702c7d YT |
42 | |
43 | /* | |
44 | ** callback for CURLOPT_READFUNCTION | |
45 | */ | |
46 | ||
f2ed79d8 | 47 | size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) |
c6702c7d | 48 | { |
a55256cf | 49 | ssize_t rc = 0; |
1f85420a DS |
50 | struct per_transfer *per = userdata; |
51 | struct OperationConfig *config = per->config; | |
52 | ||
53 | if((per->uploadfilesize != -1) && | |
54 | (per->uploadedsofar == per->uploadfilesize)) { | |
55 | /* done */ | |
56 | return 0; | |
57 | } | |
a55256cf DS |
58 | |
59 | if(config->timeout_ms) { | |
60 | struct timeval now = tvnow(); | |
1f85420a | 61 | long msdelta = tvdiff(now, per->start); |
a55256cf DS |
62 | |
63 | if(msdelta > config->timeout_ms) | |
64 | /* timeout */ | |
65 | return 0; | |
e9a7d4a1 | 66 | #ifndef _WIN32 |
a55256cf DS |
67 | /* this logic waits on read activity on a file descriptor that is not a |
68 | socket which makes it not work with select() on Windows */ | |
69 | else { | |
70 | fd_set bits; | |
71 | struct timeval timeout; | |
72 | long wait = config->timeout_ms - msdelta; | |
73 | ||
74 | /* wait this long at the most */ | |
75 | timeout.tv_sec = wait/1000; | |
6f93d5f6 | 76 | timeout.tv_usec = (int)((wait%1000)*1000); |
a55256cf DS |
77 | |
78 | FD_ZERO(&bits); | |
1f85420a DS |
79 | FD_SET(per->infd, &bits); |
80 | if(!select(per->infd + 1, &bits, NULL, NULL, &timeout)) | |
a55256cf DS |
81 | return 0; /* timeout */ |
82 | } | |
83 | #endif | |
84 | } | |
c6702c7d | 85 | |
1f85420a | 86 | rc = read(per->infd, buffer, sz*nmemb); |
c6702c7d YT |
87 | if(rc < 0) { |
88 | if(errno == EAGAIN) { | |
89 | errno = 0; | |
1f85420a | 90 | config->readbusy = TRUE; |
c6702c7d YT |
91 | return CURL_READFUNC_PAUSE; |
92 | } | |
93 | /* since size_t is unsigned we can't return negative values fine */ | |
94 | rc = 0; | |
95 | } | |
1f85420a DS |
96 | if((per->uploadfilesize != -1) && |
97 | (per->uploadedsofar + rc > per->uploadfilesize)) { | |
98 | /* do not allow uploading more than originally set out to do */ | |
99 | curl_off_t delta = per->uploadedsofar + rc - per->uploadfilesize; | |
100 | warnf(per->config->global, "File size larger in the end than when " | |
101 | "started. Dropping at least %" CURL_FORMAT_CURL_OFF_T " bytes", | |
102 | delta); | |
103 | rc = (ssize_t)(per->uploadfilesize - per->uploadedsofar); | |
104 | } | |
105 | config->readbusy = FALSE; | |
a55256cf | 106 | |
127eb0d8 | 107 | /* when select() returned zero here, it timed out */ |
c6702c7d YT |
108 | return (size_t)rc; |
109 | } | |
9a2cbf30 JS |
110 | |
111 | /* | |
112 | ** callback for CURLOPT_XFERINFOFUNCTION used to unpause busy reads | |
113 | */ | |
114 | ||
115 | int tool_readbusy_cb(void *clientp, | |
116 | curl_off_t dltotal, curl_off_t dlnow, | |
117 | curl_off_t ultotal, curl_off_t ulnow) | |
118 | { | |
119 | struct per_transfer *per = clientp; | |
ad0aa27a | 120 | struct OperationConfig *config = per->config; |
9a2cbf30 JS |
121 | |
122 | (void)dltotal; /* unused */ | |
123 | (void)dlnow; /* unused */ | |
124 | (void)ultotal; /* unused */ | |
125 | (void)ulnow; /* unused */ | |
126 | ||
127 | if(config->readbusy) { | |
5f4aaf8b DS |
128 | /* lame code to keep the rate down because the input might not deliver |
129 | anything, get paused again and come back here immediately */ | |
130 | static long rate = 500; | |
131 | static struct timeval prev; | |
132 | static curl_off_t ulprev; | |
133 | ||
134 | if(ulprev == ulnow) { | |
135 | /* it did not upload anything since last call */ | |
136 | struct timeval now = tvnow(); | |
137 | if(prev.tv_sec) | |
138 | /* get a rolling average rate */ | |
139 | /* rate = rate - rate/4 + tvdiff(now, prev)/4; */ | |
140 | rate -= rate/4 - tvdiff(now, prev)/4; | |
141 | prev = now; | |
142 | } | |
143 | else { | |
144 | rate = 50; | |
145 | ulprev = ulnow; | |
146 | } | |
147 | if(rate >= 50) { | |
148 | /* keeps the looping down to 20 times per second in the crazy case */ | |
149 | config->readbusy = FALSE; | |
150 | curl_easy_pause(per->curl, CURLPAUSE_CONT); | |
151 | } | |
152 | else | |
153 | /* sleep half a period */ | |
154 | tool_go_sleep(25); | |
9a2cbf30 JS |
155 | } |
156 | ||
157 | return per->noprogress? 0 : CURL_PROGRESSFUNC_CONTINUE; | |
158 | } |