Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

test_http_server.c File Reference

#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "gwlib/gwlib.h"
#include "gwlib/http.h"

Include dependency graph for test_http_server.c:

Include dependency graph

Go to the source code of this file.

Defines

#define MAX_THREADS   1024

Functions

void client_thread (void *arg)
void help (void)
void sigterm (int signo)
int main (int argc, char **argv)

Variables

Octstrwhitelist
Octstrblacklist
Octstrreply_text = NULL
int verbose
int run
int port
int ssl = 0


Define Documentation

#define MAX_THREADS   1024
 

Definition at line 71 of file test_http_server.c.


Function Documentation

void client_thread void *  arg  )  [static]
 

Definition at line 79 of file test_http_server.c.

References blacklist, debug(), gwlist_append(), gwlist_create, gwlist_destroy(), gwlist_get(), gwlist_len(), http_accept_request(), http_cgi_variable(), http_close_all_ports(), http_destroy_cgiargs(), http_header_dump(), http_header_value(), http_send_reply(), info(), HTTPCGIVar::name, octstr_append_from_hex(), octstr_compare(), octstr_create, octstr_destroy(), octstr_destroy_item(), octstr_dump, octstr_duplicate, octstr_format(), octstr_get_cstr, octstr_imm(), octstr_print(), port, reply_text, run, ssl, HTTPCGIVar::value, and whitelist.

Referenced by main().

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          * Don't use gwlist_extract() here, otherwise we don't have a chance
00103          * to re-use the cgivars later on.
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         /* check for special URIs and handle those */
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             /* safe the body into a temporary file */
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             /* provide us with a HTTP 302 redirection response
00159              * will return /redirect/<pid> for the location header 
00160              * and will return /redirect/ if cgivar loop is set to allow looping
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; /* will provide 302 */
00179             octstr_destroy(uri);
00180         } else if (octstr_compare(url, octstr_imm("/mmsc")) == 0) {
00181             /* fake a M-Send.conf PDU which is using MMSEncapsulation as body */
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"              /* X-Mms-Message-Type: m-send-conf */
00190                 "98632d3862343300"  /* X-Mms-Transaction-ID: c-8b43 */
00191                 "8d90"              /* X-Mms-MMS-Version: 1.0 */
00192                 "9280"              /* Response-status: Ok */
00193                 "8b313331373939353434393639383434313731323400"
00194             );                      /* Message-Id: 13179954496984417124 */
00195             resph = gwlist_create();
00196             gwlist_append(resph, reply_type);
00197             /* safe the M-Send.req body into a temporary file */
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         /* return response to client */
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 }

Here is the call graph for this function:

void help void   )  [static]
 

Definition at line 230 of file test_http_server.c.

References info().

00230                        {
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 }

Here is the call graph for this function:

int main int  argc,
char **  argv
 

Definition at line 281 of file test_http_server.c.

References blacklist, client_thread(), debug(), error(), filename, getopt(), GW_DEBUG, GW_NON_EXCL, gwlib_init(), gwlib_shutdown(), gwthread_create, gwthread_join(), help(), http_open_port(), log_open(), log_set_output_level(), octstr_create, octstr_destroy(), octstr_get_cstr, octstr_read_file(), optarg, panic, port, reply_text, run, ssl, threads, use_global_server_certkey_file(), verbose, and whitelist.

00281                                 {
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      * check if we are doing a SSL-enabled server version here
00422      * load the required cert and key file
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      * Do the real work in a separate thread so that the main
00440      * thread can catch signals safely.
00441      */
00442     for (i = 0; i < use_threads; ++i) 
00443         threads[i] = gwthread_create(client_thread, file_contents);
00444 
00445     /* wait for all working threads */
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 }

Here is the call graph for this function:

void sigterm int  signo  )  [static]
 

Definition at line 275 of file test_http_server.c.

References debug(), http_close_all_ports(), and run.

00275                                {
00276     run = 0;
00277     http_close_all_ports();
00278     debug("test.gwlib", 0, "Signal %d received, quitting.", signo);
00279 }

Here is the call graph for this function:


Variable Documentation

Octstr * blacklist
 

Definition at line 73 of file test_http_server.c.

Referenced by client_thread(), and main().

int port
 

Definition at line 76 of file test_http_server.c.

Octstr* reply_text = NULL
 

Definition at line 74 of file test_http_server.c.

Referenced by client_thread(), and main().

int run
 

Definition at line 76 of file test_http_server.c.

Referenced by client_thread(), main(), and sigterm().

int ssl = 0
 

Definition at line 77 of file test_http_server.c.

Referenced by accept_boxc(), boxc_create(), client_thread(), conn_pool_get(), conn_pool_key(), conn_pool_put(), connect_to_bearerbox(), get_connection(), http_open_port(), httpadmin_start(), httpd_emu_create(), init_smsbox(), main(), server_thread(), smsc_http_create(), SSL_smart_shutdown(), start_http_thread(), and wait_for_connections().

int verbose
 

Definition at line 76 of file test_http_server.c.

Octstr* whitelist
 

Definition at line 73 of file test_http_server.c.

Referenced by client_thread(), and main().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.