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 <signal.h>
00067
00068 #include "gwlib/gwlib.h"
00069 #include "gwlib/http.h"
00070
00071 #define MAX_THREADS 1024
00072
00073 Octstr *whitelist, *blacklist;
00074 Octstr *reply_text = NULL;
00075
00076 int verbose, run, port;
00077 int ssl = 0;
00078
00079 static void client_thread(void *arg)
00080 {
00081 HTTPClient *client;
00082 Octstr *body, *url, *ip;
00083 List *headers, *resph, *cgivars;
00084 HTTPCGIVar *v;
00085 Octstr *reply_body, *reply_type;
00086 unsigned long n = 0;
00087 int status, i;
00088
00089 while (run) {
00090 client = http_accept_request(port, &ip, &url, &headers, &body, &cgivars);
00091
00092 n++;
00093 if (client == NULL)
00094 break;
00095
00096 info(0, "Request for <%s> from <%s>",
00097 octstr_get_cstr(url), octstr_get_cstr(ip));
00098 if (verbose)
00099 debug("test.http", 0, "CGI vars were");
00100
00101
00102
00103
00104
00105 for (i = 0; i < gwlist_len(cgivars); i++) {
00106 if ((v = gwlist_get(cgivars, i)) != NULL && verbose) {
00107 octstr_dump(v->name, 0);
00108 octstr_dump(v->value, 0);
00109 }
00110 }
00111
00112 if (arg == NULL) {
00113 reply_body = octstr_duplicate(reply_text);
00114 reply_type = octstr_create("Content-Type: text/plain; "
00115 "charset=\"UTF-8\"");
00116 } else {
00117 reply_body = octstr_duplicate(arg);
00118 reply_type = octstr_create("Content-Type: text/vnd.wap.wml");
00119 }
00120
00121 resph = gwlist_create();
00122 gwlist_append(resph, reply_type);
00123
00124 status = HTTP_OK;
00125
00126
00127 if (octstr_compare(url, octstr_imm("/quit")) == 0) {
00128 run = 0;
00129 } else if (octstr_compare(url, octstr_imm("/whitelist")) == 0) {
00130 octstr_destroy(reply_body);
00131 if (whitelist != NULL) {
00132 if (verbose) {
00133 debug("test.http.server", 0, "we send a white list");
00134 octstr_dump(whitelist, 0);
00135 }
00136 reply_body = octstr_duplicate(whitelist);
00137 } else {
00138 reply_body = octstr_imm("");
00139 }
00140 } else if (octstr_compare(url, octstr_imm("/blacklist")) == 0) {
00141 octstr_destroy(reply_body);
00142 if (blacklist != NULL) {
00143 if (verbose) {
00144 debug("test.http.server", 0, "we send a blacklist");
00145 octstr_dump(blacklist, 0);
00146 }
00147 reply_body = octstr_duplicate(blacklist);
00148 } else {
00149 reply_body = octstr_imm("");
00150 }
00151 } else if (octstr_compare(url, octstr_imm("/save")) == 0) {
00152
00153 pid_t pid = getpid();
00154 FILE *f = fopen(octstr_get_cstr(octstr_format("/tmp/body.%ld.%ld", pid, n)), "w");
00155 octstr_print(f, body);
00156 fclose(f);
00157 } else if (octstr_compare(url, octstr_imm("/redirect/")) == 0) {
00158
00159
00160
00161
00162 Octstr *redirect_header, *scheme, *uri, *l;
00163 pid_t pid = getpid();
00164
00165 uri = ((l = http_cgi_variable(cgivars, "loop")) != NULL) ?
00166 octstr_format("%s?loop=%s", octstr_get_cstr(url),
00167 octstr_get_cstr(l)) :
00168 octstr_format("%s%ld", octstr_get_cstr(url), pid);
00169
00170 octstr_destroy(reply_body);
00171 reply_body = octstr_imm("Here you got a redirection URL that you should follow.");
00172 scheme = ssl ? octstr_imm("https://") : octstr_imm("http://");
00173 redirect_header = octstr_format("Location: %s%s%s",
00174 octstr_get_cstr(scheme),
00175 octstr_get_cstr(http_header_value(headers, octstr_imm("Host"))),
00176 octstr_get_cstr(uri));
00177 gwlist_append(resph, redirect_header);
00178 status = HTTP_FOUND;
00179 octstr_destroy(uri);
00180 } else if (octstr_compare(url, octstr_imm("/mmsc")) == 0) {
00181
00182 pid_t pid = getpid();
00183 FILE *f;
00184 gwlist_destroy(resph, octstr_destroy_item);
00185 octstr_destroy(reply_body);
00186 reply_type = octstr_create("Content-Type: application/vnd.wap.mms-message");
00187 reply_body = octstr_create("");
00188 octstr_append_from_hex(reply_body,
00189 "8c81"
00190 "98632d3862343300"
00191 "8d90"
00192 "9280"
00193 "8b313331373939353434393639383434313731323400"
00194 );
00195 resph = gwlist_create();
00196 gwlist_append(resph, reply_type);
00197
00198 f = fopen(octstr_get_cstr(octstr_format("/tmp/mms-body.%ld.%ld", pid, n)), "w");
00199 octstr_print(f, body);
00200 fclose(f);
00201 }
00202
00203 if (verbose) {
00204 debug("test.http", 0, "request headers were");
00205 http_header_dump(headers);
00206 if (body != NULL) {
00207 debug("test.http", 0, "request body was");
00208 octstr_dump(body, 0);
00209 }
00210 }
00211
00212
00213 http_send_reply(client, status, resph, reply_body);
00214
00215 octstr_destroy(ip);
00216 octstr_destroy(url);
00217 octstr_destroy(body);
00218 octstr_destroy(reply_body);
00219 http_destroy_cgiargs(cgivars);
00220 gwlist_destroy(headers, octstr_destroy_item);
00221 gwlist_destroy(resph, octstr_destroy_item);
00222 }
00223
00224 octstr_destroy(whitelist);
00225 octstr_destroy(blacklist);
00226 debug("test.http", 0, "Working thread 'client_thread' terminates");
00227 http_close_all_ports();
00228 }
00229
00230 static void help(void) {
00231 info(0, "Usage: test_http_server [options...]");
00232 info(0, "where options are:");
00233 info(0, "-t number");
00234 info(0, " set number of working threads to use (default: 1)");
00235 info(0, "-v number");
00236 info(0, " set log level for stderr logging (default: 0 - debug)");
00237 info(0, "-l logfile");
00238 info(0, " log all output to a file");
00239 info(0, "-f file");
00240 info(0, " use a specific file content for the response body");
00241 info(0, "-r reply_text");
00242 info(0, " defines which static text to use for replies");
00243 info(0, "-h");
00244 info(0, " provides this usage help information");
00245 info(0, "-q");
00246 info(0, " don't be too verbose with output");
00247 info(0, "-p port");
00248 info(0, " bind server to a specific port");
00249 info(0, "-s");
00250 info(0, " be an SSL-enabled server");
00251 info(0, "-c ssl_cert");
00252 info(0, " file of the SSL certificate to use");
00253 info(0, "-k ssl_key");
00254 info(0, " file of the SSL private key to use");
00255 info(0, "-w white_list");
00256 info(0, " file that is used for whitelist");
00257 info(0, "-b black_list");
00258 info(0, " file that is used for blacklist");
00259 info(0, "specific URIs with special functions are:");
00260 info(0, " /quite - shutdown the HTTP server");
00261 info(0, " /whitelist - provides the -w whitelist as response");
00262 info(0, " /blacklist - provides the -b blacklist as response");
00263 info(0, " /save - save a HTTP POST request body to a file /tmp/body.<pid>.<n>");
00264 info(0, " where <pid> is the process id and <n> is the received request number");
00265 info(0, " /redirect/ - respond with HTTP 302 and the location /redirect/<pid>");
00266 info(0, " where <pid> is the process id. if a cgivar loop=<something> is given");
00267 info(0, " then HTTP reponses will end up in a loop.");
00268 info(0, " /mmsc - fake a MMSC HTTP interface for M-Send.req PDUs send by a");
00269 info(0, " mobile MMS-capable device, responds with a M-Send.conf PDU and");
00270 info(0, " saves the M-Send.req body to a file /tmp/mms-body.<pid>.<n> in");
00271 info(0, " MMSEncapsulation encoded binary format");
00272
00273 }
00274
00275 static void sigterm(int signo) {
00276 run = 0;
00277 http_close_all_ports();
00278 debug("test.gwlib", 0, "Signal %d received, quitting.", signo);
00279 }
00280
00281 int main(int argc, char **argv) {
00282 int i, opt, use_threads;
00283 struct sigaction act;
00284 char *filename;
00285 Octstr *log_filename;
00286 Octstr *file_contents;
00287 #ifdef HAVE_LIBSSL
00288 Octstr *ssl_server_cert_file = NULL;
00289 Octstr *ssl_server_key_file = NULL;
00290 #endif
00291 char *whitelist_name;
00292 char *blacklist_name;
00293 int white_asked,
00294 black_asked;
00295 long threads[MAX_THREADS];
00296
00297 gwlib_init();
00298
00299 act.sa_handler = sigterm;
00300 sigemptyset(&act.sa_mask);
00301 act.sa_flags = 0;
00302 sigaction(SIGTERM, &act, NULL);
00303
00304 port = 8080;
00305 use_threads = 1;
00306 verbose = 1;
00307 run = 1;
00308 filename = NULL;
00309 log_filename = NULL;
00310 blacklist_name = NULL;
00311 whitelist_name = NULL;
00312 white_asked = 0;
00313 black_asked = 0;
00314
00315 reply_text = octstr_create("Sent.");
00316
00317 while ((opt = getopt(argc, argv, "hqv:p:t:f:l:sc:k:b:w:r:")) != EOF) {
00318 switch (opt) {
00319 case 'v':
00320 log_set_output_level(atoi(optarg));
00321 break;
00322
00323 case 'q':
00324 verbose = 0;
00325 break;
00326
00327 case 'h':
00328 help();
00329 exit(0);
00330
00331 case 'p':
00332 port = atoi(optarg);
00333 break;
00334
00335 case 't':
00336 use_threads = atoi(optarg);
00337 if (use_threads > MAX_THREADS)
00338 use_threads = MAX_THREADS;
00339 break;
00340
00341 case 'c':
00342 #ifdef HAVE_LIBSSL
00343 octstr_destroy(ssl_server_cert_file);
00344 ssl_server_cert_file = octstr_create(optarg);
00345 #endif
00346 break;
00347
00348 case 'k':
00349 #ifdef HAVE_LIBSSL
00350 octstr_destroy(ssl_server_key_file);
00351 ssl_server_key_file = octstr_create(optarg);
00352 #endif
00353 break;
00354
00355 case 's':
00356 #ifdef HAVE_LIBSSL
00357 ssl = 1;
00358 #endif
00359 break;
00360
00361 case 'f':
00362 filename = optarg;
00363 break;
00364
00365 case 'l':
00366 octstr_destroy(log_filename);
00367 log_filename = octstr_create(optarg);
00368 break;
00369
00370 case 'w':
00371 whitelist_name = optarg;
00372 if (whitelist_name == NULL)
00373 whitelist_name = "";
00374 white_asked = 1;
00375 break;
00376
00377 case 'b':
00378 blacklist_name = optarg;
00379 if (blacklist_name == NULL)
00380 blacklist_name = "";
00381 black_asked = 1;
00382 break;
00383
00384 case 'r':
00385 octstr_destroy(reply_text);
00386 reply_text = octstr_create(optarg);
00387 break;
00388
00389 case '?':
00390 default:
00391 error(0, "Invalid option %c", opt);
00392 help();
00393 panic(0, "Stopping.");
00394 }
00395 }
00396
00397 if (log_filename != NULL) {
00398 log_open(octstr_get_cstr(log_filename), GW_DEBUG, GW_NON_EXCL);
00399 octstr_destroy(log_filename);
00400 }
00401
00402 if (filename == NULL)
00403 file_contents = NULL;
00404 else
00405 file_contents = octstr_read_file(filename);
00406
00407 if (white_asked) {
00408 whitelist = octstr_read_file(whitelist_name);
00409 if (whitelist == NULL)
00410 panic(0, "Cannot read the whitelist");
00411 }
00412
00413 if (black_asked) {
00414 blacklist = octstr_read_file(blacklist_name);
00415 if (blacklist == NULL)
00416 panic(0, "Cannot read the blacklist");
00417 }
00418
00419 #ifdef HAVE_LIBSSL
00420
00421
00422
00423
00424 if (ssl) {
00425 if (ssl_server_cert_file != NULL && ssl_server_key_file != NULL) {
00426 use_global_server_certkey_file(ssl_server_cert_file, ssl_server_key_file);
00427 octstr_destroy(ssl_server_cert_file);
00428 octstr_destroy(ssl_server_key_file);
00429 } else {
00430 panic(0, "certificate and public key need to be given!");
00431 }
00432 }
00433 #endif
00434
00435 if (http_open_port(port, ssl) == -1)
00436 panic(0, "http_open_server failed");
00437
00438
00439
00440
00441
00442 for (i = 0; i < use_threads; ++i)
00443 threads[i] = gwthread_create(client_thread, file_contents);
00444
00445
00446 for (i = 0; i < use_threads; ++i)
00447 gwthread_join(threads[i]);
00448
00449 debug("test.http", 0, "Program exiting normally.");
00450 gwlib_shutdown();
00451 return 0;
00452 }
00453
00454
00455
00456
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.