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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include <string.h>
00064 #include <stdlib.h>
00065 #include <unistd.h>
00066 #include <stdio.h>
00067
00068 #include "gwlib/gwlib.h"
00069 #include "gwlib/http.h"
00070
00071 #define MAX_THREADS 1024
00072 #define MAX_IN_QUEUE 128
00073
00074 static long max_requests = 1;
00075 static double interval = 0;
00076 static int method = HTTP_METHOD_GET;
00077 static char **urls = NULL;
00078 static int num_urls = 0;
00079 static int verbose = 1;
00080 static Octstr *auth_username = NULL;
00081 static Octstr *auth_password = NULL;
00082 static Octstr *msg_text = NULL;
00083 static Octstr *ssl_client_certkey_file = NULL;
00084 static Octstr *extra_headers = NULL;
00085 static Octstr *content_file = NULL;
00086 static Octstr *method_name = NULL;
00087 static int file = 0;
00088 static List *split = NULL;
00089
00090
00091 static Octstr *post_content_create(void)
00092 {
00093 Octstr *content;
00094
00095 if ((content = octstr_read_file(octstr_get_cstr(content_file))) == NULL)
00096 panic(0, "Cannot read content text");
00097 debug("", 0, "body content is");
00098 octstr_dump(content, 0);
00099
00100 return content;
00101 }
00102
00103 static void start_request(HTTPCaller *caller, List *reqh, long i)
00104 {
00105 Octstr *url, *content = NULL;
00106 long *id;
00107
00108 if ((i % 1000) == 0)
00109 info(0, "Starting fetch %ld", i);
00110 id = gw_malloc(sizeof(long));
00111 *id = i;
00112 url = octstr_create(urls[i % num_urls]);
00113 if (file) {
00114 octstr_append(url, octstr_imm("&text="));
00115 octstr_append(url, msg_text);
00116 }
00117
00118
00119 if (split != NULL)
00120 http_header_combine(reqh, split);
00121
00122
00123
00124
00125
00126 if (content_file != NULL) {
00127 content = post_content_create();
00128 method = HTTP_METHOD_POST;
00129 }
00130
00131
00132
00133
00134
00135
00136 http_start_request(caller, method,
00137 url, reqh, content, 1, id, ssl_client_certkey_file);
00138
00139 debug("", 0, "Started request %ld with url:", *id);
00140 octstr_url_decode(url);
00141 octstr_dump(url, 0);
00142 octstr_destroy(url);
00143 octstr_destroy(msg_text);
00144 octstr_destroy(content);
00145 }
00146
00147
00148 static int receive_reply(HTTPCaller *caller)
00149 {
00150 void *id;
00151 int ret;
00152 Octstr *final_url;
00153 List *replyh;
00154 Octstr *replyb;
00155 Octstr *type;
00156 Octstr *charset;
00157 Octstr *os;
00158
00159 id = http_receive_result(caller, &ret, &final_url, &replyh, &replyb);
00160 octstr_destroy(final_url);
00161 if (id == NULL || ret == -1) {
00162 error(0, "http GET failed");
00163 return -1;
00164 }
00165 debug("", 0, "Done with request %ld", *(long *) id);
00166 gw_free(id);
00167
00168 http_header_get_content_type(replyh, &type, &charset);
00169 debug("", 0, "Content-type is <%s>, charset is <%s>",
00170 octstr_get_cstr(type),
00171 octstr_get_cstr(charset));
00172 octstr_destroy(type);
00173 octstr_destroy(charset);
00174 if (verbose)
00175 debug("", 0, "Reply headers:");
00176 while ((os = gwlist_extract_first(replyh)) != NULL) {
00177 if (verbose)
00178 octstr_dump(os, 1);
00179 octstr_destroy(os);
00180 }
00181 gwlist_destroy(replyh, NULL);
00182 if (verbose) {
00183 debug("", 0, "Reply body:");
00184 octstr_dump(replyb, 1);
00185 }
00186 octstr_destroy(replyb);
00187
00188 return 0;
00189 }
00190
00191
00192 static void client_thread(void *arg)
00193 {
00194 List *reqh;
00195 unsigned long i;
00196 long succeeded, failed;
00197 HTTPCaller *caller;
00198 char buf[1024];
00199 long in_queue;
00200 Counter *counter = NULL;
00201
00202 caller = arg;
00203 succeeded = 0;
00204 failed = 0;
00205 reqh = gwlist_create();
00206 sprintf(buf, "%ld", (long) gwthread_self());
00207 http_header_add(reqh, "X-Thread", buf);
00208 if (auth_username != NULL && auth_password != NULL)
00209 http_add_basic_auth(reqh, auth_username, auth_password);
00210
00211 in_queue = 0;
00212 counter = counter_create();
00213
00214 for (;;) {
00215 i = counter_increase(counter);
00216 if (i >= max_requests)
00217 goto receive_rest;
00218 start_request(caller, reqh, i);
00219 if (interval > 0)
00220 gwthread_sleep(interval);
00221 ++in_queue;
00222 if (receive_reply(caller) == -1)
00223 ++failed;
00224 else
00225 ++succeeded;
00226 --in_queue;
00227 }
00228
00229 receive_rest:
00230 while (in_queue > 0) {
00231 if (receive_reply(caller) == -1)
00232 ++failed;
00233 else
00234 ++succeeded;
00235 --in_queue;
00236 }
00237
00238 counter_destroy(counter);
00239 http_destroy_headers(reqh);
00240 http_caller_destroy(caller);
00241 info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
00242 }
00243
00244
00245 static void split_headers(Octstr *headers, List **split)
00246 {
00247 long start;
00248 long pos;
00249
00250 *split = gwlist_create();
00251 start = 0;
00252 for (pos = 0; pos < octstr_len(headers); pos++) {
00253 if (octstr_get_char(headers, pos) == '\n') {
00254 Octstr *line;
00255
00256 if (pos == start) {
00257
00258 start = pos + 1;
00259 continue;
00260 }
00261 line = octstr_copy(headers, start, pos - start);
00262 start = pos + 1;
00263 gwlist_append(*split, line);
00264 }
00265 }
00266 }
00267
00268
00269 static void help(void)
00270 {
00271 info(0, "Usage: test_http [options] url ...");
00272 info(0, "where options are:");
00273 info(0, "-v number");
00274 info(0, " set log level for stderr logging");
00275 info(0, "-q");
00276 info(0, " don't print the body or headers of the HTTP response");
00277 info(0, "-r number");
00278 info(0, " make `number' requests, repeating URLs as necessary");
00279 info(0, "-t number");
00280 info(0, " run `number' threads, that make -r `number' requests");
00281 info(0, "-i interval");
00282 info(0, " make one request in `interval' seconds");
00283 info(0, "-p domain.name");
00284 info(0, " use `domain.name' as a proxy");
00285 info(0, "-P portnumber");
00286 info(0, " connect to proxy at port `portnumber'");
00287 info(0, "-S");
00288 info(0, " use HTTPS scheme to access SSL-enabled proxy server");
00289 info(0, "-e domain1:domain2:...");
00290 info(0, " set exception list for proxy use");
00291 info(0, "-u filename");
00292 info(0, " read request's &text= string from file 'filename'. It is");
00293 info(0, " url encoded before it is added to the request");
00294 info(0, "-H filename");
00295 info(0, " read HTTP headers from file 'filename' and add them to");
00296 info(0, " the request for url 'url'");
00297 info(0, "-B filename");
00298 info(0, " read content from file 'filename' and send it as body");
00299 info(0, " of a POST method request (default: GET if no -B is set)");
00300 info(0, "-m method");
00301 info(0, " use a specific HTTP method for request to server");
00302 info(0, "-s");
00303 info(0, " use HTTPS scheme to access SSL-enabled HTTP server");
00304 info(0, "-c ssl_client_cert_key_file");
00305 info(0, " use this file as the SSL certificate and key file");
00306 }
00307
00308 int main(int argc, char **argv)
00309 {
00310 int i, opt, num_threads;
00311 Octstr *proxy;
00312 List *exceptions;
00313 long proxy_port;
00314 int proxy_ssl = 0;
00315 Octstr *proxy_username;
00316 Octstr *proxy_password;
00317 Octstr *exceptions_regex;
00318 char *p;
00319 long threads[MAX_THREADS];
00320 time_t start, end;
00321 double run_time;
00322 FILE *fp;
00323 int ssl = 0;
00324
00325 gwlib_init();
00326
00327 proxy = NULL;
00328 proxy_port = -1;
00329 exceptions = gwlist_create();
00330 proxy_username = NULL;
00331 proxy_password = NULL;
00332 exceptions_regex = NULL;
00333 num_threads = 1;
00334 file = 0;
00335 fp = NULL;
00336
00337 while ((opt = getopt(argc, argv, "hv:qr:p:P:Se:t:i:a:u:sc:H:B:m:")) != EOF) {
00338 switch (opt) {
00339 case 'v':
00340 log_set_output_level(atoi(optarg));
00341 break;
00342
00343 case 'q':
00344 verbose = 0;
00345 break;
00346
00347 case 'r':
00348 max_requests = atoi(optarg);
00349 break;
00350
00351 case 't':
00352 num_threads = atoi(optarg);
00353 if (num_threads > MAX_THREADS)
00354 num_threads = MAX_THREADS;
00355 break;
00356
00357 case 'i':
00358 interval = atof(optarg);
00359 break;
00360
00361 case 'u':
00362 file = 1;
00363 fp = fopen(optarg, "a");
00364 if (fp == NULL)
00365 panic(0, "Cannot open message text file %s", optarg);
00366 msg_text = octstr_read_file(optarg);
00367 if (msg_text == NULL)
00368 panic(0, "Cannot read message text");
00369 debug("", 0, "message text is");
00370 octstr_dump(msg_text, 0);
00371 octstr_url_encode(msg_text);
00372 fclose(fp);
00373 break;
00374
00375 case 'h':
00376 help();
00377 exit(0);
00378
00379 case 'p':
00380 proxy = octstr_create(optarg);
00381 break;
00382
00383 case 'P':
00384 proxy_port = atoi(optarg);
00385 break;
00386
00387 case 'S':
00388 proxy_ssl = 1;
00389 break;
00390
00391 case 'e':
00392 p = strtok(optarg, ":");
00393 while (p != NULL) {
00394 gwlist_append(exceptions, octstr_create(p));
00395 p = strtok(NULL, ":");
00396 }
00397 break;
00398
00399 case 'E':
00400 exceptions_regex = octstr_create(optarg);
00401 break;
00402
00403 case 'a':
00404 p = strtok(optarg, ":");
00405 if (p != NULL) {
00406 auth_username = octstr_create(p);
00407 p = strtok(NULL, "");
00408 if (p != NULL)
00409 auth_password = octstr_create(p);
00410 }
00411 break;
00412
00413 case 's':
00414 ssl = 1;
00415 break;
00416
00417 case 'c':
00418 octstr_destroy(ssl_client_certkey_file);
00419 ssl_client_certkey_file = octstr_create(optarg);
00420 break;
00421
00422 case 'H':
00423 fp = fopen(optarg, "a");
00424 if (fp == NULL)
00425 panic(0, "Cannot open header text file %s", optarg);
00426 extra_headers = octstr_read_file(optarg);
00427 if (extra_headers == NULL)
00428 panic(0, "Cannot read header text");
00429 debug("", 0, "headers are");
00430 octstr_dump(extra_headers, 0);
00431 split_headers(extra_headers, &split);
00432 fclose(fp);
00433 break;
00434
00435 case 'B':
00436 content_file = octstr_create(optarg);
00437 break;
00438
00439 case 'm':
00440 method_name = octstr_create(optarg);
00441 break;
00442
00443 case '?':
00444 default:
00445 error(0, "Invalid option %c", opt);
00446 help();
00447 panic(0, "Stopping.");
00448 }
00449 }
00450
00451 if (optind == argc) {
00452 help();
00453 exit(0);
00454 }
00455
00456 #ifdef HAVE_LIBSSL
00457
00458
00459
00460
00461 if (ssl || proxy_ssl) {
00462 if (ssl_client_certkey_file != NULL) {
00463 use_global_client_certkey_file(ssl_client_certkey_file);
00464 } else {
00465 panic(0, "client certkey file need to be given!");
00466 }
00467 }
00468 #endif
00469
00470 if (method_name != NULL) {
00471 method = http_name2method(method_name);
00472 }
00473
00474 if (proxy != NULL && proxy_port > 0) {
00475 http_use_proxy(proxy, proxy_port, proxy_ssl, exceptions,
00476 proxy_username, proxy_password, exceptions_regex);
00477 }
00478 octstr_destroy(proxy);
00479 octstr_destroy(proxy_username);
00480 octstr_destroy(proxy_password);
00481 octstr_destroy(exceptions_regex);
00482 gwlist_destroy(exceptions, octstr_destroy_item);
00483
00484 urls = argv + optind;
00485 num_urls = argc - optind;
00486
00487 time(&start);
00488 if (num_threads == 1)
00489 client_thread(http_caller_create());
00490 else {
00491 for (i = 0; i < num_threads; ++i)
00492 threads[i] = gwthread_create(client_thread, http_caller_create());
00493 for (i = 0; i < num_threads; ++i)
00494 gwthread_join(threads[i]);
00495 }
00496 time(&end);
00497
00498 run_time = difftime(end, start);
00499 info(0, "%ld requests in %f seconds, %f requests/s.",
00500 (max_requests * num_threads), run_time, (max_requests * num_threads) / run_time);
00501
00502 octstr_destroy(ssl_client_certkey_file);
00503 octstr_destroy(auth_username);
00504 octstr_destroy(auth_password);
00505 octstr_destroy(extra_headers);
00506 octstr_destroy(content_file);
00507 gwlist_destroy(split, octstr_destroy_item);
00508
00509 gwlib_shutdown();
00510
00511 return 0;
00512 }
00513
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.