progressfunc.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2020, 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. ***************************************************************************/
  22. /* <DESC>
  23. * Use the progress callbacks, old and/or new one depending on available
  24. * libcurl version.
  25. * </DESC>
  26. */
  27. #include <stdio.h>
  28. #include <curl/curl.h>
  29. #if LIBCURL_VERSION_NUM >= 0x073d00
  30. /* In libcurl 7.61.0, support was added for extracting the time in plain
  31. microseconds. Older libcurl versions are stuck in using 'double' for this
  32. information so we complicate this example a bit by supporting either
  33. approach. */
  34. #define TIME_IN_US 1 /* microseconds */
  35. #define TIMETYPE curl_off_t
  36. #define TIMEOPT CURLINFO_TOTAL_TIME_T
  37. #define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3000000
  38. #else
  39. #define TIMETYPE double
  40. #define TIMEOPT CURLINFO_TOTAL_TIME
  41. #define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3
  42. #endif
  43. #define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES 6000
  44. struct myprogress {
  45. TIMETYPE lastruntime; /* type depends on version, see above */
  46. CURL *curl;
  47. };
  48. /* this is how the CURLOPT_XFERINFOFUNCTION callback works */
  49. static int xferinfo(void *p,
  50. curl_off_t dltotal, curl_off_t dlnow,
  51. curl_off_t ultotal, curl_off_t ulnow)
  52. {
  53. struct myprogress *myp = (struct myprogress *)p;
  54. CURL *curl = myp->curl;
  55. TIMETYPE curtime = 0;
  56. curl_easy_getinfo(curl, TIMEOPT, &curtime);
  57. /* under certain circumstances it may be desirable for certain functionality
  58. to only run every N seconds, in order to do this the transaction time can
  59. be used */
  60. if((curtime - myp->lastruntime) >= MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL) {
  61. myp->lastruntime = curtime;
  62. #ifdef TIME_IN_US
  63. fprintf(stderr, "TOTAL TIME: %" CURL_FORMAT_CURL_OFF_T ".%06ld\r\n",
  64. (curtime / 1000000), (long)(curtime % 1000000));
  65. #else
  66. fprintf(stderr, "TOTAL TIME: %f \r\n", curtime);
  67. #endif
  68. }
  69. fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
  70. " DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
  71. "\r\n",
  72. ulnow, ultotal, dlnow, dltotal);
  73. if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES)
  74. return 1;
  75. return 0;
  76. }
  77. #if LIBCURL_VERSION_NUM < 0x072000
  78. /* for libcurl older than 7.32.0 (CURLOPT_PROGRESSFUNCTION) */
  79. static int older_progress(void *p,
  80. double dltotal, double dlnow,
  81. double ultotal, double ulnow)
  82. {
  83. return xferinfo(p,
  84. (curl_off_t)dltotal,
  85. (curl_off_t)dlnow,
  86. (curl_off_t)ultotal,
  87. (curl_off_t)ulnow);
  88. }
  89. #endif
  90. int main(void)
  91. {
  92. CURL *curl;
  93. CURLcode res = CURLE_OK;
  94. struct myprogress prog;
  95. curl = curl_easy_init();
  96. if(curl) {
  97. prog.lastruntime = 0;
  98. prog.curl = curl;
  99. curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
  100. #if LIBCURL_VERSION_NUM >= 0x072000
  101. /* xferinfo was introduced in 7.32.0, no earlier libcurl versions will
  102. compile as they won't have the symbols around.
  103. If built with a newer libcurl, but running with an older libcurl:
  104. curl_easy_setopt() will fail in run-time trying to set the new
  105. callback, making the older callback get used.
  106. New libcurls will prefer the new callback and instead use that one even
  107. if both callbacks are set. */
  108. curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
  109. /* pass the struct pointer into the xferinfo function, note that this is
  110. an alias to CURLOPT_PROGRESSDATA */
  111. curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);
  112. #else
  113. curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, older_progress);
  114. /* pass the struct pointer into the progress function */
  115. curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog);
  116. #endif
  117. curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
  118. res = curl_easy_perform(curl);
  119. if(res != CURLE_OK)
  120. fprintf(stderr, "%s\n", curl_easy_strerror(res));
  121. /* always cleanup */
  122. curl_easy_cleanup(curl);
  123. }
  124. return (int)res;
  125. }