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