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/* <DESC> 25 * Show transfer timing info after download completes. 26 * </DESC> 27 */ 28/* Example source code to show how the callback function can be used to 29 * download data into a chunk of memory instead of storing it in a file. 30 * After successful download we use curl_easy_getinfo() calls to get the 31 * amount of downloaded bytes, the time used for the whole download, and 32 * the average download speed. 33 * On Linux you can create the download test files with: 34 * dd if=/dev/urandom of=file_1M.bin bs=1M count=1 35 * 36 */ 37 38#include <stdio.h> 39#include <stdlib.h> 40#include <time.h> 41 42#include <curl/curl.h> 43 44#define URL_BASE "http://speedtest.your.domain/" 45#define URL_1M URL_BASE "file_1M.bin" 46#define URL_2M URL_BASE "file_2M.bin" 47#define URL_5M URL_BASE "file_5M.bin" 48#define URL_10M URL_BASE "file_10M.bin" 49#define URL_20M URL_BASE "file_20M.bin" 50#define URL_50M URL_BASE "file_50M.bin" 51#define URL_100M URL_BASE "file_100M.bin" 52 53#define CHKSPEED_VERSION "1.0" 54 55static size_t WriteCallback(void *ptr, size_t size, size_t nmemb, void *data) 56{ 57 /* we are not interested in the downloaded bytes itself, 58 so we only return the size we would have saved ... */ 59 (void)ptr; /* unused */ 60 (void)data; /* unused */ 61 return (size_t)(size * nmemb); 62} 63 64int main(int argc, char *argv[]) 65{ 66 CURL *curl_handle; 67 CURLcode res; 68 int prtall = 0, prtsep = 0, prttime = 0; 69 const char *url = URL_1M; 70 char *appname = argv[0]; 71 72 if(argc > 1) { 73 /* parse input parameters */ 74 for(argc--, argv++; *argv; argc--, argv++) { 75 if(argv[0][0] == '-') { 76 switch(argv[0][1]) { 77 case 'h': 78 case 'H': 79 fprintf(stderr, 80 "\rUsage: %s [-m=1|2|5|10|20|50|100] [-t] [-x] [url]\n", 81 appname); 82 exit(1); 83 case 'v': 84 case 'V': 85 fprintf(stderr, "\r%s %s - %s\n", 86 appname, CHKSPEED_VERSION, curl_version()); 87 exit(1); 88 case 'a': 89 case 'A': 90 prtall = 1; 91 break; 92 case 'x': 93 case 'X': 94 prtsep = 1; 95 break; 96 case 't': 97 case 'T': 98 prttime = 1; 99 break; 100 case 'm': 101 case 'M': 102 if(argv[0][2] == '=') { 103 long m = strtol((*argv) + 3, NULL, 10); 104 switch(m) { 105 case 1: 106 url = URL_1M; 107 break; 108 case 2: 109 url = URL_2M; 110 break; 111 case 5: 112 url = URL_5M; 113 break; 114 case 10: 115 url = URL_10M; 116 break; 117 case 20: 118 url = URL_20M; 119 break; 120 case 50: 121 url = URL_50M; 122 break; 123 case 100: 124 url = URL_100M; 125 break; 126 default: 127 fprintf(stderr, "\r%s: invalid parameter %s\n", 128 appname, *argv + 3); 129 return 1; 130 } 131 break; 132 } 133 fprintf(stderr, "\r%s: invalid or unknown option %s\n", 134 appname, *argv); 135 return 1; 136 default: 137 fprintf(stderr, "\r%s: invalid or unknown option %s\n", 138 appname, *argv); 139 return 1; 140 } 141 } 142 else { 143 url = *argv; 144 } 145 } 146 } 147 148 /* print separator line */ 149 if(prtsep) { 150 printf("-------------------------------------------------\n"); 151 } 152 /* print localtime */ 153 if(prttime) { 154 time_t t = time(NULL); 155 printf("Localtime: %s", ctime(&t)); 156 } 157 158 /* init libcurl */ 159 curl_global_init(CURL_GLOBAL_ALL); 160 161 /* init the curl session */ 162 curl_handle = curl_easy_init(); 163 164 /* specify URL to get */ 165 curl_easy_setopt(curl_handle, CURLOPT_URL, url); 166 167 /* send all data to this function */ 168 curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteCallback); 169 170 /* some servers do not like requests that are made without a user-agent 171 field, so we provide one */ 172 curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, 173 "libcurl-speedchecker/" CHKSPEED_VERSION); 174 175 /* get it! */ 176 res = curl_easy_perform(curl_handle); 177 178 if(CURLE_OK == res) { 179 curl_off_t val; 180 181 /* check for bytes downloaded */ 182 res = curl_easy_getinfo(curl_handle, CURLINFO_SIZE_DOWNLOAD_T, &val); 183 if((CURLE_OK == res) && (val>0)) 184 printf("Data downloaded: %lu bytes.\n", (unsigned long)val); 185 186 /* check for total download time */ 187 res = curl_easy_getinfo(curl_handle, CURLINFO_TOTAL_TIME_T, &val); 188 if((CURLE_OK == res) && (val>0)) 189 printf("Total download time: %lu.%06lu sec.\n", 190 (unsigned long)(val / 1000000), (unsigned long)(val % 1000000)); 191 192 /* check for average download speed */ 193 res = curl_easy_getinfo(curl_handle, CURLINFO_SPEED_DOWNLOAD_T, &val); 194 if((CURLE_OK == res) && (val>0)) 195 printf("Average download speed: %lu kbyte/sec.\n", 196 (unsigned long)(val / 1024)); 197 198 if(prtall) { 199 /* check for name resolution time */ 200 res = curl_easy_getinfo(curl_handle, CURLINFO_NAMELOOKUP_TIME_T, &val); 201 if((CURLE_OK == res) && (val>0)) 202 printf("Name lookup time: %lu.%06lu sec.\n", 203 (unsigned long)(val / 1000000), (unsigned long)(val % 1000000)); 204 205 /* check for connect time */ 206 res = curl_easy_getinfo(curl_handle, CURLINFO_CONNECT_TIME_T, &val); 207 if((CURLE_OK == res) && (val>0)) 208 printf("Connect time: %lu.%06lu sec.\n", 209 (unsigned long)(val / 1000000), (unsigned long)(val % 1000000)); 210 } 211 } 212 else { 213 fprintf(stderr, "Error while fetching '%s' : %s\n", 214 url, curl_easy_strerror(res)); 215 } 216 217 /* cleanup curl stuff */ 218 curl_easy_cleanup(curl_handle); 219 220 /* we are done with libcurl, so clean it up */ 221 curl_global_cleanup(); 222 223 return 0; 224} 225