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

test_xmlrpc.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * test_xmlrpc.c: A simple program to test XML-RPC parsing
00059  *
00060  * Stipe Tolj <stolj@wapme.de>
00061  */
00062 
00063 
00064 #include <string.h>
00065 #include <stdlib.h>
00066 #include <unistd.h>
00067 #include <stdio.h>
00068 
00069 #include "gwlib/gwlib.h"
00070 #include "gwlib/http.h"
00071 #include "gwlib/xmlrpc.h"
00072 
00073 #define MAX_THREADS 1024
00074 #define MAX_IN_QUEUE 128
00075 
00076 static Counter *counter = NULL; 
00077 static long max_requests = 1;
00078 /*static int verbose = 1;*/
00079 static Octstr *auth_username = NULL;
00080 static Octstr *auth_password = NULL;
00081 static Octstr *ssl_client_certkey_file = NULL;
00082 static Octstr *extra_headers = NULL;
00083 static Octstr *content_file = NULL;
00084 static Octstr *url = NULL;
00085 static int file = 0;
00086 static XMLRPCDocument *msg;
00087 
00088 
00089 static void start_request(HTTPCaller *caller, List *reqh, long i)
00090 {
00091     long *id;
00092     int ret;
00093 
00094     if ((i % 1000) == 0)
00095        info(0, "Starting fetch %ld", i);
00096     id = gw_malloc(sizeof(long));
00097     *id = i;
00098                            
00099     /*
00100      * not semd the XML-RPC document contained in msg to
00101      * the URL 'url' using the POST method
00102      */
00103     ret = xmlrpc_send_call(msg, caller, url, reqh, id);
00104 
00105     debug("", 0, "Started request %ld.", *id);
00106     /*
00107     debug("", 0, "Started request %ld with url:", *id);
00108     octstr_url_decode(url);
00109     octstr_dump(url, 0);
00110     */
00111 }
00112 
00113 
00114 static int receive_reply(HTTPCaller *caller)
00115 {
00116     void *id;
00117     int ret;
00118     Octstr *final_url;
00119     List *replyh;
00120     Octstr *replyb;
00121     Octstr *output;
00122     XMLRPCDocument *xrdoc;
00123     /*
00124     Octstr *type, *os_xrdoc, *os;
00125     Octstr *charset;
00126     */
00127     
00128     id = http_receive_result(caller, &ret, &final_url, &replyh, &replyb);
00129     octstr_destroy(final_url);
00130     if (id == NULL || ret == -1) {
00131         error(0, "http POST failed");
00132         gw_free(id);
00133         return -1;
00134     }
00135     debug("", 0, "Done with request %ld", *(long *) id);
00136     gw_free(id);
00137 
00138 /*
00139     http_header_get_content_type(replyh, &type, &charset);
00140     debug("", 0, "Content-type is <%s>, charset is <%s>",
00141           octstr_get_cstr(type), octstr_get_cstr(charset));
00142     octstr_destroy(type);
00143     octstr_destroy(charset);
00144     if (verbose)
00145         debug("", 0, "Reply headers:");
00146     while ((os = gwlist_extract_first(replyh)) != NULL) {
00147         if (verbose)
00148             octstr_dump(os, 1);
00149         octstr_destroy(os);
00150     }
00151     if (verbose) {
00152         debug("", 0, "Reply body:");
00153         octstr_dump(replyb, 1);
00154     }
00155 */
00156     xrdoc = xmlrpc_parse_response(replyb);
00157     debug("", 0, "Parsed xmlrpc");
00158     
00159     if ((xmlrpc_parse_status(xrdoc) != XMLRPC_COMPILE_OK) && 
00160         ((output = xmlrpc_parse_error(xrdoc)) != NULL)) {
00161         /* parse failure */
00162         error(0, "%s", octstr_get_cstr(output));
00163         octstr_destroy(output);
00164         return -1;
00165     } else { 
00166         /*parse proper xmlrpc */
00167         if (xmlrpc_is_fault(xrdoc)) {
00168             Octstr *fstring = xmlrpc_get_faultstring(xrdoc);
00169             debug("xr", 0, "Got fault response with code:%ld and description: %s",
00170                            xmlrpc_get_faultcode(xrdoc),
00171                            octstr_get_cstr(fstring));
00172             octstr_destroy(fstring);
00173             http_destroy_headers(replyh);
00174             octstr_destroy(replyb);
00175             return -1;
00176         } 
00177         /*
00178         os_xrdoc = xmlrpc_print_response(xrdoc);
00179         debug("xr", 0, "XMLRPC response:");
00180         octstr_dump(os_xrdoc, 0);
00181         */
00182     }
00183     http_destroy_headers(replyh);
00184     octstr_destroy(replyb);
00185     return 0;
00186 }
00187 
00188 
00189 static void client_thread(void *arg) 
00190 {
00191     List *reqh;
00192     long i, succeeded, failed;
00193     HTTPCaller *caller;
00194     char buf[1024];
00195     long in_queue;
00196 
00197     caller = arg;
00198     succeeded = 0;
00199     failed = 0;
00200     reqh = gwlist_create();
00201 
00202     sprintf(buf, "%ld", (long) gwthread_self());
00203     http_header_add(reqh, "X-Thread", buf);
00204     if (auth_username != NULL && auth_password != NULL)
00205         http_add_basic_auth(reqh, auth_username, auth_password);
00206 
00207     in_queue = 0;
00208     
00209     for (;;) {
00210         while (in_queue < MAX_IN_QUEUE) {
00211             i = counter_increase(counter);
00212             if (i >= max_requests)
00213                 goto receive_rest;
00214             start_request(caller, reqh, i);
00215 #if 1
00216             gwthread_sleep(0.1);
00217 #endif
00218             ++in_queue;
00219         }
00220         while (in_queue >= MAX_IN_QUEUE) {
00221             if (receive_reply(caller) == -1)
00222                 ++failed;
00223             else
00224                 ++succeeded;
00225             --in_queue;
00226         }
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     http_caller_destroy(caller);
00239     info(0, "This thread: %ld succeeded, %ld failed.", succeeded, failed);
00240 }
00241 
00242 
00243 static void help(void) 
00244 {
00245     info(0, "Usage: test_xmlrpc [options] xml_source");
00246     info(0, "where options are:");
00247     info(0, "-u URL");
00248     info(0, "    send XML-RPC source as POST HTTP request to URL");
00249     info(0, "-v number");
00250     info(0, "    set log level for stderr logging");
00251     info(0, "-q");
00252     info(0, "    don't print the body or headers of the HTTP response");
00253     info(0, "-r number");
00254     info(0, "    make `number' requests, repeating URLs as necessary");
00255     info(0, "-p domain.name");
00256     info(0, "    use `domain.name' as a proxy");
00257     info(0, "-P portnumber");
00258     info(0, "    connect to proxy at port `portnumber'");
00259     info(0, "-S");
00260     info(0, "    use HTTPS scheme to access SSL-enabled proxy server");
00261     info(0, "-e domain1:domain2:...");
00262     info(0, "    set exception list for proxy use");
00263     info(0, "-s");
00264     info(0, "    use HTTPS scheme to access SSL-enabled HTTP server");
00265     info(0, "-c ssl_client_cert_key_file");
00266     info(0, "    use this file as the SSL certificate and key file");
00267 }
00268 
00269 
00270 int main(int argc, char **argv)
00271 {
00272     int i, opt, num_threads;
00273     Octstr *proxy;
00274     List *exceptions;
00275     long proxy_port;
00276     int proxy_ssl = 0;
00277     Octstr *proxy_username;
00278     Octstr *proxy_password;
00279     Octstr *exceptions_regex;
00280     char *p;
00281     long threads[MAX_THREADS];
00282     time_t start, end;
00283     double run_time;
00284     FILE *fp;
00285     Octstr *output, *xml_doc; 
00286     int ssl = 0;
00287     
00288     gwlib_init();
00289 
00290     proxy = NULL;
00291     proxy_port = -1;
00292     exceptions = gwlist_create();
00293     proxy_username = NULL;
00294     proxy_password = NULL;
00295     exceptions_regex = NULL;
00296     num_threads = 0;
00297     file = 0;
00298     fp = NULL;
00299     
00300     while ((opt = getopt(argc, argv, "hvr:t:p:u:P:Se:a:sc:")) != EOF) {
00301         switch (opt) {
00302             case 'h':
00303                 help();
00304                 exit(1);
00305                 break;
00306 
00307             case 'v':
00308                 log_set_output_level(atoi(optarg));
00309                 break;
00310 
00311             case 'r':
00312                 max_requests = atoi(optarg);
00313                 break;
00314     
00315             case 't':
00316                 num_threads = atoi(optarg);
00317                 if (num_threads > MAX_THREADS)
00318                     num_threads = MAX_THREADS;
00319                 break;
00320 
00321             case 'p':
00322                 proxy = octstr_create(optarg);
00323                 break;
00324 
00325             case 'u':
00326                 url = octstr_create(optarg);
00327                 break;
00328     
00329             case 'P':
00330                 proxy_port = atoi(optarg);
00331                 break;
00332                 
00333             case 'S':
00334                 proxy_ssl = 1;
00335                 break;
00336     
00337             case 'e':
00338                 p = strtok(optarg, ":");
00339                 while (p != NULL) {
00340                     gwlist_append(exceptions, octstr_create(p));
00341                     p = strtok(NULL, ":");
00342                 }
00343                 break;
00344 
00345             case 'E':
00346                 exceptions_regex = octstr_create(optarg);
00347                 break;
00348     
00349             case 'a':
00350                 p = strtok(optarg, ":");
00351                 if (p != NULL) {
00352                     auth_username = octstr_create(p);
00353                     p = strtok(NULL, "");
00354                     if (p != NULL)
00355                         auth_password = octstr_create(p);
00356                 }
00357                 break;
00358 
00359             case 's':
00360                 ssl = 1;
00361                 break;
00362 
00363             case 'c':
00364                octstr_destroy(ssl_client_certkey_file);
00365                ssl_client_certkey_file = octstr_create(optarg);
00366                 break;
00367 
00368             case '?':
00369             default:
00370                 error(0, "Invalid option %c", opt);
00371                 help();
00372                 panic(0, "Stopping");
00373                 break;
00374         }
00375     }
00376 
00377     if (optind >= argc) {
00378         error(0, "Missing arguments");
00379         help();
00380         panic(0, "Stopping");
00381     }
00382 
00383 #ifdef HAVE_LIBSSL
00384     /*
00385      * check if we are doing a SSL-enabled client version here
00386      * load the required cert and key file
00387      */
00388     if (ssl || proxy_ssl) {
00389         if (ssl_client_certkey_file != NULL) {
00390             use_global_client_certkey_file(ssl_client_certkey_file);
00391         } else {
00392             panic(0, "client certkey file need to be given!");
00393         }
00394     }
00395 #endif
00396 
00397     if (proxy != NULL && proxy_port > 0) {
00398         http_use_proxy(proxy, proxy_port, proxy_ssl, exceptions,
00399                        proxy_username, proxy_password,
00400                        exceptions_regex);
00401     }
00402     octstr_destroy(proxy);
00403     octstr_destroy(proxy_username);
00404     octstr_destroy(proxy_password);
00405     octstr_destroy(exceptions_regex);
00406     gwlist_destroy(exceptions, octstr_destroy_item);
00407     
00408     counter = counter_create();
00409 
00410     xml_doc = octstr_read_file(argv[optind]);
00411     if (xml_doc == NULL)
00412         panic(0, "Cannot read the XML document");
00413 
00414     /*
00415      * parse the XML source
00416      */
00417     msg = xmlrpc_parse_call(xml_doc);
00418 
00419     if ((xmlrpc_parse_status(msg) != XMLRPC_COMPILE_OK) && 
00420         ((output = xmlrpc_parse_error(msg)) != NULL)) {
00421         /* parse failure */
00422         error(0, "%s", octstr_get_cstr(output));
00423         octstr_destroy(output);
00424     }
00425 
00426     /*
00427      * if no POST is desired then dump the re-formated XML
00428      */
00429     if (url != NULL) {
00430         
00431         time(&start);
00432         if (num_threads == 0)
00433            client_thread(http_caller_create());
00434         else {
00435             for (i = 0; i < num_threads; ++i)
00436                 threads[i] = gwthread_create(client_thread, http_caller_create());
00437             for (i = 0; i < num_threads; ++i)
00438                 gwthread_join(threads[i]);
00439         }
00440         time(&end);
00441     
00442     
00443         run_time = difftime(end, start);
00444         info(0, "%ld requests in %f seconds, %f requests/s.",
00445              max_requests, run_time, max_requests / run_time);
00446         
00447         octstr_destroy(url);
00448 
00449     } else {
00450         output = xmlrpc_print_call(msg);
00451         if (output != NULL) {
00452             octstr_print(stderr, output);
00453             octstr_destroy(output);
00454         }
00455     }
00456 
00457     counter_destroy(counter);
00458     octstr_destroy(auth_username);
00459     octstr_destroy(auth_password);
00460     octstr_destroy(ssl_client_certkey_file);
00461     octstr_destroy(extra_headers);
00462     octstr_destroy(content_file);
00463 
00464 
00465     xmlrpc_destroy_call(msg);
00466     octstr_destroy(xml_doc);
00467 
00468     gwlib_shutdown();
00469 
00470     return 0;
00471 }
00472 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.