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