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 "test.h"
25
26 #include "testutil.h"
27 #include "warnless.h"
28 #include "memdebug.h"
29
30 struct transfer_status {
31 CURL *easy;
32 int hd_count;
33 int bd_count;
34 CURLcode result;
35 };
36
37 #define KN(a) a, #a
38
geterr(const char * name,CURLcode val,int lineno)39 static int geterr(const char *name, CURLcode val, int lineno)
40 {
41 printf("CURLINFO_%s returned %d, \"%s\" on line %d\n",
42 name, val, curl_easy_strerror(val), lineno);
43 return (int)val;
44 }
45
report_time(const char * key,const char * where,curl_off_t time,bool ok)46 static void report_time(const char *key, const char *where, curl_off_t time,
47 bool ok)
48 {
49 if(ok)
50 printf("%s on %s is OK\n", key, where);
51 else
52 printf("%s on %s is WRONG: %" CURL_FORMAT_CURL_OFF_T "\n",
53 key, where, time);
54 }
55
check_time(CURL * easy,int key,const char * name,const char * where)56 static void check_time(CURL *easy, int key, const char *name,
57 const char *where)
58 {
59 curl_off_t tval;
60 CURLcode res = curl_easy_getinfo(easy, (CURLINFO)key, &tval);
61 if(res) {
62 geterr(name, res, __LINE__);
63 }
64 else
65 report_time(name, where, tval, tval > 0);
66 }
67
check_time0(CURL * easy,int key,const char * name,const char * where)68 static void check_time0(CURL *easy, int key, const char *name,
69 const char *where)
70 {
71 curl_off_t tval;
72 CURLcode res = curl_easy_getinfo(easy, (CURLINFO)key, &tval);
73 if(res) {
74 geterr(name, res, __LINE__);
75 }
76 else
77 report_time(name, where, tval, !tval);
78 }
79
header_callback(char * ptr,size_t size,size_t nmemb,void * userp)80 static size_t header_callback(char *ptr, size_t size, size_t nmemb,
81 void *userp)
82 {
83 struct transfer_status *st = (struct transfer_status *)userp;
84 size_t len = size * nmemb;
85
86 (void)ptr;
87 if(!st->hd_count++) {
88 /* first header, check some CURLINFO value to be reported. See #13125 */
89 check_time(st->easy, KN(CURLINFO_CONNECT_TIME_T), "1st header");
90 check_time(st->easy, KN(CURLINFO_PRETRANSFER_TIME_T), "1st header");
91 check_time(st->easy, KN(CURLINFO_STARTTRANSFER_TIME_T), "1st header");
92 /* continuously updated */
93 check_time(st->easy, KN(CURLINFO_TOTAL_TIME_T), "1st header");
94 /* no SSL, must be 0 */
95 check_time0(st->easy, KN(CURLINFO_APPCONNECT_TIME_T), "1st header");
96 /* download not really started */
97 check_time0(st->easy, KN(CURLINFO_SPEED_DOWNLOAD_T), "1st header");
98 }
99 (void)fwrite(ptr, size, nmemb, stdout);
100 return len;
101 }
102
write_callback(char * ptr,size_t size,size_t nmemb,void * userp)103 static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userp)
104 {
105 struct transfer_status *st = (struct transfer_status *)userp;
106
107 (void)ptr;
108 (void)st;
109 fwrite(ptr, size, nmemb, stdout);
110 return size * nmemb;
111 }
112
test(char * URL)113 CURLcode test(char *URL)
114 {
115 CURL *curls = NULL;
116 CURLcode res = CURLE_OK;
117 struct transfer_status st;
118
119 start_test_timing();
120
121 memset(&st, 0, sizeof(st));
122
123 global_init(CURL_GLOBAL_ALL);
124
125 easy_init(curls);
126 st.easy = curls; /* to allow callbacks access */
127
128 easy_setopt(curls, CURLOPT_URL, URL);
129 easy_setopt(curls, CURLOPT_WRITEFUNCTION, write_callback);
130 easy_setopt(curls, CURLOPT_WRITEDATA, &st);
131 easy_setopt(curls, CURLOPT_HEADERFUNCTION, header_callback);
132 easy_setopt(curls, CURLOPT_HEADERDATA, &st);
133
134 easy_setopt(curls, CURLOPT_NOPROGRESS, 0L);
135
136 res = curl_easy_perform(curls);
137
138 check_time(curls, KN(CURLINFO_CONNECT_TIME_T), "done");
139 check_time(curls, KN(CURLINFO_PRETRANSFER_TIME_T), "done");
140 check_time(curls, KN(CURLINFO_POSTTRANSFER_TIME_T), "done");
141 check_time(curls, KN(CURLINFO_STARTTRANSFER_TIME_T), "done");
142 /* no SSL, must be 0 */
143 check_time0(curls, KN(CURLINFO_APPCONNECT_TIME_T), "done");
144 check_time(curls, KN(CURLINFO_SPEED_DOWNLOAD_T), "done");
145 check_time(curls, KN(CURLINFO_TOTAL_TIME_T), "done");
146
147 test_cleanup:
148
149 curl_easy_cleanup(curls);
150 curl_global_cleanup();
151
152 return res; /* return the final return code */
153 }
154