quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

tool_cb_rea.c (5462B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, 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 "tool_cfgable.h"
     31 #include "tool_cb_rea.h"
     32 #include "tool_operate.h"
     33 #include "tool_util.h"
     34 #include "tool_msgs.h"
     35 
     36 #include "memdebug.h" /* keep this as LAST include */
     37 
     38 /*
     39 ** callback for CURLOPT_READFUNCTION
     40 */
     41 
     42 size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
     43 {
     44   ssize_t rc = 0;
     45   struct per_transfer *per = userdata;
     46   struct OperationConfig *config = per->config;
     47 
     48   if((per->uploadfilesize != -1) &&
     49      (per->uploadedsofar == per->uploadfilesize)) {
     50     /* done */
     51     return 0;
     52   }
     53 
     54   if(config->timeout_ms) {
     55     struct curltime now = curlx_now();
     56     long msdelta = (long)curlx_timediff(now, per->start);
     57 
     58     if(msdelta > config->timeout_ms)
     59       /* timeout */
     60       return 0;
     61 #ifndef _WIN32
     62     /* this logic waits on read activity on a file descriptor that is not a
     63        socket which makes it not work with select() on Windows */
     64     else {
     65       fd_set bits;
     66       struct timeval timeout;
     67       long wait = config->timeout_ms - msdelta;
     68 
     69       /* wait this long at the most */
     70       timeout.tv_sec = wait/1000;
     71       timeout.tv_usec = (int)((wait%1000)*1000);
     72 
     73       FD_ZERO(&bits);
     74 #if defined(__DJGPP__)
     75 #pragma GCC diagnostic push
     76 #pragma GCC diagnostic ignored "-Warith-conversion"
     77 #endif
     78       FD_SET(per->infd, &bits);
     79 #if defined(__DJGPP__)
     80 #pragma GCC diagnostic pop
     81 #endif
     82       if(!select(per->infd + 1, &bits, NULL, NULL, &timeout))
     83         return 0; /* timeout */
     84     }
     85 #endif
     86   }
     87 
     88   /* If we are on Windows, and using `-T .`, then per->infd points to a socket
     89    connected to stdin via a reader thread, and needs to be read with recv()
     90    Make sure we are in non-blocking mode and infd is not regular stdin
     91    On Linux per->infd should be stdin (0) and the block below should not
     92    execute */
     93   if(!strcmp(per->uploadfile, ".") && per->infd > 0) {
     94 #if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE)
     95     rc = recv(per->infd, buffer, curlx_uztosi(sz * nmemb), 0);
     96     if(rc < 0) {
     97       if(SOCKERRNO == SOCKEWOULDBLOCK) {
     98         CURL_SETERRNO(0);
     99         config->readbusy = TRUE;
    100         return CURL_READFUNC_PAUSE;
    101       }
    102 
    103       rc = 0;
    104     }
    105 #else
    106     warnf(per->config->global, "per->infd != 0: FD == %d. This behavior"
    107           " is only supported on desktop Windows", per->infd);
    108 #endif
    109   }
    110   else {
    111     rc = read(per->infd, buffer, sz*nmemb);
    112     if(rc < 0) {
    113       if(errno == EAGAIN) {
    114         CURL_SETERRNO(0);
    115         config->readbusy = TRUE;
    116         return CURL_READFUNC_PAUSE;
    117       }
    118       /* since size_t is unsigned we cannot return negative values fine */
    119       rc = 0;
    120     }
    121   }
    122   if((per->uploadfilesize != -1) &&
    123      (per->uploadedsofar + rc > per->uploadfilesize)) {
    124     /* do not allow uploading more than originally set out to do */
    125     curl_off_t delta = per->uploadedsofar + rc - per->uploadfilesize;
    126     warnf(per->config->global, "File size larger in the end than when "
    127           "started. Dropping at least %" CURL_FORMAT_CURL_OFF_T " bytes",
    128           delta);
    129     rc = (ssize_t)(per->uploadfilesize - per->uploadedsofar);
    130   }
    131   config->readbusy = FALSE;
    132 
    133   /* when select() returned zero here, it timed out */
    134   return (size_t)rc;
    135 }
    136 
    137 /*
    138 ** callback for CURLOPT_XFERINFOFUNCTION used to unpause busy reads
    139 */
    140 
    141 int tool_readbusy_cb(void *clientp,
    142                      curl_off_t dltotal, curl_off_t dlnow,
    143                      curl_off_t ultotal, curl_off_t ulnow)
    144 {
    145   struct per_transfer *per = clientp;
    146   struct OperationConfig *config = per->config;
    147   static curl_off_t ulprev;
    148 
    149   (void)dltotal;  /* unused */
    150   (void)dlnow;  /* unused */
    151   (void)ultotal;  /* unused */
    152   (void)ulnow;  /* unused */
    153 
    154   if(config->readbusy) {
    155     if(ulprev == ulnow) {
    156 #ifndef _WIN32
    157       fd_set bits;
    158       struct timeval timeout;
    159       /* wait this long at the most */
    160       timeout.tv_sec = 0;
    161       timeout.tv_usec = 1000;
    162 
    163       FD_ZERO(&bits);
    164 #if defined(__DJGPP__)
    165 #pragma GCC diagnostic push
    166 #pragma GCC diagnostic ignored "-Warith-conversion"
    167 #endif
    168       FD_SET(per->infd, &bits);
    169 #if defined(__DJGPP__)
    170 #pragma GCC diagnostic pop
    171 #endif
    172       select(per->infd + 1, &bits, NULL, NULL, &timeout);
    173 #else
    174       /* sleep */
    175       curlx_wait_ms(1);
    176 #endif
    177     }
    178 
    179     config->readbusy = FALSE;
    180     curl_easy_pause(per->curl, CURLPAUSE_CONT);
    181   }
    182 
    183   ulprev = ulnow;
    184 
    185   return per->noprogress ? 0 : CURL_PROGRESSFUNC_CONTINUE;
    186 }