00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030
00031 #include <sys/time.h>
00032 #include <unistd.h>
00033
00034
00035 #include <curl/curl.h>
00036
00037 #ifndef CURLPIPE_MULTIPLEX
00038
00039
00040
00041 #define CURLPIPE_MULTIPLEX 0
00042 #endif
00043
00044 #define NUM_HANDLES 1000
00045
00046 void *curl_hnd[NUM_HANDLES];
00047 int num_transfers;
00048
00049
00050
00051 static int hnd2num(CURL *hnd)
00052 {
00053 int i;
00054 for(i=0; i< num_transfers; i++) {
00055 if(curl_hnd[i] == hnd)
00056 return i;
00057 }
00058 return 0;
00059 }
00060
00061 static
00062 void dump(const char *text, int num, unsigned char *ptr, size_t size,
00063 char nohex)
00064 {
00065 size_t i;
00066 size_t c;
00067
00068 unsigned int width=0x10;
00069
00070 if(nohex)
00071
00072 width = 0x40;
00073
00074 fprintf(stderr, "%d %s, %ld bytes (0x%lx)\n",
00075 num, text, (long)size, (long)size);
00076
00077 for(i=0; i<size; i+= width) {
00078
00079 fprintf(stderr, "%4.4lx: ", (long)i);
00080
00081 if(!nohex) {
00082
00083 for(c = 0; c < width; c++)
00084 if(i+c < size)
00085 fprintf(stderr, "%02x ", ptr[i+c]);
00086 else
00087 fputs(" ", stderr);
00088 }
00089
00090 for(c = 0; (c < width) && (i+c < size); c++) {
00091
00092 if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
00093 i+=(c+2-width);
00094 break;
00095 }
00096 fprintf(stderr, "%c",
00097 (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
00098
00099 if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
00100 i+=(c+3-width);
00101 break;
00102 }
00103 }
00104 fputc('\n', stderr);
00105 }
00106 }
00107
00108 static
00109 int my_trace(CURL *handle, curl_infotype type,
00110 char *data, size_t size,
00111 void *userp)
00112 {
00113 const char *text;
00114 int num = hnd2num(handle);
00115 (void)handle;
00116 (void)userp;
00117 switch(type) {
00118 case CURLINFO_TEXT:
00119 fprintf(stderr, "== %d Info: %s", num, data);
00120 default:
00121 return 0;
00122
00123 case CURLINFO_HEADER_OUT:
00124 text = "=> Send header";
00125 break;
00126 case CURLINFO_DATA_OUT:
00127 text = "=> Send data";
00128 break;
00129 case CURLINFO_SSL_DATA_OUT:
00130 text = "=> Send SSL data";
00131 break;
00132 case CURLINFO_HEADER_IN:
00133 text = "<= Recv header";
00134 break;
00135 case CURLINFO_DATA_IN:
00136 text = "<= Recv data";
00137 break;
00138 case CURLINFO_SSL_DATA_IN:
00139 text = "<= Recv SSL data";
00140 break;
00141 }
00142
00143 dump(text, num, (unsigned char *)data, size, 1);
00144 return 0;
00145 }
00146
00147 static void setup(CURL *hnd, int num)
00148 {
00149 FILE *out;
00150 char filename[128];
00151
00152 snprintf(filename, 128, "dl-%d", num);
00153
00154 out = fopen(filename, "wb");
00155
00156
00157 curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out);
00158
00159
00160 curl_easy_setopt(hnd, CURLOPT_URL, "https://localhost:8443/index.html");
00161
00162
00163 curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
00164 curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, my_trace);
00165
00166
00167 curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
00168
00169
00170 curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L);
00171 curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L);
00172
00173 #if (CURLPIPE_MULTIPLEX > 0)
00174
00175 curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
00176 #endif
00177
00178 curl_hnd[num] = hnd;
00179 }
00180
00181
00182
00183
00184 int main(int argc, char **argv)
00185 {
00186 CURL *easy[NUM_HANDLES];
00187 CURLM *multi_handle;
00188 int i;
00189 int still_running;
00190
00191 if(argc > 1)
00192
00193 num_transfers = atoi(argv[1]);
00194
00195 if(!num_transfers || (num_transfers > NUM_HANDLES))
00196 num_transfers = 3;
00197
00198
00199 multi_handle = curl_multi_init();
00200
00201 for(i=0; i<num_transfers; i++) {
00202 easy[i] = curl_easy_init();
00203
00204 setup(easy[i], i);
00205
00206
00207 curl_multi_add_handle(multi_handle, easy[i]);
00208 }
00209
00210 curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
00211
00212
00213 curl_multi_perform(multi_handle, &still_running);
00214
00215 do {
00216 struct timeval timeout;
00217 int rc;
00218 CURLMcode mc;
00219
00220 fd_set fdread;
00221 fd_set fdwrite;
00222 fd_set fdexcep;
00223 int maxfd = -1;
00224
00225 long curl_timeo = -1;
00226
00227 FD_ZERO(&fdread);
00228 FD_ZERO(&fdwrite);
00229 FD_ZERO(&fdexcep);
00230
00231
00232 timeout.tv_sec = 1;
00233 timeout.tv_usec = 0;
00234
00235 curl_multi_timeout(multi_handle, &curl_timeo);
00236 if(curl_timeo >= 0) {
00237 timeout.tv_sec = curl_timeo / 1000;
00238 if(timeout.tv_sec > 1)
00239 timeout.tv_sec = 1;
00240 else
00241 timeout.tv_usec = (curl_timeo % 1000) * 1000;
00242 }
00243
00244
00245 mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
00246
00247 if(mc != CURLM_OK) {
00248 fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
00249 break;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 if(maxfd == -1) {
00259 #ifdef _WIN32
00260 Sleep(100);
00261 rc = 0;
00262 #else
00263
00264 struct timeval wait = { 0, 100 * 1000 };
00265 rc = select(0, NULL, NULL, NULL, &wait);
00266 #endif
00267 }
00268 else {
00269
00270
00271 rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
00272 }
00273
00274 switch(rc) {
00275 case -1:
00276
00277 break;
00278 case 0:
00279 default:
00280
00281 curl_multi_perform(multi_handle, &still_running);
00282 break;
00283 }
00284 } while(still_running);
00285
00286 curl_multi_cleanup(multi_handle);
00287
00288 for(i=0; i<num_transfers; i++)
00289 curl_easy_cleanup(easy[i]);
00290
00291 return 0;
00292 }